2016-02-15 61 views
2

我有两个应用:如何确保记录已添加到数据库中?

  • 第一个插入一条记录到PostgreSQL数据库(假设它的id等于X),并通知其被通知发送邮件给用户的第二个
  • 之一,但在此之前,它会检查是否具有ID X的记录(它被包含在从第一机器的“通知信息”中)被插入到数据库中

在99%情况下,它工作得很好,但有时所述第二机无法找到具有给定ID的记录。怎么可能?

在我使用Hibernate和对象保存到这样的数据库中的第一台机器的侧面:

objectDao.save(object); 

,然后发送消息:

publisher.sendObjectAddedMessage(user.getId(), ipSource.getIpAddress(), object.getId()); 

没什么特别的。我试图在发送消息之前立即刷新休眠或稍等一会,但事件发生后就会出现问题。

我的PostgreSQL的版本是:

PostgreSQL 9.3.5 on x86_64-unknown-linux-gnu, compiled by gcc (Debian 4.7.2-5) 4.7.2, 64-bit 
+0

如果您在发送该消息之前增加了时间,那么可以吗?该记录出现在数据库或缺少?或者在发送消息后注册会出现在数据库中? –

+0

在第二台机器上,我实现了“三次尝试”机制(超时),这有时可以帮助,但并不经常。 – y434y

回答

1

我们强烈建议您使用一些事件侦听器调用publisher.sendObjectAddedMessage()

即你应该创建一个侦听器,在任何对象被持久化之后调用一个方法,以确保你的sendObjectAddedMessage()在实体持久化之前不会被调用。

考虑这个例子:

我会坚持这个简单的实体Person.java,我将几个事件与此类关联。无论何时保存此实体,都会在负责此实体的事务处理之前和之后调用一些方法。

Person.java

@Entity 
public class Person implements Serializable { 
    @Id 
    @GeneratedValue (strategy = GenerationType.AUTO) 
    int id; 

    String name; 

    //getters and setters below this 
    ... 
} 

现在考虑我的Main类。你可以看到我创建了AuditLogInterceptor并将它与会话相关联。

通过将此拦截器与会话相关联,它将调用拦截器的几种方法,如onSavepreFlushpostFlush方法。这将确保在需要时总是调用这些方法。 (如postFlush不会被保存实体之前调用)

Test.java

public class Test { 
    public static void main(String[] args) { 
     AuditLogInterceptor interceptor = new AuditLogInterceptor(); 

     Session session = HibernateUtil.getSessionFactory() 
       .withOptions() 
       .interceptor(interceptor) 
       .openSession(); 
     interceptor.setSession(session);   

     Person p = new Person(); 
     p.setName("John Doe"); 

     session.getTransaction().begin(); 
     session.save(p); 
     session.getTransaction().commit(); 
     session.close(); 
    } 
} 

这是主类AuditLogInterceptor.java的代码。它实现了休眠的EmptyInterceptor接口。正如您在Test.java中所了解的那样,我们将会话与此拦截器关联。因此,它的覆盖方法将被称为在几个事件,如保存,更新等..

AuditLogInterceptor.java

package test; 

import java.io.Serializable; 
import java.util.Iterator; 

import org.hibernate.CallbackException; 
import org.hibernate.EmptyInterceptor; 
import org.hibernate.Session; 
import org.hibernate.type.Type; 

public class AuditLogInterceptor extends EmptyInterceptor{ 
    Session session; 

    public void setSession(Session session) { 
     this.session=session; 
    } 

     @Override 
    public boolean onSave(Object entity,Serializable id, 
     Object[] state,String[] propertyNames,Type[] types) 
     throws CallbackException { 

     System.out.println("onSave"); 

     return false; 

    } 

    //called before commit into database 
     @Override 
    public void preFlush(Iterator iterator) { 
     System.out.println("preFlush"); 
    } 

    //called after committed into database 
     @Override 
    public void postFlush(Iterator iterator) { 
     System.out.println("postFlush");       
    } 
} 

现在

Hibernate: drop table if exists hibernate_sequence 
Hibernate: drop table if exists Person 
Hibernate: create table hibernate_sequence (next_val bigint) 
Hibernate: insert into hibernate_sequence values (1) 
Hibernate: create table Person (id integer not null, name varchar(255), primary key (id)) 
Feb 16, 2016 8:23:18 AM org.hibernate.tool.hbm2ddl.SchemaExport execute 
INFO: HHH000230: Schema export complete 
Hibernate: select next_val as id_val from hibernate_sequence for update 
Hibernate: update hibernate_sequence set next_val= ? where next_val=? 
onSave 
preFlush 
Hibernate: insert into Person (name, id) values (?, ?) 
postFlush 

正如你可以看到,我们的印刷onSave输出,preFlushpostFlush,在大底AuditLogInterceptor.java

postFlush期间,您可以拨打publisher.sendObjectAddedMessage()。在我看来,这将在所有情况下100%正常工作:)

要了解更多详情,请参阅this示例。

相关问题