我有两个应用程序:
在99%的情况下,它运行良好,但有时第二台机器无法找到具有给定ID的记录。怎么可能?
在第一台机器的一侧,我使用休眠并将对象保存到数据库中,如下所示:
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 :(得分: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
并已将其与会话相关联。
通过将此拦截器与会话相关联,它将调用此拦截器的onSave
,preFlush
和postFlush
方法等多种方法。这将确保在需要时始终调用这些方法。 (比如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
的代码。它实现了hibernate的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
的colsole上打印了preFlush
,postFlush
和AuditLogInterceptor.java
。
在postFlush
期间,您可以致电publisher.sendObjectAddedMessage()
。在我看来,这将适用于所有情况的100%:)
要详细了解详情,请参阅this示例。
答案 1 :(得分:0)
也许你应该尝试使用事件监听器(@PostPersist)? 例如。 http://alexandregama.org/2014/03/23/entity-listeners-and-callback-methods-jpa/
public class MessageListener {
@PostPersist
private void send(Object object) {
//send
}
}
@EntityListeners(MessageListener.class)
public class ObjectPOJO {
}