我有一个在旧版.hbm.xml文件中建模的表。
用于检索行的旧版代码使用org.hibernate.Criteria获取uniqueResult()。在迁移到Hibernate 5.x时,不建议使用Criteria,因此我尝试使用CriteriaBuilder来实现这一点。但是,当我尝试根据以前的工作原理(Hib 4.x)添加限制(Hib 5.x)时,会收到IllegalArgumentException:
java.lang.IllegalArgumentException: Unable to locate Attribute with the the given name [xyzKey.plantName] on this ManagedType [com.foo.bar.Plant]
at org.hibernate.metamodel.model.domain.internal.AbstractManagedType.checkNotNull(AbstractManagedType.java:147)
at org.hibernate.metamodel.model.domain.internal.AbstractManagedType.getAttribute(AbstractManagedType.java:118)
at org.hibernate.metamodel.model.domain.internal.AbstractManagedType.getAttribute(AbstractManagedType.java:43)
at org.hibernate.query.criteria.internal.path.AbstractFromImpl.locateAttributeInternal(AbstractFromImpl.java:111)
at org.hibernate.query.criteria.internal.path.AbstractPathImpl.locateAttribute(AbstractPathImpl.java:204)
at org.hibernate.query.criteria.internal.path.AbstractPathImpl.get(AbstractPathImpl.java:177)
Plant.hbm.xml:
<hibernate-mapping>
<class lazy="false" name="com.foo.bar.Plant" table="Plant">
<meta inherit="false" attribute="extends">com.foo.bar.PlantBase</meta>
<id name="id" type="integer" column="plantID" unsaved-value="null">
<meta inherit="false" attribute="scope-set">protected</meta>
<generator class="native" />
</id>
<component name="xyzKey" class="com.foo.bar.PlantKey">
<meta inherit="false" attribute="use-in-tostring">true</meta>
<property name="plantName" type="string" index="xyzKeyndx" unique-key="plantKey">
<column name="plantName" />
</property>
<property name="xyzRevision" type="string" index="xyzKeyndx" unique-key="plantKey">
<column name="xyzRevision" length="100"/>
</property>
</component>
<property name="active" type="java.lang.Boolean" index="xyzKeyndx">
<column name="active" not-null="true"/>
</property>
<property name="description" type="string" not-null="false">
<meta inherit="false" attribute="field-description">User specified description. Does not need to be unique.</meta>
<meta inherit="false" attribute="use-in-tostring">false</meta>
<column name="descr" not-null="false" />
</property>
<property name="location" type="string" not-null="true">
<column name="location" />
</property>
</class>
</hibernate-mapping>
基于Hibernate 4.x的代码有效:
protected Plant selectPlant(Session session, PlantKey xyzKey)
{
Criteria c = session.createCriteria(Plant.class);
if (Util.isEmpty(xyzKey.getXyzRevision()))
{
SimpleExpression plantName = Restrictions.eq("xyzKey.plantName", xyzKey.getPlantName());
SimpleExpression active = Restrictions.eq("active", true);
c.add(Restrictions.and(plantName, active));
}
else
{
c.add( Restrictions.eq("xyzKey", xyzKey) );
}
Plant plant = (Plant)c.uniqueResult();
return plant;
}
基于Hibernate 5.x的代码失败:
protected Plant selectPlant(Session session, PlantKey xyzKey)
{
ElapsedTimer timer = new ElapsedTimer();
CriteriaBuilder criteriaBuilder = session.getCriteriaBuilder();
CriteriaQuery<Plant> criteriaQuery = criteriaBuilder.createQuery(Plant.class);
Root<Plant> root = criteriaQuery.from(Plant.class);
List<Predicate> restrictions = new ArrayList<>();
if ( FBCUtil.isEmpty(vpeKey.getVpeRevision()) )
{
restrictions.add(criteriaBuilder.equal(root.get("xyzKey.plantName"), xyzKey.getPlantName())); // FAILS HERE!
restrictions.add(criteriaBuilder.equal(root.get("active"), true));
}
else
{
restrictions.add(criteriaBuilder.equal(root.get("xyzKey"), xyzKey));
}
criteriaQuery.where(restrictions.toArray(new Predicate[restrictions.size()]));
Query<Plant> query = session.createQuery(criteriaQuery);
Plant plant = query.uniqueResult();
return plant;
}