Hibernate - OneToMany 注释导致选择查询的左连接不匹配

Posted

技术标签:

【中文标题】Hibernate - OneToMany 注释导致选择查询的左连接不匹配【英文标题】:Hibernate - OneToMany annotation resulting in select query with mismatched left join 【发布时间】:2017-09-18 03:36:06 【问题描述】:

我有三个表,表 1 和表 2 之间以及表 2 和表 3 之间存在一对多关系。

Table1 具有包含两列的复合主键 - Col_A 和 Col_B

表1

Col_A Col_B ....其他列

Table2 具有复合主键,包含三列 Col_A、Col_B 和 Col_C。 Col_A 和 Col_B 值来自 Table1,但数据库架构中没有定义外键关系(这是一个旧的遗留数据库......由于数据问题,我现在无法添加约束)

表2

Col_A Col_B Col_C ---其他栏目

Table3 具有包含四列的复合主键。同样,表 2 和表 3 之间没有外键关系。

表3

Col_A

Col_B

Col_C

Col_D

----其他栏目

我已经通过以下方式定义了我的域对象映射..

ClassOne

    @Id
    @EmbeddedId
    private TableOneId id;

    @OneToMany(fetch = FetchType.EAGER, cascade = CascadeType.ALL, mappedBy = "classOne")  
    private Set<ClassTwo> classTwoList = new HashSet<ClassTwo>(0); 



 TableOneId
     //I've omitted the column name annotations for simplicity
      private String colA;
      private String colB;


ClassTwo

    @Id
    @EmbeddedId
    private TableTwoId id;

    @OneToMany(fetch = FetchType.EAGER, cascade = CascadeType.ALL, mappedBy = "classTwo")  
    private Set<ClassThree> classTwoList = new HashSet<ClassThree>(0); 

    @ManyToOne
    @JoinColumns(
       @JoinColumn(name="COL_A",insertable=false, updatable=false),
       @JoinColumn(name="COL_B",insertable=false, updatable=false) 
    )
    private ClassOne classOne;


 TableTwoId
      private String colA;
      private String colB;
      private String colC;



ClassThree

    @Id
    @EmbeddedId
    private TableThreeId id;

    @ManyToOne
    @JoinColumns(
       @JoinColumn(name="COL_A",insertable=false, updatable=false),
       @JoinColumn(name="COL_B",insertable=false, updatable=false) ,
       @JoinColumn(name="COL_C",insertable=false, updatable=false)
    )
    private ClassTwo classTwo;


 TableThreeId
      private String colA;
      private String colB;
      private String colC;
      private String colD;

通过上述映射配置,向三个表中的插入按预期工作。当我调用 session.save(classOne) 时,我可以看到记录被插入到所有三个表中。

但是当我从 DB 中检索 ClassOne 时,生成的 select SQL 留下了不正确的列..

ClassOne classOne = (ClassOne )session.get(ClassOne .class, id);

select **** from Table1 t1 left join Table2 t2 on t1.col_a = t2.col_a 和 t1.col_b = t2.col_b 在 t2.col_a = t3.col_a 上左加入 Table3 t3 和 t2.col_b = t3.col_ct2.col_c = t3.col_b

正如您在上面看到的,t2 和 t3 之间的左连接有错误的列关联。我该如何解决这个问题?

【问题讨论】:

你能在TableTwoIdTableThreeId上显示注释吗?顺便说一句,很好地描述了问题。 @Rafa..感谢您的补充。我通过在@JoinColumn 注释中指定referencedColumnName 属性解决了这个问题 【参考方案1】:

我找到了解决办法..

我在 JoinColumn 中添加了 referenceColumn 属性,问题已经消失。我可以看到 Hibernate SQL 具有正确的左连接关联。

ClassTwo

    @Id
    @EmbeddedId
    private TableTwoId id;

    @OneToMany(fetch = FetchType.EAGER, cascade = CascadeType.ALL, mappedBy = "classTwo")  
    private Set<ClassThree> classTwoList = new HashSet<ClassThree>(0); 

    @ManyToOne
    @JoinColumns(
       @JoinColumn(name="COL_A",insertable=false, updatable=false, referencedColumnName="COL_A"),
       @JoinColumn(name="COL_B",insertable=false, updatable=false,referencedColumnName="COL_B") 
    )
    private ClassOne classOne;



ClassThree

    @Id
    @EmbeddedId
    private TableThreeId id;

    @ManyToOne
    @JoinColumns(
       @JoinColumn(name="COL_A",insertable=false, updatable=false, referencedColumnName="COL_A"),
       @JoinColumn(name="COL_B",insertable=false, updatable=false, referencedColumnName="COL_B") ,
       @JoinColumn(name="COL_C",insertable=false, updatable=false, referencedColumnName="COL_C")
    )
    private ClassTwo classTwo;

现在生成的 SQL 看起来像

select **** from Table1 t1 left join Table2 t2 on t1.col_a = t2.col_a 和 t1.col_b = t2.col_b 在 t2.col_a = t3.col_a 上左加入 Table3 t3 和 t2.col_b = t3.col_b 和 t2.col_c = t3.col_c

【讨论】:

以上是关于Hibernate - OneToMany 注释导致选择查询的左连接不匹配的主要内容,如果未能解决你的问题,请参考以下文章

使用带有 Hibernate 的 JPA 注释来描述外键仅在子表中的 @OneToMany 关系

休眠 OneToMany 和 ManyToOne?

JPA(休眠)映射OneToMany不正确?

(原创)hibernate 一对多建表实例详解 附上各个注释的含义

Hibernate - OneToMany - 多列

Hibernate 从 onetomany 中删除