java jpa从父母,孩子和孙子表中获取详细信息

问题描述 投票:0回答:1

我有三张桌子

示例

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.
java spring-boot spring-data-jpa
1个回答
0
投票

在我看来,出现这个问题的原因是当findById的EntityGraph注解中没有指定Model时,或者findById的事务范围仅适用于该查询时,Hibernate无法执行延迟加载。 我认为您可以尝试以下解决方案:

  1. 使用实体图

在您的存储库中,使用更新后的图表:

@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);

  1. 扩大交易范围
@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;
    }
}

我希望我的预测和演示是正确的

© www.soinside.com 2019 - 2024. All rights reserved.