我有一个实体类:
package womble;
public class Cabbage {
private int id;
// getters, setters, etc.
}
我已经映射到两个单独的数据库表,如下所示:
<hibernate-mapping>
<class name="womble.Cabbage"> <!-- Using the default entity and table name. -->
<id name="id" unsaved-value="null">
<generator class="native"/>
</id>
</class>
</hibernate-mapping>
<hibernate-mapping>
<class name="womble.Cabbage" entity-name="CabbageBackup" table="cabbage_backup">
<id name="id">
<generator class="assigned"/>
</id>
</class>
</hibernate-mapping>
我正在尝试检索上次保存的Cabbage实例,如下所示:
package womble;
public class CabbageDao {
Session session; // Hibernate session
String GET_MAX_ID = "select max(id) from Cabbage";
public getLastCabbage() {
Object lastId = session.createQuery(GET_MAX_ID).uniqueResult();
return session.load(Cabbage.class, lastId);
}
}
这会引发NonUniqueResultException
:“查询未返回唯一结果:2”
通过查看日志,Hibernate显然会查询这两个表,然后将结果连接在一起。
有没有办法让Hibernate只查询实体的默认映射? (也就是说,当我使用简单的类名时,专门防止它神奇地查询两个映射。)
我尝试使用上面的方法,使用标准API将Cabbage.class传递给#createCriteria(),以及字符串“Cabbage”,两者都从两个表中选择。我试图避免为“主”映射指定一个实体名称,因为在我的代码中有多个这样的类,我也必须修复它们之间的所有关系。
答案 0 :(得分:2)
首先,Hibernate没有关于你的“默认”的概念 - 两者的映射都是平等的。就其而言。
您是否需要从备份表中访问旧卷心菜(不是我之前使用过的词组),或者您只是使用该表来存档旧数据?
如果是后者,则可能有更好的方法来实现相同的结果,例如使用数据库触发器。
答案 1 :(得分:1)
尝试在两个映射上使用实体名称,并指定您想要的内容。我相信那是该属性的契约。
答案 2 :(得分:0)
嗯,一个简单的答案(不一定是最好的答案)是使用.list()
而不是.uniqueResult()
带回最大ID的集合。然后,您可以将结果投入新的HashSet
,让Java完成独特的工作。不优雅,但它会起作用。
public getLastCabbage() {
Set lastIds = new HashSet(session.createQuery(GET_MAX_ID).list());
// ignore the possibility of null; full steam ahead
return session.load(Cabbage.class, lastIds.iterator().next());
}
答案 3 :(得分:0)
您可能会考虑为您执行此表修订的extensions to hibernate之一。我从未亲自使用过envers,但文档看起来很有趣。