Reputation: 117
Lazy loading for one to many does not work
I have the following Order entity
@Data
@Entity
@EqualsAndHashCode
@Table(name = Order.TABLE_NAME)
public class Order implements Serializable {
private static final long serialVersionUID = -7036337819884484941L;
@Column(name = OrderNames.ORDER_ID)
private String orderId;
@Column
private String name;
@JsonManagedReference
@ToString.Exclude
@OneToMany(mappedBy = "order", cascade = CascadeType.ALL, fetch = FetchType.LAZY)
private Set<OrderItem> orderItem = new HashSet<>();
and I have another entity OrderItem
@Data
@Entity
@EqualsAndHashCode(callSuper = true, exclude = "order")
@Table(name = OrderItemNames.TABLE_NAME)
public class OrderItem implements Serializable {
private static final long serialVersionUID = -7036337819884484941L;
@Column(name = OrderItemNames.ORDER_ID)
private String orderId;
@Column(name = OrderItemNames.ORDER_ITEM_ID)
private String orderItemId;
@JsonBackReference
@ToString.Exclude
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = OrderItemNames.ORDER_FK, nullable = false)
private Order order;
Here is my repository
@Repository
public interface OrderRepository extends JpaRepository<Order, String> {
Order findByOrderId(String orderId);
}
And here is my ServiceImpl
@Override
public Order findByOrderId(String orderId) {
Order order = orderRepository.findByOrderId(orderId);
return order;
}
From my understanding, if I debug on the orderRepository.findByOrderId, I expect it will only show Order entity (without OrderItem) because the fetch type is lazy
But the actual result is eager and the order has the orderItem entity as well regardless if I do it eagerly / lazily.
I have followed this as well https://stackoverflow.com/a/37727206/6460497 but to no avail. Do I miss something regarding the ToString or @EqualsAndHashCode ?
EDIT:
I turned on the SQL logging and it does 2 queries (select the order table and then select the orderItem table). This happens on both eager and lazy loading.
I also tried to remove lombok @Data and use @Getter @Setter create my own equal hashCode and toString, but it still load the data even if i set it to lazy.
Here is my properties to postgreSql
spring.jpa.database=postgresql
spring.jpa.database-platform=org.hibernate.dialect.PostgreSQLDialect
spring.jpa.show-sql=false
spring.jpa.hibernate.ddl-auto=none
spring.jpa.hibernate.naming.physical-strategy=org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl
spring.jpa.properties.hibernate.default_schema=public
spring.jpa.properties.hibernate.show_sql=true
spring.jpa.open-in-view = false
hibernate.show_sql=true
hibernate.dialect=org.hibernate.dialect.PostgreSQLDialect
hibernate.format_sql=true
hibernate.hbm2ddl.auto=
spring.datasource.url=jdbc:postgresql://localhost:5432/postgres
spring.datasource.username=username
spring.datasource.password=password
Upvotes: 2
Views: 3293
Reputation: 145
There is a high chance Order is getting initialized when getOrderItems()
is called while debugging if OpenEntityManagerInView
interceptor is configured.
To turn this off in spring boot project you can use the following option in your application.properties
file.
spring.jpa.open-in-view=false
You can check whether Order is getting fetched with a SQL JOIN
query or with a different SELECT
query by enabling <property name="show_sql">true</property>
in your persistent.xml
or
by using the following if using spring boot.
spring.jpa.properties.hibernate.show_sql=true
You can see a sample for testing the scenario in this repository.
Upvotes: 2
Reputation: 117
I have found the answer by adding the following properties
spring.jpa.open-in-view = false
Also I found out that because I am debuging the entity, it seems that it does eager loading where actually it works as expected (lazy).
@Override
public Order findByOrderId(String orderId) {
Order order = orderRepository.findByOrderId(orderId);
return order;
}
say i put a debug point at
return order;
at this point, the db only do one query (for order) and then I lookup the entity like this then only hibernate do the query for the child entity.
Upvotes: -1