一对多延迟加载不适用于休眠和龙目岛
lazy loading for one to many does not work for hibernate and lombok
一对多的延迟加载不起作用
我有以下订单实体
@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<>();
我还有另一个实体 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;
这是我的存储库
@Repository
public interface OrderRepository extends JpaRepository<Order, String> {
Order findByOrderId(String orderId);
}
这是我的 ServiceImpl
@Override
public Order findByOrderId(String orderId) {
Order order = orderRepository.findByOrderId(orderId);
return order;
}
据我了解,
如果我在 orderRepository.findByOrderId 上调试,我希望它只会显示订单实体(没有 OrderItem),因为获取类型是惰性的
但实际结果是急切的,订单也有 orderItem 实体,无论我是急切还是懒惰。
我也遵循了这个 但无济于事。
我是否遗漏了有关 ToString 或 @EqualsAndHashCode 的内容?
编辑:
我打开了 SQL 日志记录,它进行了 2 次查询(select 订单 table 然后 select orderItem table)。这种情况发生在急切加载和延迟加载上。
我还尝试删除 lombok @Data 并使用 @Getter @Setter 创建我自己的相等 hashCode 和 toString,但即使我将其设置为惰性,它仍会加载数据。
这是我的 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
如果配置了 OpenEntityManagerInView
拦截器,调试时调用 getOrderItems()
时很有可能会初始化订单。
要在 spring 引导项目中关闭此功能,您可以在 application.properties
文件中使用以下选项。
spring.jpa.open-in-view=false
您可以通过启用 <property name="show_sql">true</property>
检查订单是使用 SQL JOIN
查询还是使用不同的 SELECT
查询获取
在您的 persistent.xml
或
如果使用 spring boot.
,则使用以下命令
spring.jpa.properties.hibernate.show_sql=true
您可以在 this repository 中查看用于测试场景的示例。
我通过添加以下属性找到了答案
spring.jpa.open-in-view = false
我还发现,因为我正在调试该实体,所以它似乎在实际按预期工作的地方进行了预加载(惰性)。
@Override
public Order findByOrderId(String orderId) {
Order order = orderRepository.findByOrderId(orderId);
return order;
}
说我把调试点放在
return order;
此时,数据库仅执行一次查询(针对订单),然后我查找实体
like this
然后只有 hibernate 对子实体进行查询。
你可以加上"order"注释
@Getter(AccessLevel.NONE)
一对多的延迟加载不起作用
我有以下订单实体
@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<>();
我还有另一个实体 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;
这是我的存储库
@Repository
public interface OrderRepository extends JpaRepository<Order, String> {
Order findByOrderId(String orderId);
}
这是我的 ServiceImpl
@Override
public Order findByOrderId(String orderId) {
Order order = orderRepository.findByOrderId(orderId);
return order;
}
据我了解, 如果我在 orderRepository.findByOrderId 上调试,我希望它只会显示订单实体(没有 OrderItem),因为获取类型是惰性的
但实际结果是急切的,订单也有 orderItem 实体,无论我是急切还是懒惰。
我也遵循了这个
编辑:
我打开了 SQL 日志记录,它进行了 2 次查询(select 订单 table 然后 select orderItem table)。这种情况发生在急切加载和延迟加载上。
我还尝试删除 lombok @Data 并使用 @Getter @Setter 创建我自己的相等 hashCode 和 toString,但即使我将其设置为惰性,它仍会加载数据。
这是我的 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
如果配置了 OpenEntityManagerInView
拦截器,调试时调用 getOrderItems()
时很有可能会初始化订单。
要在 spring 引导项目中关闭此功能,您可以在 application.properties
文件中使用以下选项。
spring.jpa.open-in-view=false
您可以通过启用 <property name="show_sql">true</property>
检查订单是使用 SQL JOIN
查询还是使用不同的 SELECT
查询获取
在您的 persistent.xml
或
如果使用 spring boot.
spring.jpa.properties.hibernate.show_sql=true
您可以在 this repository 中查看用于测试场景的示例。
我通过添加以下属性找到了答案
spring.jpa.open-in-view = false
我还发现,因为我正在调试该实体,所以它似乎在实际按预期工作的地方进行了预加载(惰性)。
@Override
public Order findByOrderId(String orderId) {
Order order = orderRepository.findByOrderId(orderId);
return order;
}
说我把调试点放在
return order;
此时,数据库仅执行一次查询(针对订单),然后我查找实体 like this 然后只有 hibernate 对子实体进行查询。
你可以加上"order"注释
@Getter(AccessLevel.NONE)