我有三张桌子
示例
Table1 -> Car
Table2 -> Brand
Table3 -> Parameters
Table 3 -> Model
汽车与品牌和参数具有一对多的关系
品牌与型号是一对多的关系
@NamedEntityGraph(
name = "graph-a",
attributeNodes = {
@NamedAttributeNode("brand"),
@NamedAttributeNode("parameters")
}
)
@Data
@Entity
@Table(name = "CAR")
public class CAR {
@Id
private long carId;
private String name;
@OneToMany(fetch = FetchType.LAZY, cascade = CascadeType.ALL, mappedBy = "car")
private Set<Brand> brands;
@OneToMany(fetch = FetchType.LAZY, cascade = CascadeType.ALL, mappedBy = "car")
private Set<Params> params = new HashSet<>();
}
@NamedEntityGraph(
name = "graph-with-children",
attributeNodes = {
@NamedAttributeNode("models"),
}
)
@Data
@Entity
@Table(name = "BRAND")
public class BRAND {
@EmbeddedId
private BRANDID id;
@OneToMany(fetch = FetchType.LAZY, cascade = CascadeType.ALL, mappedBy = "brands")
private Set<MODEL> models;
@ManyToOne(fetch=FetchType.LAZY)
@JoinColumn(name = "CAR_ID", insertable = false, updatable = false)
private Car car;
}
@Data
@Entity
@Table(name = "MODEL")
public class MODEL {
@EmbeddedId
private ModelId id;
@ManyToOne(fetch=FetchType.LAZY)
@JoinColumns({
@JoinColumn(name = "BRAND_ID", referencedColumnName = "BRAND_ID", insertable = false, updatable = false),
@JoinColumn(name = "CAR_ID", referencedColumnName = "CAR_ID", insertable = false, updatable = false)
})
private BRAND brands;
}
我的存储库方法是
@Override
@EntityGraph(value = "graph-a")
Optional<Car> findById(Long carId);
当我运行此代码时,我可以获得汽车详细信息、品牌详细信息,但不能获取型号详细信息
当我执行brand.getModels()时,它会抛出异常
Unable to evaluate the expression Method threw 'org.hibernate.LazyInitializationException'
exception.
在我看来,出现这个问题的原因是当findById的EntityGraph注解中没有指定Model时,或者findById的事务范围仅适用于该查询时,Hibernate无法执行延迟加载。 我认为您可以尝试以下解决方案:
在您的存储库中,使用更新后的图表:
@NamedEntityGraph(
name = "graph-a-with-models",
attributeNodes = {
@NamedAttributeNode("brand"),
@NamedAttributeNode("parameters"),
@NamedAttributeNode(value = "brands", subgraph = "brand-subgraph")
},
subgraphs = {
@NamedSubgraph(
name = "brand-subgraph",
attributeNodes = @NamedAttributeNode("models")
)
}
)
@Override
@EntityGraph(value = "graph-a-with-models")
Optional<Car> findById(Long carId);
@Service
@Transactional
public class CarService {
public Car getCarWithDetails(Long carId) {
Car car = carRepository.findById(carId)
.orElseThrow(() -> new CarNotFoundException("Car not found"));
for (Brand brand : car.getBrands()) {
brand.getModels(); // Lazy loading occurs inside the transaction
}
return car;
}
}
我希望我的预测和演示是正确的