Hibernate/JPA - 实体侦听器没有被正确调用 [英] Hibernate/JPA - Entity listener not being called properly

查看:34
本文介绍了Hibernate/JPA - 实体侦听器没有被正确调用的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试在我的 Seam/Hibernate/JPA 应用程序中利用 EntityListener 对象和回调方法.我在 JBoss 5.1 上使用 Seam 2.2 管理的持久性上下文,后端使用 PostgreSQL 9.1.我声明了以下实体:

I'm trying to leverage EntityListener objects and callback methods within my Seam/Hibernate/JPA application. I'm using a Seam 2.2-managed persistence context on JBoss 5.1 with PostgreSQL 9.1 on the backend. I have the following entity declared:

@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 回调类:

along with the following EntityListener callback class:

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$
    }
}

然而,当我运行我的测试时,我没有看到我所有的回调方法都像我期望的那样被调用.我已经对以下场景进行了测试:

When I run my test, however, I do not see all of my callback methods being called as I would expect. I've run tests of the following scenarios:

  • 保留一个新项目
  • 更新现有项目
  • 加载项目
  • 删除项目

但是,我看到的唯一回调是:

However, the only callbacks I see being called are:

  • @PrePersist
  • @PreRemove
  • @PostLoad
  • @PreUpdate

剩余的回调没有按预期执行.这是正常行为吗?只是我误会了吗?这是否与 Seam 管理事务的方式有关?或者,我只是做错了什么?

The remaining callbacks do not get executed as expected. Is this the normal behavior? Am I just misunderstanding it? Does this have something to do with the way Seam manages transactions? Or, am I just not doing something right?

如果您能提供任何帮助,我将不胜感激.

I'd appreciate any help you can give.

根据要求,这是我正在调用的确切代码和我收到的输出:

As requested, here is the exact code I'm calling and the output I receive:

测试 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.

Sorry if i give a wrong answer... i don't know Seam.

但是在您的主题中,您说Hibernate/JPA"并不清楚.您是使用 SessionFactory 中的 Session 还是 EntityManagerFactory 中的 EntityManager 来持久化实体?

But in your subject you say "Hibernate/JPA" which is unclear. Do you persist entities using a Session from a SessionFactory, or an EntityManager from an EntityManagerFactory?

有一个很大的不同,因为如果您将 Seam 与 SessionFactory 一起使用,则最大的不同在于默认情况下 JPA 侦听器(触发您的带注释的回调)不会默认注册,而它们与 EntityManagerFactory 一起使用.因此,您可能正在使用 SessionFactory,而您项目中配置该会话工厂的其他人仅注册了所有 JPA 回调侦听器的子集.

There is a big difference because if you use Seam with a SessionFactory, the big difference is that by default the JPA listeners (which fire your annotated callbacks) are not registred by default, while they are with an EntityManagerFactory. So it may be possible that you are using a SessionFactory, and that someone else on your project, who configured that session factory, only registered a subset of all the JPA callback listeners.

见:http://docs.jboss.org/hibernate/entitymanager/3.5/reference/en/html/configuration.html#d0e865

好的,抱歉,您使用的是 EntityManager...

Ok sorry, you use an EntityManager...

但也许尝试将 SessionFactory 置于 EntityManagerFactory 之后是一个好主意,并查看注册了哪些事件侦听器.那个应用程序只有你一个人吗?如果有人尝试注册自定义/传统事件侦听器或其他内容,他可能已经覆盖了 JPA 事件侦听器.

but perhaps it would be a good idea to try to get that SessionFactory behind the EntityManagerFactory, and see which event listeners are registred. Are you alone on that application? If someone tried to register a custom/legacy eventlistener or something, he may have overriden a JPA eventlistener.

这可以通过类似的方式实现:

This can be achieved by something like that:

EntityManager em = ...
Session session = (Session)em.getDelegage()
SessionFactoryImpl sessionFactoryImpl = (SessionFactoryImpl)session.getSessionFactory();
EventListeners el = sessionFactoryImpl.getEventListeners()

然后你可以看看里面是什么,例如,根据你的问题,你可以比较:

And then you can look what's inside, for exemple, according to your problem, you can compare:

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

It seems that it is possible to easily override JPA default listeners, see that: http://docs.jboss.org/hibernate/entitymanager/3.6/reference/en/html/listeners.html

如果您向我们展示您的persistence.xml 就好了

It would be nice if you show us your persistence.xml

这篇关于Hibernate/JPA - 实体侦听器没有被正确调用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆