论坛首页 Java企业应用论坛

Hibernate 隐含关联(implicit joins)的变化

浏览 2251 次
精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
作者 正文
   发表时间:2007-12-05  
前一个关于这个问题的帖子被隐藏了,这次说明确些。
例如有两个类,员工TestEmployee 和部门TestDept,它们是ManyToOne关系:
@Entity
@Table(name = "test_employees", uniqueConstraints = { })
public class TestEmployee extends BaseModel implements Serializable {
  private Integer id;
  private TestDept dept;

  @Id
  @GeneratedValue(generator = "hilo")
  @GenericGenerator(name = "hilo", strategy = "hilo")
  @Column(name = "ID", unique = true, nullable = false)
  public Integer getId() {
    return this.id;
  }

  public void setId(Integer id) {
    this.id = id;
  }

  @ManyToOne(cascade = { }, fetch = FetchType.LAZY)
  @JoinColumn(name = "dept_id")
  public TestDept getDept() {
    return this.dept;
  }

  public void setDept(TestDept dept) {
    this.dept = dept;
  }
}
@Entity
@Table(name = "test_depts", uniqueConstraints = { })
public class TestDept extends BaseModel implements Serializable {
  
  private Integer id;
  private String name;
  private Set<TestEmployee> employees = new HashSet<TestEmployee>(0);

  @Id
  @GeneratedValue(generator = "hibseq")
  @GenericGenerator(name = "hibseq", strategy = "hilo")
  @Column(name = "ID", unique = true, nullable = false)
  public Integer getId() {
    return this.id;
  }

  public void setId(Integer id) {
    this.id = id;
  }


  @Column(name = "name")
  public String getName() {
    return this.name;
  }

  public void setName(String name) {
    this.name = name;
  }

  @OneToMany(cascade = { }, fetch = FetchType.LAZY, mappedBy = "dept")
  public Set<TestEmployee> getEmployees() {
    return this.employees;
  }

  public void setEmployees(Set<TestEmployee> employees) {
    this.employees = employees;
  }
}

现在我要查询员工A所在的部门,使用隐含关联:
getHibernateTemplate().find(
        "from TestDept d where d.employees.name = 'A'");

如果使用Hibernate3.2.3以后的版本,会出现一个异常illegal attempt to dereference collection。这个问题比较容易解决,只需要明确的关联上employees即可:
getHibernateTemplate().find(
        "from TestDept d inner join d.employees e where e.name = 'A'");

可是,如果使用Hibernate3.2.2,即使使用隐含关联也不会有问题。我的问题是:现在升级为Hibernate3.2.5,以前的代码怎么办?这是Hibernate的Bug吗?
从Hibnerate的Jira上终于得到了答案:
对于implicit joins,Hibernate3.2.2会自动生成inner join,这样,被关联对象如果为null,就不会查出任何结果。这使得隐含关联更具确定性(原文:This makes implicit joins more deterministic. )。
Hibernate3.2.2之后如果隐含关联的是一个Collection,那么Hibernate就会抛出那个异常。这会提醒用户,使用更加明确的关联。
终于弄清问题所在了,可是以前的代码都得改,JUnit测出了40多个Bugs,郁闷呀!

   发表时间:2007-12-05  
你给的代码:
getHibernateTemplate().find("from TestDept d where d.employees.name = 'A'");  

Hibernate从来没有说过HQL可以这样用,因为employees是TestDept对应的一个集合,集合没有name这个属性。
在3.1~3.2中某几个版本有bug,能够让你这样的查询能生效,如果你要升级,只能一个一个地修改了。

你昨天被隐藏帖子说的是类似这样的查询:
getHibernateTemplate().find("from TestEmployee e where e.testDept.name = 'B'");  

这样的HSQL是一直可以生效的,不会出现你说的问题。
0 请登录后投票
   发表时间:2007-12-05  
Readonly 写道
你给的代码:
getHibernateTemplate().find("from TestDept d where d.employees.name = 'A'");  

Hibernate从来没有说过HQL可以这样用,因为employees是TestDept对应的一个集合,集合没有name这个属性。
在3.1~3.2中某几个版本有bug,能够让你这样的查询能生效,如果你要升级,只能一个一个地修改了。

你昨天被隐藏帖子说的是类似这样的查询:
getHibernateTemplate().find("from TestEmployee e where e.testDept.name = 'B'");  

这样的HSQL是一直可以生效的,不会出现你说的问题。

是的,这个问题困扰我很久了,所以昨天又问了一次,还吧代码贴错了,惭愧。
0 请登录后投票
论坛首页 Java企业应用版

跳转论坛:
Global site tag (gtag.js) - Google Analytics