一对多延迟加载不适用于休眠和龙目岛

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)