【问题标题】:Join tables in Hibernate在 Hibernate 中加入表
【发布时间】:2014-09-03 22:14:12
【问题描述】:

我的 PostgreSQL 数据库中有两个表:

CREATE TABLE tableOne (id int, name varchar(10), address varchar(20))
CREATE TABLE tableTwo (id int, info text, addresses varchar(20)[])

现在我想创建一个连接如下:

SELECT * FROM tableOne JOIN tableTwo ON address = ANY(addresses)

我尝试使用 Hibernate - 类 TableOne 来实现这一点:

@Entity
@Table(name = "tableOne")
class TableOne {
      private int id;
      private TableTwo tableTwo;
      private String address;

     @Id
     @Column(name = "id")
     public getId() { return id; }

     @ManyToOne
     @JoinFormula(value = "address = any(tableTwo.addresses)", 
                  referencedColumnName = "addresses")
     public TableTwo getTableTwo(){
        return tableTwo;
     }
     // Setters follow here

}

但 Hibernate 不断生成带有无意义 JOIN 子句的查询,例如:

... JOIN tableTwo ON _this.address = any(tableTwo.addresses) = tableTwo.addresses

我如何告诉 Hibernate 使用注释来正确格式化我的连接查询?不幸的是,我们的项目必须仅限于 Criteria API。

编辑:

根据下面 cmets 中 ashokhein 的建议,我只用 @ManyToOne 注释了方法 getTableTwo() - 现在我想使用 Criteria API 进行连接,大概使用 createAlias(associationPath,alias,joinType,withClause) 方法,其中 withClause 将是我在连接中的ON 子句。

但我不确定将什么作为 associationPath 和 alias 参数。

有什么提示吗?

【问题讨论】:

  • 不要在实体类中创建查询。不应允许自定义查询。
  • 你的意思是创建一个原生查询?
  • 可以使用NamedQuery,HSQL,Criteria
  • 那么如何注释getTableTwo方法呢?
  • 另一个很好的例子,说明当您需要一些可以用 SQL 完成并且超越 ORM 的东西时,Hibernate 如何变得非常烦人......谢谢! :-)

标签: java sql hibernate postgresql join


【解决方案1】:

要支持 PostgreSQL 阵列,您需要一个 custom Hibernate Type。拥有一个专用的用户类型将允许您运行本机 SQL 查询以使用该类型:

String[] values = ...
Type arrayType = new CustomType(new ArrayUserType());
query.setParameter("value", values, arrayType);

HQL supports ANY/SOME syntax 但仅适用于子查询。在您的情况下,您需要一个本机查询来针对数组值使用 PostgreSQL 特定的 ANY 子句。

【讨论】:

    【解决方案2】:

    你可以试试命名查询。

      @NamedQuery(name="JOINQUERY", query="SELECT one FROM tableOne one JOIN tableTwo two ON one.address = :address" )
      @Entity
      class TableOne{......
    

    检索部分是:

    TypedQuery<TableOne> q = em.createNamedQuery("query", TableOne.class);
    q.setParameter("address", "Mumbai"); 
    for (TableOne t : q.getResultList())
      System.out.println(t.address);
    

    您可能需要对查询进行一些排列

    【讨论】:

      【解决方案3】:

      所以经过大量时间寻找正确答案后,唯一适合我们的真正解决方案是创建视图:

      CREATE VIEW TableA_view AS SELECT TableOne.*,TableTwo.id FROM TableA JOIN TableTwo ON TableOne.address = ANY(TableTwo.addresses)
      

      并将其映射到实体TableOne 而不是原始表。 当然,这是我们唯一的解决方案,当然,使用命名查询,这是不行的,因为我们需要坚持 Criteria API。

      正如@ericbn 在 cmets 中提到的,这确实是 ORM 变得非常烦人的一个例子。我永远不会想到像这样的自定义连接子句在 Hibernate 中是不可能的。

      【讨论】:

        【解决方案4】:

        【讨论】:

        • 我认为address = any(tableTwo.addresses) 也是“一个有效的 SQL 片段”。
        猜你喜欢
        • 2023-03-27
        • 1970-01-01
        • 2017-05-11
        • 2013-07-06
        • 2017-06-17
        • 2018-08-21
        • 2020-12-25
        • 1970-01-01
        • 2016-07-07
        相关资源
        最近更新 更多