【问题标题】:JPA join multiple table one to many and one to oneJPA 一对多和一对一连接多个表
【发布时间】:2020-05-25 17:17:11
【问题描述】:

我在 Oracle DB 上有这 4 个表

FACTORY_MASTER

FACTORY_DETAILS

LOT_MASTER

很多细节

关系

FACTORY_MASTER 1 - N FACTORY_DETAILS

LOT_MASTER 1 - N LOT_DETAILS

FACTORY_DETAILS 1 - 1 LOT_DETAILS

这是模型类的当前实现

public class FactoryMaster {

    @Id
    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "factory_master_gen")
    @SequenceGenerator(name = "factory_master_gen", sequenceName = "seq_factory_master")
    @Column(name = "FACTORY_MASTER_ID")
    private Long id;

    @OneToMany(cascade = CascadeType.ALL,
               orphanRemoval = true,
               fetch = FetchType.LAZY)
    @JoinColumn(name = "FACTORY_MASTER_ID",
                referencedColumnName = "FACTORY_MASTER_ID",
                nullable = false)
    private List<FactoryDetail> details;

}

public class FactoryDetail {

    @Id
    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "factory_detail_gen")
    @SequenceGenerator(name = "factory_detail_gen", sequenceName = "seq_factory_detail")
    @Column(name = "FACTORY_DETAIL_ID")
    private Long id;

    // I exclude on purpose ManyToOne, because you cannot have FactoryDetail without a Master

    @OneToOne(mappedBy = "factoryDetail")
    private LotDetail lotDetail;

}

public class LotMaster {

    @Id
    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "lot_master_gen")
    @SequenceGenerator(name = "lot_master_gen", sequenceName = "seq_lot_master")
    @Column(name = "LOT_MASTER_ID")
    private Long id;

    @OneToMany(cascade = CascadeType.ALL,
               orphanRemoval = true,
               fetch = FetchType.LAZY)
    @JoinColumn(name = "LOT_MASTER_ID",
                referencedColumnName = "LOT_MASTER_ID",
                nullable = false)
    private List<LotDetail> details;

}

public class LotDetail {

    @Id
    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "lot_detail_gen")
    @SequenceGenerator(name = "lot_detail_gen", sequenceName = "seq_lot_detail")
    @Column(name = "LOT_DETAIL_ID")
    private Long id;

    @OneToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "FACTORY_DETAIL_ID",
                referencedColumnName = "FACTORY_DETAIL_ID")
    private FactoryDetail factoryDetail;
}

我需要使用 lot_master_id

提取 factory_master

所以查询是

select distinct fm.*
  from factory_master fm
       join factory_details fd on fd.factory_master_id = fm.factory_master_id
       join lot_details ld on fd.lot_details_id = ld.lot_details_id
       join lot_master lt on ld.lot_master_id = lt.lot_master_id 
 where lt.lot_master_id = :ID

如何通过 JPQL valid 得到同样的结果?

谢谢

【问题讨论】:

    标签: spring hibernate jpa hql jpql


    【解决方案1】:

    可能使用这样的交叉连接会有所帮助:

    select distinct fm 
    from
    
    FactoryMaster fm 
        inner join fm.details fd 
        inner join fd.lotDetail ld1
    
    ,LotMaster lm 
        inner join lm.details ld2 
    
    where 
        ld2.id = ld1.id
        and
        lm.id = :lotMasterId
    

    【讨论】:

    • 替代交叉连接?由于我在 LotMaster 和 LotDetails 之间获得了一对多的关系,因此可以通过子节点加入而不添加双向映射 - manyToOne,因此在 LotDetails 中添加父节点谢谢
    • 上述查询不需要在FactoryDe​​tail中添加FactoryMaster(即多对一双向映射)。事实上,如果你这样做了,那么你就不需要交叉连接了。然后,您可以使用以下方法实现要求: select distinct fm from LotMaster lm inner join lm.details ld inner join ld.factoryDe​​tail fd inner join fd.factoryMaster fm where lm.id = :lotMasterId
    • 使用建议的查询(不是 CrossJoin)我必须按照你所说的设置多对一的双向映射,但是如果没有 Master,我就不能拥有 FactoryDe​​tail,这就是我在开始双向映射后排除的原因.如果实现的唯一方法是交叉连接,我会这样做
    • 从性能角度来看,交叉连接被认为是不好的。在 LotDetails 中添加 LotMaster 不会花费太多。因此,更好的方法是采用双向方式并仅使用内部连接来使用查询。
    • 但是,即使我想避免双向,因为我不需要双向导航访问和其他性能风险似乎是唯一的解决方案谢谢您的帮助
    【解决方案2】:
    @Query(value = "select distinct fm.*from factory_master fm
    join factory_details fd on fd.factory_master_id = fm.factory_master_id
    join lot_details ld on fd.lot_details_id = ld.lot_details_id
    join lot_master lt on ld.lot_master_id = lt.lot_master_id 
    where lt.lot_master_id =:#{#Id}", nativeQuery = true)
    List<FactoryMaster > getFactoryMaster(@Param("Id")Long Id);
    
    
    u can use like this
    

    【讨论】:

    • 不使用原生查询,可以吗?
    • 是的,您可以提及本机查询=false
    • HQL?你能举个例子吗?谢谢?
    猜你喜欢
    • 2021-08-23
    • 2018-10-31
    • 1970-01-01
    • 2021-09-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-10-14
    • 2016-09-27
    相关资源
    最近更新 更多