hibernate - Hibernate/JPA-实体监听器未正确调用

标签 hibernate jpa callback seam entitylisteners

我试图在我的Seam/Hibernate/JPA应用程序中利用EntityListener对象和回调方法。我在JBoss 5.1和后端的PostgreSQL 9.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,而项目中配置了该 session 工厂的其他人仅注册了所有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,那就太好了

    关于hibernate - Hibernate/JPA-实体监听器未正确调用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8373024/

    相关文章:

    java - 基于 Hibernate SessionFactory 注解的配置

    具有外连接的 Hibernate HQL 查询

    postgresql - JPA:生成非 pk 唯一且随机的字母数字值

    java.lang.ClassNotFoundException : play. db.jpa.JPABase 使用 hibernate

    javascript - 将代码重写为递归回调后,jQuery .fadeIn() 和 .fadeOut() 回调无法正常工作

    c - 函数数组在 if 和 switch 语句上的性能

    java - 恢复 hibernate 连接

    java - MySQL 中的关系

    java - 使用 eclipselink 和 @namedquery 进行转换时出错

    javascript - 将 innerHTML 传递给元素并附加事件