我有两个简单的映射:
<class name="org.testing.Person" table="PERSON">
<id name="personId" type="long" column="PERSON_ID">
<generator class="native"/>
</id>
<property name="personName" type="string" not-null="true" column="PERSON_NAME"/>
<many-to-one name="personAddress" class="org.testing.Address" column="PERSON_ADDRESS" not-null="true" cascade="all" unique="true"/>
</class>
和
<class name="org.testing.Address" table="ADDRESS">
<id name="addressId" type="long" column="ADDRESS_ID">
<generator class="native" />
</id>
<property name="street" column="ADDRESS_STREET" type="string" />
<property name="city" column="ADDRESS_CITY" type="string" />
<property name="state" column="ADDRESS_STATE" type="string" />
</class>
我尝试获取此人地址的属性,如下所示:
session.createCriteria(Person.class)
.add(Restrictions.eq("personName", "Frodo"))
.createAlias("personAddress", "pa")
.setProjection(Projections.property("pa.street"))
.list();
并且它有效。 比这样:
session.createCriteria(Person.class)
.add(Restrictions.eq("personName", "Frodo"))
.createCriteria("personAddress")
.setProjection(Projections.property("street"))
.list();
它抛出:
org.hibernate.QueryException: could not resolve property: street of: org.testing.Person
。我认为两者应该给出相同的结果。我哪里错了?
预先感谢!
.setProjection(Projections.property("street"))
始终按照根标准进行操作。要投影加入的项目,您必须使用您发布的第一个版本。
休眠3.3.2;
让我们看看代码源:
public Criteria createAlias(String associationPath, String alias, int joinType) {
new Subcriteria( this, associationPath, alias, joinType );
return this;
}
public Criteria createCriteria(String associationPath, int joinType) {
return new Subcriteria( this, associationPath, joinType );
}
createCriteria 返回子 Criteria,所以所有操作都在子 Criteria 上; 但 createAlias 返回的是创建子 Criteria 的条件;
示例 1. 广告 ManyToone 广告组;他们都有“名字”属性
Criteria criteria1 = s.createCriteria(Ad.class, "ad").add(Restrictions.eq("ad.id", Long.valueOf(343909))) ;
Criteria criteria2 = criteria1.createCriteria("adGroup")
.setProjection(Projections.property("name"))
List list = criteria2.list();
List list = s.createCriteria(Ad.class, "ad").add(Restrictions.eq("ad.id", Long.valueOf(343909)))
.createAlias("adGroup", "adGroup")
.setProjection(Projections.property("name"))
.list();
假设广告组中的名称是“aaaa” 广告中的名字是“bbbb” 在第一个语句中,结果的“名称”值来自 adGroup 实体 =“aaaa”。 在第二条语句中,结果的“name”值来自广告实体“bbbb”。
ps1:如果 adgroup 实体中没有“name”属性,但在 ad 实体中,第一个语句将抛出异常:org.hibernate.QueryException:无法解析属性:name of:AdGroup ; 但如果你改为“ .setProjection(Projections.property("ad.name")) ”,返回广告名称的值就可以了
ps2 :第一条语句通过 criteria2 调用 list() ,但 hibernate 将从根 criteria = criteria1 开始处理;所以最终的sql将包含来自criteria1的“where ad.id =343909”;
示例 2.
老师 oneToMany 学生 学生 oneToMany 学生
List list1 = s.createCriteria(Teacher.class, "teacher").add(Restrictions.eq("teacher.id", Long.valueOf(343909)))
.createCriteria("students").createCriteria("books")
.list();
List list2 = s.createCriteria(Teacher.class, "teacher").add(Restrictions.eq("teacher.id", Long.valueOf(343909)))
.createAlias("students").createCriteria("books").setProjection(Projections.property("name"))
.list();
第二条语句将抛出异常:org.hibernate.QueryException:无法解析属性:书籍:教师; 因为书籍是学生的财产 这就是 createCriteria 和 createAlias 之间的区别;