Java Hibernate:动态连接多个表
我是新加入Hibernate的,我正在尝试动态加入更多的表。我用三个表构建了一个示例:Employee、Address、Country。我想找回某个国家的所有员工。这里是我的配置文件:Java Hibernate:动态连接多个表,java,hibernate,join,criteria,hibernate-criteria,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>
<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>
我得到了正确的结果,但我的目标不是手动指定起始表和筛选表之间的整个路径:我希望hibernate为我完成这项工作。我想这样写:
List employees = session.createCriteria("Employee")
.createCriteria("country")
.add(Restrictions.eq("code","IT"))
.list();
但是我得到了错误信息
org.hibernate.QueryException: could not resolve property: country of: Employee
Hibernate只是一个用于隐藏SQL表达式的包装器或抽象层 在您的工作示例中,Hibernate构建了一个SQL select语句,创建双连接并返回所需的输出。您正在向Hibernate提供如何过滤关联表的“知识”。与编写自己的SQL语句相同 但在第二个示例中,您希望Hibernate从第一个表中猜测第二级关联。Hibernate只需查找表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>
按家庭或业务地址或两者筛选国家/地区?
或者想象一下这样一种情况,即通过每个表中的id字段进行过滤
总而言之:Hibernate不能变魔术,它只是用来隐藏原始SQL。如果我将您的查询翻译成Java语言,您要做的就是直接从employee获得coutry的价值。但在Java中,可能会出现编译错误。这样的东西在Java、Hibernate或普通SQL中都不会自动工作。员工和国家/地区之间没有直接链接,但有一系列链接:员工->地址->国家/地区 为了用Java方式解决这个问题,可以直接从employee获得对country的二次引用。然后调用employee.getAddress().getCountry()和employee.getCountry()将相等 要在hibernate中实现这一点,您需要向Employee添加新的field country,并使用entity Address将其映射为与entity country的不可修改的多对多关系。这只会将2个hibernate连接减少为一个,不能重复应用于2个以上的连接
如果此解决方案适合您,我可以为您提供示例语法。好的,我理解您的比较。关键是Hibernate有一个查询(生成器)引擎,但它不能像我想象的那样动态地找到图中两个实体之间的路径。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>
List employees = session.createCriteria("Employee")
.createCriteria("country")
.add(Restrictions.eq("code","IT"))
.list();