2014-11-03 78 views
0

我是Hibernate的新手,我试图动态加入更多的表。我用三个表格构建了一个例子:员工,地址,国家。我想检索某个国家的所有员工。在这里我的配置文件:休眠:动态连接多个表

<class entity-name="Employee"> 
     <id name="id" type="int" column="id"> 
      <generator class="native"/> 
     </id> 
     <property name="firstName" column="first_name" type="string"/> 
     <property name="lastName" column="last_name" type="string"/> 
     <property name="salary" column="salary" type="int"/> 

     <many-to-one name="address" column="address" unique="true" 
        class="Address" not-null="true"/> 
    </class> 

    <class entity-name="Address"> 
     <id name="id" type="int" column="id"> 
      <generator class="native"/> 
     </id> 
     <property name="street" column="street_name" type="string"/> 
     <property name="city" column="city_name" type="string"/> 
     <property name="state" column="state_name" type="string"/> 
     <property name="zipcode" column="zipcode" type="string"/> 

     <many-to-one name="country" column="country" unique="true" 
        class="Country" not-null="true"/> 
    </class> 

    <class entity-name="Country"> 
     <id name="id" type="int" column="id"> 
      <generator class="native"/> 
     </id> 
     <property name="name" column="name" type="string"/> 
     <property name="code" column="code" type="string"/> 
    </class> 

如果我做

List employees = session.createCriteria("Employee") 
      .createCriteria("address") 
      .createCriteria("country") 
      .add(Restrictions.eq("code","IT")) 
      .list(); 

我得到正确的结果回来,但我的目标不是要手动指定开始表和筛选器表之间的整个路径:我想是休眠为我工作。我想编写这样的事:

List employees = session.createCriteria("Employee") 
      .createCriteria("country") 
      .add(Restrictions.eq("code","IT")) 
      .list(); 

,但我得到的错误信息

org.hibernate.QueryException: could not resolve property: country of: Employee 

回答

1

Hibernate是只是一个包装或抽象层遁形SQL表达式。

在您的工作示例的Hibernate构建一个SQL SELECT语句创建一个双JOIN和返回所需的输出。您正在向Hibernate提供如何过滤关联表的“知识”。和你自己写SQL语句一样。

但是在你的第二个例子中,你希望Hibernate从第一个表猜测第二级关联。如果表雇员有一个列/外键国家,它没有找到它,休眠只是查找。所以错误是:无法解决属性:国家:员工

你不能指望从Hibernate做这种魔术,因为它会产生或排序错误的查询。

只是为了说明你的例子。

如果你的员工将有类型地址的两个领域:

<class entity-name="Employee"> 
     <id name="id" type="int" column="id"> 
      <generator class="native"/> 
     </id> 
     <property name="firstName" column="first_name" type="string"/> 
     <property name="lastName" column="last_name" type="string"/> 
     <property name="salary" column="salary" type="int"/> 

     <many-to-one name="bussiness_address" column="bussiness_address" unique="true" 
        class="Address" not-null="true"/> 
     <many-to-one name="home_address" column="home_address" unique="true" 
        class="Address" not-null="true"/> 
    </class> 

双方将有一个国家联系......我应该在此查询的情况下冬眠吗?

List employees = session.createCriteria("Employee") 
      .createCriteria("country") 
      .add(Restrictions.eq("code","IT")) 
      .list(); 

业务地址或两个过滤器的国家吗? 或者想象一下,您在每个表格中都会显示id字段。

所以包东西:Hibernate无法使用魔法,只有在这里躲远原始的SQL。

1

如果我翻译查询到Java语言,你正在试图做的是越来越coutry的价值直接从员工的。在Java中,你会得到一个编译错误。这种东西在Java,Hibernate或普通SQL中都不会自动工作。员工和国家之间没有直接联系,但员工 - >地址 - >国家有一系列链接。

要以Java方式解决此问题,可以直接从员工维护对国家的次要引用。然后调用employee.getAddress()。getCountry()和employee.getCountry()将是平等的。

为了在hibernate中实现这一点,您需要向Employee添加新的字段国家,并将其映射为与实体Country不可修改的多对多关系,使用实体Address映射关系。这只会将2个hibernate联接减少到1个,它不能反复应用于超过2个联接。

如果这个解决方案对您来说可以,我可以为您提供示例语法。

+0

好的,我理解你的比较。关键是Hibernate有一个查询(构建器)引擎,但它不能像我所想的那样动态地在图中的两个实体之间找到路径。 – Zardo 2014-11-11 09:55:30

+0

你是对的。 Hibernate需要在查询中加入一个从员工到国家/地区实体的路径 – OndrejM 2015-01-07 11:19:19