Hibernate的saveOrUpdate方法问题

3

我正在尝试使用Hibernate(首次涉足数据库)并且在选择使用saveOrUpdate还是Save.Update时感到困惑。我有一个目的地POJO类及其其他属性,需要与Destination实体一起更新。我正在接收一个XML文件进行导入,并使用以下代码更新/保存目的地实体及其属性类。

try{
        getSessionFactory().getCurrentSession().beginTransaction();
        getSessionFactory().getCurrentSession().saveOrUpdate(entity);
        getSessionFactory().getCurrentSession().getTransaction().commit();
        }
        catch(Exception e){
            getSessionFactory().getCurrentSession().getTransaction().rollback();
        }
        finally{
            getSessionFactory().close();
        }

一切都运行正常,直到我使用相同的会话实例。但是,当我使用相同的 XML 文件更新目标 PO 的某些属性时,它会给出以下错误。

SEVERE: Duplicate entry 'MNLI' for key 'DESTINATIONID'
9 Jan, 2011 4:58:11 PM org.hibernate.event.def.AbstractFlushingEventListener performExecutions
SEVERE: Could not synchronize database state with session
org.hibernate.exception.ConstraintViolationException: Could not execute JDBC batch update
    at org.hibernate.exception.SQLStateConverter.convert(SQLStateConverter.java:94)
    at org.hibernate.exception.JDBCExceptionHelper.convert(JDBCExceptionHelper.java:66)
    at org.hibernate.jdbc.AbstractBatcher.executeBatch(AbstractBatcher.java:275)
    at org.hibernate.jdbc.AbstractBatcher.prepareStatement(AbstractBatcher.java:114)
    at org.hibernate.jdbc.AbstractBatcher.prepareStatement(AbstractBatcher.java:109)
    at org.hibernate.jdbc.AbstractBatcher.prepareBatchStatement(AbstractBatcher.java:244)
    at org.hibernate.persister.entity.AbstractEntityPersister.insert(AbstractEntityPersister.java:2242)
    at org.hibernate.persister.entity.AbstractEntityPersister.insert(AbstractEntityPersister.java:2678)
    at org.hibernate.action.EntityInsertAction.execute(EntityInsertAction.java:79)

我正在使用UUID作为Destination表的主键,并且在目标表中我有一个唯一的目标ID。但是我可以理解,在第二种情况下,Hibernate无法找到是否已经存在相同目标的条目,并尝试执行插入语句而不是更新语句。
一种可能的解决方案是我可以使用目标ID来检查是否已经存在给定ID的目标,并根据结果发出保存或更新命令。 我的问题是,是否有其他更好的方法来实现这一点?
提前感谢。

有没有任何理由不将getSessionFactory().getCurrentSession()存储在一个变量中? - Baz1nga
你在执行 session.Save() 吗? - Baz1nga
@User350374;仅用于测试目的,我正在使用saveOrUpdate()方法。 - Umesh Awasthi
1个回答

2
saveOrUpdate() 操作的语义如下(参见11.7. Automatic state detection):
  • 如果对象已经存在于此会话中,则不执行任何操作
  • 如果与会话关联的另一个对象具有相同的标识符,则抛出异常
  • 如果对象没有标识符属性,则将其保存(save())
  • 如果对象的标识符具有分配给新实例化对象的值,则将其保存(save())
  • 如果对象由 <version><timestamp> 版本控制,并且版本属性值与分配给新实例化对象的值相同,则将其保存(save())
  • 否则更新(update())对象
因此,看起来在导入 XML 文件时主键或版本值丢失了。

是的,因为我们从第三方系统获取XML,所以没有任何机会获取主键,而且我对版本值了解很少,我知道我们可以使用它来控制,但不确定如何做到这一点。此外,我已经阅读了文档,但仍然不清楚如何处理我的情况,因为我不确定何时会收到第二个XML进行更新。 - Umesh Awasthi
@umesh:如果你的XML没有主键,而是通过目标ID进行标识,那么是的,你需要首先确定具有相同目标ID的现有对象的主键。 - axtavt
谢谢,我刚想到另一种方法,我们能否通过一些版本控制的技巧来做到这一点,比如第三方 XML 发送时间戳? - Umesh Awasthi

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接