在新的Hibernate会话中,在事件can';看不到保存在不同会话中的实体(但相同事务)

在新的Hibernate会话中,在事件can';看不到保存在不同会话中的实体(但相同事务),hibernate,spring,transactions,Hibernate,Spring,Transactions,我正在使用Hibernate的PreInsertEventListener对表中的字段进行审核。 我还使用Spring创建SessionFactory和TransactionManager 其他一些可能相关的细节: 使用OpenSessionInViewFilter 休眠版本:3.5.1-Final Spring版本:3.0.3.发布 Oracle 10g数据库 在事件中使用会话是不安全的,因为它可能正在刷新,因此我创建了一个新会话 public boolean onPreInsert(fina

我正在使用Hibernate的
PreInsertEventListener
对表中的字段进行审核。 我还使用Spring创建SessionFactory和TransactionManager

其他一些可能相关的细节:
使用OpenSessionInViewFilter
休眠版本:3.5.1-Final
Spring版本:3.0.3.发布
Oracle 10g数据库

在事件中使用会话是不安全的,因为它可能正在刷新,因此我创建了一个新会话

public boolean onPreInsert(final PreInsertEvent event) {
    final SessionFactory factory = triggeringSession.getSessionFactory();
    Session triggeringSession = event.getSession();
    triggeringSession.doWork(new Work() {
        public void execute(Connection connection) throws SQLException {
            Session newSession = factory.openSession(connection);
            saveStuff(newSession);
            newSession.flush();
        }
    });
    return false;
}
在我的
saveStuff
方法中,我需要保存一个新实体

private void saveStuff(Session session) {
   HistoricReference historicReference = new HistoricReference();
   historicReference.setId("12345"); // This is actually an unique ID based on a generated auditing number and table that was inserted into

    // If this haven't been created I want it to be saved
    if (session.get(HistoricReference.class, "12345") == null) {
        session.save(historicReference);
    }

    // Other stuff saved (regarding old/new values etc.) that historicReference as id (as part of composite id)

}
我的问题是,如果在同一事务中插入两个相同类型的新实体,就会在HistoricReference表上得到唯一的约束冲突。我进行了调试,检查是否已经创建的代码总是返回false,但在事务提交后,它会尝试插入它两次。这是因为每次都会创建一个新会话吗

例如:

MyEntity entity1 = new MyEntity();
MyEntity entity2 = new MyEntity();  
session.save(entity1);
session.save(entity2);
我将在请求结束时(尝试提交时)得到一个唯一的约束错误。这是因为当为entity2调用
onPreInsert(…)
时,它将再次调用
session.save(historicReference)
。如果不保存entity2,则不会遇到任何问题

session.get(HistoricReference.class,“12345”)
是否会返回一个值,即使该值保存在不同的会话中,但却是相同的未提交事务

我有一个解决这个问题的方法,但它有点粗糙(使用
TransactionSynchronizationManager
绑定到事务的布尔值,以防止历史引用被保存两次),我更喜欢一个更干净的解决方案(或者至少更好地理解为什么它不能像我期望的那样工作)


任何帮助都将不胜感激。

一种解决方案是将历史引用的保存移到FlusheEvent。在preInsert事件中,只需获取数据并将其收集到线程本地映射/列表中,然后访问并将其保存在FlusheEvent中。

请使用
session.merge()
而不是
session.save()
。和

希望有帮助