Sha*_*man 6 hibernate seam jpa callback entitylisteners
我正在尝试在我的Seam/Hibernate/JPA应用程序中利用EntityListener对象和回调方法.我在后端使用带有PostgreSQL 9.1的JBoss 5.1上的Seam 2.2管理持久化上下文.我声明了以下实体:
@Entity(name = "TestEntity")
@EntityListeners(TestCallback.class)
@Table(name = "tbl_test")
public class TestEntity implements Serializable {
private static final long serialVersionUID = 2016897066783042092L;
@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "xxx")
@SequenceGenerator(name = "xxx", sequenceName = "xxx")
@Index(name = "xxx")
@DocumentId
private Long id = null;
@Column
private String test = null;
...
}
Run Code Online (Sandbox Code Playgroud)
以及以下EntityListener回调类:
public class TestCallback {
/**
* Logger for this class
*/
private Log logger = null;
public TestCallback() {
logger = Logging.getLog(TestCallback.class);
}
@PrePersist
public void prePersist(TestEntity e) {
logger.debug("prePersist(TestEntity) - start"); //$NON-NLS-1$
logger.debug("prePersist(TestEntity) - end"); //$NON-NLS-1$
}
@PostPersist
public void postPersist(TestEntity e) {
logger.debug("postPersist(TestEntity) - start"); //$NON-NLS-1$
logger.debug("postPersist(TestEntity) - end"); //$NON-NLS-1$
}
@PostLoad
public void postLoad(TestEntity e) {
logger.debug("postLoad(TestEntity) - start"); //$NON-NLS-1$
logger.debug("postLoad(TestEntity) - end"); //$NON-NLS-1$
}
@PreUpdate
public void preUpdate(TestEntity e) {
logger.debug("preUpdate(TestEntity) - start"); //$NON-NLS-1$
logger.debug("preUpdate(TestEntity) - end"); //$NON-NLS-1$
}
@PostUpdate
public void postUpdate(TestEntity e) {
logger.debug("postUpdate(TestEntity) - start"); //$NON-NLS-1$
logger.debug("postUpdate(TestEntity) - end"); //$NON-NLS-1$
}
@PreRemove
public void preRemove(TestEntity e) {
logger.debug("preRemove(TestEntity) - start"); //$NON-NLS-1$
logger.debug("preRemove(TestEntity) - end"); //$NON-NLS-1$
}
@PostRemove
public void postRemove(TestEntity e) {
logger.debug("postRemove(TestEntity) - start"); //$NON-NLS-1$
logger.debug("postRemove(TestEntity) - end"); //$NON-NLS-1$
}
}
Run Code Online (Sandbox Code Playgroud)
但是,当我运行测试时,我没有看到所有的回调方法都按照我的预期被调用.我运行了以下场景的测试:
但是,我看到的唯一回调是:
@PrePersist@PreRemove@PostLoad@PreUpdate剩余的回调没有按预期执行.这是正常行为吗?我只是误解了吗?这与Seam管理交易的方式有关吗?或者,我是不是做对了?
我很感激你能给予的任何帮助.
编辑: 根据要求,这是我正在调用的确切代码和我收到的输出:
测试1:
public void runTest() {
logger.debug("runTest() - start"); //$NON-NLS-1$
TestEntity e = new TestEntity();
e.setTest("XXX");
this.entityManager.persist(e);
this.entityManager.flush();
this.entityManager.clear();
logger.debug("runTest() - end"); //$NON-NLS-1$
}
Run Code Online (Sandbox Code Playgroud)
输出1:
12:27:56,307 INFO [STDOUT] 29735 DEBUG myapp.test.web.actions.test.TestAction - - runTest() - start
12:27:56,312 INFO [STDOUT] 29740 DEBUG myapp.test.entities.TestCallback - - prePersist(TestEntity) - start
12:27:56,312 INFO [STDOUT] 29740 DEBUG myapp.test.entities.TestCallback - - prePersist(TestEntity) - end
12:27:56,347 INFO [STDOUT] 29775 DEBUG myapp.test.web.actions.test.TestAction - - runTest() - end
Run Code Online (Sandbox Code Playgroud)
测试2:
public void runTest2() {
logger.debug("runTest2() - start"); //$NON-NLS-1$
String sql = "SELECT DISTINCT t FROM TestEntity t";
Query q = this.entityManager.createQuery(sql);
List<TestEntity> l = q.getResultList();
for (int i = 0; i < l.size(); i++) {
String x = l.get(i).getTest();
logger.debug("runTest2() - String x=" + x); //$NON-NLS-1$
}
logger.debug("runTest2() - end"); //$NON-NLS-1$
}
Run Code Online (Sandbox Code Playgroud)
输出2:
12:28:36,964 INFO [STDOUT] 70392 DEBUG myapp.test.web.actions.test.TestAction - - runTest2() - start
12:28:36,982 INFO [STDOUT] 70410 DEBUG myapp.test.entities.TestCallback - - postLoad(TestEntity) - start
12:28:36,982 INFO [STDOUT] 70410 DEBUG myapp.test.entities.TestCallback - - postLoad(TestEntity) - end
12:28:36,982 INFO [STDOUT] 70410 DEBUG myapp.test.web.actions.test.TestAction - - runTest2() - String x=XXX
12:28:36,983 INFO [STDOUT] 70411 DEBUG myapp.test.web.actions.test.TestAction - - runTest2() - end
Run Code Online (Sandbox Code Playgroud)
测试3:
public void runTest3() {
logger.debug("runTest3() - start"); //$NON-NLS-1$
String sql = "SELECT DISTINCT t FROM TestEntity t";
Query q = this.entityManager.createQuery(sql);
List<TestEntity> l = q.getResultList();
for (int i = 0; i < l.size(); i++) {
l.get(i).setTest("YYY" + System.currentTimeMillis());
this.entityManager.persist(l.get(i));
}
this.entityManager.flush();
this.entityManager.clear();
Random rand = new SecureRandom();
q = this.entityManager.createQuery(sql);
l = q.getResultList();
for (int i = 0; i < l.size(); i++) {
this.entityManager.remove(l.get(i));
}
this.entityManager.flush();
this.entityManager.clear();
logger.debug("runTest3() - end"); //$NON-NLS-1$
}
Run Code Online (Sandbox Code Playgroud)
输出3:
12:30:00,404 INFO [STDOUT] 153832 DEBUG myapp.test.web.actions.test.TestAction - - runTest3() - start
12:30:00,407 INFO [STDOUT] 153835 DEBUG myapp.test.entities.TestCallback - - postLoad(TestEntity) - start
12:30:00,407 INFO [STDOUT] 153835 DEBUG myapp.test.entities.TestCallback - - postLoad(TestEntity) - end
12:30:00,408 INFO [STDOUT] 153836 DEBUG myapp.test.entities.TestCallback - - preUpdate(TestEntity) - start
12:30:00,408 INFO [STDOUT] 153836 DEBUG myapp.test.entities.TestCallback - - preUpdate(TestEntity) - end
12:30:00,410 INFO [STDOUT] 153838 DEBUG myapp.test.entities.TestCallback - - postLoad(TestEntity) - start
12:30:00,411 INFO [STDOUT] 153839 DEBUG myapp.test.entities.TestCallback - - postLoad(TestEntity) - end
12:30:00,414 INFO [STDOUT] 153842 DEBUG myapp.test.entities.TestCallback - - preRemove(TestEntity) - start
12:30:00,414 INFO [STDOUT] 153842 DEBUG myapp.test.entities.TestCallback - - preRemove(TestEntity) - end
12:30:00,453 INFO [STDOUT] 153881 DEBUG myapp.test.web.actions.test.TestAction - - runTest3() - end
Run Code Online (Sandbox Code Playgroud)
对不起,如果我给出了错误的答案......我不知道Seam.
但是在你的主题中你说"Hibernate/JPA"还不清楚.您是使用SessionFactory中的Session还是EntityManagerFactory中的EntityManager来持久保存实体?
有一个很大的区别,因为如果你使用Seam与SessionFactory,最大的区别是默认情况下,默认情况下JPA监听器(触发带注释的回调)不会被注册,而它们与EntityManagerFactory一起使用.因此,您可能正在使用SessionFactory,并且您的项目中配置了该会话工厂的其他人只注册了所有JPA回调侦听器的子集.
请参阅:http: //docs.jboss.org/hibernate/entitymanager/3.5/reference/en/html/configuration.html#d0e865
编辑:好的抱歉,您使用的是EntityManager ...
但也许最好尝试将SessionFactory放在EntityManagerFactory后面,并查看注册了哪些事件监听器.那个申请你一个人吗?如果有人试图注册自定义/遗留事件监视器或其他东西,他可能已经覆盖了JPA事件监视器.
这可以通过以下方式实现:
EntityManager em = ...
Session session = (Session)em.getDelegage()
SessionFactoryImpl sessionFactoryImpl = (SessionFactoryImpl)session.getSessionFactory();
EventListeners el = sessionFactoryImpl.getEventListeners()
Run Code Online (Sandbox Code Playgroud)
然后你可以看看里面是什么,例如,根据你的问题,你可以比较:
el.getPreLoadEventListeners()
el.getPreDeleteEventListeners()
Run Code Online (Sandbox Code Playgroud)
并记住"默认行为"是:http: //docs.jboss.org/hibernate/stable/entitymanager/reference/en/html_single/#d0e865
似乎可以轻松覆盖JPA默认侦听器,请参阅:http: //docs.jboss.org/hibernate/entitymanager/3.6/reference/en/html/listeners.html
如果你向我们展示你的persistence.xml会很好