【问题标题】:Hibernate: dynamic join multiple tablesHibernate:动态连接多个表
【发布时间】:2014-11-03 14:30:26
【问题描述】:

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

【问题讨论】:

    标签: java hibernate join criteria hibernate-criteria


    【解决方案1】:

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

    在您的工作示例中,Hibernate 构建一个 SQL 选择语句,创建一个双重 JOIN 并返回所需的输出。您正在为 Hibernate 提供如何过滤关联表的“知识”。就像您编写自己的 SQL 语句一样。

    但是在您的第二个示例中,您希望 Hibernate 从第一个表中猜测第二级关联。如果表 Employee 有一个列/外键国家,Hibernate 只是查找它并且找不到它。所以错误是:could not resolve property: country of: Employee

    你不能指望 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>
    

    两者都会有一个 Country 链接...如果这个查询休眠应该怎么办?

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

    homebusiness 地址或两者过滤国家? 或者想象一下,您通过每个表中存在的 id 字段进行过滤。

    总结一下:Hibernate 不能做魔法,它只是隐藏原始 SQL。

    【讨论】:

      【解决方案2】:

      如果我将您的查询翻译成 Java 语言,那么您要做的就是直接从员工那里获得国家的价值。但是在 Java 中你会得到一个编译错误。这样的事情在 Java、Hibernate 或普通 SQL 中都不起作用。员工和国家之间没有直接的联系,但是有一系列联系员工 -> 地址 -> 国家。

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

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

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

      【讨论】:

      • 好的,我理解你的比较。关键是 Hibernate 有一个查询(构建器)引擎,但它不能像我想象的那样动态地找到图中两个实体之间的路径。
      • 你是对的。 Hibernate 需要在查询中加入一个从员工到国家的路径通过地址实体
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-10-08
      相关资源
      最近更新 更多