我试图在我的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; ... }
以及以下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$ } }
但是,当我运行测试时,我没有看到我期望的所有回调方法都被调用。我已经对以下情况进行了测试:
但是,我看到的唯一回调是:
@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$ }
输出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
测试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$ }
输出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
测试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$ }
输出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
抱歉,如果我给出错误的答案…我不知道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()
然后您可以查看内部内容,例如,根据您的问题,您可以进行比较:
el.getPreLoadEventListeners() el.getPreDeleteEventListeners()
并记住“默认行为”是: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,那就太好了