如何强制Hibernate使用连接来获取实例的数据?



我有一个使用Hibernate作为JPA提供者的Spring Boot应用程序。我的应用程序有两个与@OneToMany/@ManyToOne关系连接的实体。在两个方向上都标注了@Fetch(FetchMode.JOIN)fetch = FetchType.EAGER的关系。

我的实体被称为CarDriver:

@Entity
@Table(name = "car")
@Data
public class Car implements Serializable, Cloneable {
@Id
@GenericGenerator(name = "car_seq", strategy = "org.hibernate.id.enhanced.SequenceStyleGenerator", parameters = {
@Parameter(name = "sequence_name", value = "car_seq") })
@GeneratedValue(generator = "car_seq")
private Integer id;

@OneToMany(mappedBy = "car", fetch = FetchType.EAGER)
@Fetch(FetchMode.JOIN)
private List<Driver> drivers = new ArrayList<>();

@Column(name = "license_no", nullable = false)
private String licenseNo;
}
@Entity
@Table(name = "driver")
@Data
public class Driver implements Serializable, Cloneable {
@Id
@GenericGenerator(name = "driver_seq", strategy = "org.hibernate.id.enhanced.SequenceStyleGenerator", parameters = {
@Parameter(name = "sequence_name", value = "driver_seq") })
@GeneratedValue(generator = "driver_seq")
private Integer id;

@ManyToOne(fetch = FetchType.EAGER)
@JoinColumn(name = "car_id", nullable = true)
@Fetch(FetchMode.JOIN)
private Car car;

@Column(name = "name", nullable = false)
private String name;
}

当选择一个care(例如通过调用Car.findById())时,Hibernate在一个SQL中连接两个表,并返回一个Car对象和一个Drivers列表。

但是,如果我选择一个驱动程序,Hibernate将连接DriverCar表,以给我Driver对象,并填充Car属性,但它将运行第二个查询来获取汽车对象列表上的所有驱动程序对象。

出于性能原因,我希望在单个查询中获取所有涉及的对象,就像我获取汽车的情况一样。但是我找不到让Hibernate做到这一点的方法。有一个属性,hibernate.max_fetch_depth,应该这样做,但我发现它只影响取车的行为,而不是当我取司机。

我知道我可以使用EntityGraph来控制抓取,并且通过使用EntityGraph,我已经成功地在一个查询中检索了具有其汽车和所有汽车驾驶员的驾驶员对象。但是要做到这一点,我必须在检索对象时显式地使用图,并且我不能在需要Car对象的所有各种情况下都这样做。还有很多其他实体与Car有关系,我不想为每一个实体都写一个EntityGraph

那么是否有一种方法可以告诉Hibernate您希望如何在默认情况下对实体进行抓取?我本以为有注释就足够了,但似乎还需要更多的东西,或者根本无法做到这一点。

阿恩特

FetchType.EAGER是性能问题最常见的原因之一。你应该使用

@OneToMany(mappedBy = "car")
private List<Driver> drivers = new ArrayList<>();

和获取驱动程序如果需要

SELECT c FROM Car c JOIN FETCH c.drivers

最新更新