Hibernate:动态连接多个表

时间:2014-11-03 14:30:26

标签: java hibernate join criteria hibernate-criteria

我是Hibernate的新手,我试图动态加入更多的表格。我已经构建了一个包含三个表的示例:Employee,Address,Country。我想要检索某个国家/地区的所有员工。这是我的配置文件:

 <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();

我得到了正确的结果,但我的目标不是手动指定启动表和过滤器表之间的整个路径:我希望hibernate为我完成工作。我想写这样的东西:

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

但我收到错误消息

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

2 个答案:

答案 0 :(得分:1)

Hibernate只是一个隐藏SQL表达式的包装器或抽象层。

在您的工作示例中,Hibernate构建一个SQL select语句,创建一个双JOIN并返回所需的输出。你正在为Hibernate提供&#34;知识&#34;如何过滤关联的表。与编写自己的SQL语句一样。

但在第二个例子中,你希望Hibernate从第一个表中猜出第二级关联。如果表 Employee 有一个列/外键国家,Hibernate只会查找,但无法找到它。所以错误是:无法解析属性:country of:Employee

你不能指望Hibernate能够做出这样的魔法,因为它会产生或者出现各种错误的查询。

只是为了说明你的例子。

如果您的员工有两个类型为Address的字段:

<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>

两者都有一个国家链接...如果这个查询hibernate会怎么做?

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

主页商家地址或两者来过滤国家/地区? 或者想象一下你通过每个表中存在的 id 字段进行过滤的情况。

所以要把事情搞砸:Hibernate不能做魔术只是为了隐藏原始SQL。

答案 1 :(得分:1)

如果我将您的查询翻译成Java语言,那么您要做的就是直接从员工那里获得价值。在Java中,您会遇到编译错误。这样的东西在Java,Hibernate或普通SQL中都不会自动起作用。员工与国家之间没有直接联系,但是员工有一系列的链接 - &gt;地址 - &gt;国家。

要以Java方式修复此问题,可以直接从员工处获得对国家的二级引用。然后调用employee.getAddress()。getCountry()和employee.getCountry()将是相等的。

要在hibernate中实现此目的,您需要向Employee添加新的字段country,并将其映射为与实体Country的不可修改的多对多关系,使用实体Address映射关系。这只会将2个休眠连接减少到1个,它不能反复应用于2个以上的连接。

如果此解决方案适合您,我可以为您提供示例语法。