我在下面使用带有 Hibernate 的 JPA,我无法让合并工作,但在我描述我在使用 JPA 时遇到的问题之前,让我列出我想要完成的工作,以防万一我的问题源于我的方法.
我有来自系统的数据,需要放入另一个系统。为此,我正在读取数据,然后基于该数据构造新的 ORM 对象,然后我想将 ORM 对象持久保存到数据库中。现在,当数据库为空时,程序可以正常运行,只需调用 em.persist(object) 即可。但是,我希望能够在数据库中有数据时运行此过程,添加新数据并根据需要更新旧数据,这就是我遇到问题的地方。
我做一个简单的检查,看看该项目是否已经存在于数据库中,如果没有找到,我坚持,如果记录存在,我尝试合并。失败并出现重复记录错误;
ERROR JDBCExceptionReporter - Violation of UNIQUE KEY constraint 'UK-SubStuff-StuffId-SubStuffNumber'. Cannot insert duplicate key in object 'SubStuff'.
让我感到奇怪的是 em.merge() 调用正在尝试插入而不是更新(我通过 SQL 日志记录确认了这一点)。
Hibernate: insert into SubStuff (SubStuffNumber, StuffId, Name, TypeId) values (?, ?, ?, ?)
我应该注意我正在使用级联成子对象的对象。失败发生在子对象上,这对我来说很有意义,因为我希望它首先尝试合并子对象。
以下是我的代码,请原谅粗略的状态,我已尝试在此处记录一些解决方法。
private void storeData(Collection<Stuff> Stuffs) {
for (Stuff stuff : Stuffs) {
//I think this first block can be safely ignored, as I am having no issues with it
// Left it in just in case someone more experianced then I sees the root of the issue here.
Collection<SubStuff> subStuffs = stuff.getSubStuffCollection();
for (SubStuff s : subStuffs) {
//Persist SubStuff Type, which DOES NOT cascade,
// due to it not having an internal SubStuff collection
Query q = em.createNamedQuery("SubStuffType.findByType");
q.setParameter("type", f.getTypeId().getType());
try {
SubStuffType sst = (SubStuffType) q.getSingleResult();
s.setTypeId(sst);
} catch (NoResultException ex) {
if (logger.isDebugEnabled()) logger.debug("SubStuff Type not found, persisting");
em.persist(s.getTypeId());
}
}
if (em.find(Stuff.class, stuff.getId()) == null) {
//Persist on Stuffs will cascade to SubStuffs
em.persist(stuff);
} else {
// Failing to merge SubStuff, tries to insert duplicate
// Merge SubStuff first
// The block below is my attempt to merge the SubStuff Collection before merging Stuff,
// it creates the same isuse as a straight merge of Stuff.
Collection<SubStuff> mergedSubStuffs = new ArrayList<SubStuff>(SubStuffs.size());
for (SubStuff s : SubStuffs) {
Query q = em.createNamedQuery("SubStuff.findBySubStuffNumberStuffId");
q.setParameter("SubStuffNumber", s.getSubStuffNumber());
q.setParameter("StuffId", stuff.getId());
try {
SubStuff subStuff = (SubStuff) q.getSingleResult();
// -----> Merge fails, with an duplicate insert error
SubStuff mergedSubStuff = em.merge(s);
mergedSubStuffs.add(mergedSubStuff);
} catch (NoResultException ex) {
throw ex;
}
}
stuff.setSubStuffCollection(mergedSubStuffs);
// -----> This will fails with same error as above, if I remove the attempt
// to merge the sub objects
em.merge(stuff);
}
}
}
如果有 JPA 经验的人可以帮助我,我将不胜感激。Hibernate 的 saveOrUpdate() 和 JPA 的 merge() 之间的差异显然让我感到困惑,但是尽管阅读了几篇关于 EnityManger 合并的文章,我仍然无法理解这里发生的事情。
谢谢你的时间。