如何在Hibernate JPA中添加可编程的实体侦听器

xiayouxue

我使用spring,hibernate,jpa2.1。如下:

@Entity
@EntityListeners(DemoListener.class)
public class Demo {

    @Id
    private Long id;

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }
}

public class DemoListener {

    @PersistenceContext
    private EntityManager entityManager;

    @PrePersist
    public void prePersist(Demo demo){

    }
}

该示例运行良好,当我想添加更多侦听器时,我必须修改Demo实体,但是该Demo对象在其他jar中,我不想使用XML配置,是否有这样的方法:

...addListener(Demo.class, new DemoListener());
...addListener(Demo.class, new OtherDemoListener());
xiayouxue

基于hibernate-orm文档和hibernate-tutorials:

/**
 * @param <T> one of {@link EventType#baseListenerInterface()}
 * @see org.hibernate.event.service.spi.EventListenerRegistry
 */
public interface JpaEventListenerRegistry<T> {

    /**
     * add listener for entity class
     *
     * @param entityClass can't be null
     * @param listener    can't be null
     */
    void addListener(Class<?> entityClass, T listener);
}



public class JpaEventListenerRegistryImpl implements JpaEventListenerRegistry<Object> {

    private Logger logger = LoggerFactory.getLogger(getClass());

    private EventListenerRegistry eventListenerRegistry;
    private Map<EventType, JpaEventListenerRegistry> listeners = new HashMap<EventType, JpaEventListenerRegistry>();

    public JpaEventListenerRegistryImpl(EventListenerRegistry eventListenerRegistry) {
        this.eventListenerRegistry = eventListenerRegistry;
        initDefault();
    }

    private void initDefault() {
        listeners.put(EventType.PRE_INSERT, new DomainPreInsertEventListener());
        listeners.put(EventType.POST_INSERT, new DomainPostInsertEventListener());
        for (Map.Entry<EventType, JpaEventListenerRegistry> entry : listeners.entrySet()) {
            eventListenerRegistry.appendListeners(entry.getKey(), entry.getValue());
        }
    }

    @SuppressWarnings("unchecked")
    public void addListener(Class<?> entityClass, Object listener) {
        logger.info("add listener {} for entity {}", listener, entityClass.getName());
        for (EventType eventType : EventType.values()) {
            Class<?> listenerInterface = eventType.baseListenerInterface();
            if (listenerInterface.isAssignableFrom(listener.getClass())) {
                JpaEventListenerRegistry registry = listeners.get(eventType);
                if (registry == null) {
                    logger.warn("the event type {} for listener {} is not supported", eventType, listener);
                } else {
                    registry.addListener(entityClass, listener);
                }
            }
        }
    }

    public static class Abstract<T> implements JpaEventListenerRegistry<T> {

        private Logger logger = LoggerFactory.getLogger(getClass());
        private Map<Class<?>, List<T>> listeners = new HashMap<Class<?>, List<T>>();

        public void addListener(Class<?> entityClass, T listener) {
            logger.info("add listener {} for entity {}", listener, entityClass.getName());
            List<T> listeners = this.listeners.get(entityClass);
            if (listeners == null) {
                listeners = new ArrayList<T>();
                this.listeners.put(entityClass, listeners);
            }
            listeners.add(listener);
        }

        List<T> findListener(Class<?> entityClass) {
            for (Map.Entry<Class<?>, List<T>> entry : listeners.entrySet()) {
                if (entry.getKey().isAssignableFrom(entityClass)) {
                    return entry.getValue();
                }
            }
            return null;
        }

    }


    public static class DomainPreInsertEventListener extends Abstract<PreInsertEventListener> implements PreInsertEventListener {

        public boolean onPreInsert(PreInsertEvent event) {
            return onPreInsert(event, findListener(event.getEntity().getClass()));
        }

        private boolean onPreInsert(PreInsertEvent event, List<PreInsertEventListener> listeners) {
            if (listeners == null) return false;
            for (PreInsertEventListener listener : listeners) {
                if (listener.onPreInsert(event)) return true;
            }
            return false;
        }
    }

    public static class DomainPostInsertEventListener extends Abstract<PostInsertEventListener> implements PostInsertEventListener {

        public void onPostInsert(PostInsertEvent event) {
            onPostInsert(event, findListener(event.getEntity().getClass()));
        }

        private void onPostInsert(PostInsertEvent event, List<PostInsertEventListener> listeners) {
            if (listeners == null) return;
            for (PostInsertEventListener listener : listeners) {
                listener.onPostInsert(event);
            }
        }


        public boolean requiresPostCommitHanding(EntityPersister persister) {
            return false;
        }
    }
}


public class EntityManagerIllustrationTest extends TestCase {
    private EntityManagerFactory entityManagerFactory;

    @Override
    protected void setUp() throws Exception {
        // like discussed with regards to SessionFactory, an EntityManagerFactory is set up once for an application
        //      IMPORTANT: notice how the name here matches the name we gave the persistence-unit in persistence.xml!
        entityManagerFactory = Persistence.createEntityManagerFactory("org.hibernate.tutorial.jpa");

        SessionFactoryImplementor sessionFactory = entityManagerFactory.unwrap(SessionFactoryImplementor.class);
        EventListenerRegistry eventListenerRegistry = sessionFactory.getServiceRegistry().getService(EventListenerRegistry.class);
        JpaEventListenerRegistryImpl jpaEventListenerRegistry = new JpaEventListenerRegistryImpl(eventListenerRegistry);
        jpaEventListenerRegistry.addListener(EventListener.class, new JpaEventListener());
    }

    private static class JpaEventListener implements PreInsertEventListener, PostInsertEventListener {
        public boolean onPreInsert(PreInsertEvent event) {
            Event entity = (Event) event.getEntity();
            System.out.println("onPreInsert:" + entity);
            return false;
        }

        public void onPostInsert(PostInsertEvent event) {
            Event entity = (Event) event.getEntity();
            System.out.println("onPostInsert:" + entity);
        }

        public boolean requiresPostCommitHanding(EntityPersister persister) {
            return false;
        }
    }

    @Override
    protected void tearDown() throws Exception {
        entityManagerFactory.close();
    }

    public void testBasicUsage() {
        // create a couple of events...
        EntityManager entityManager = entityManagerFactory.createEntityManager();
        entityManager.getTransaction().begin();
        entityManager.persist(new Event("Our very first event!", new Date()));
//        entityManager.persist(new Event("A follow up event", new Date()));
        entityManager.getTransaction().commit();
        entityManager.close();

        // now lets pull events from the database and list them
        entityManager = entityManagerFactory.createEntityManager();
        entityManager.getTransaction().begin();
        List<Event> result = entityManager.createQuery("from Event", Event.class).getResultList();
        for (Event event : result) {
            System.out.println("Event (" + event.getDate() + ") : " + event.getTitle());
        }
        entityManager.getTransaction().commit();
        entityManager.close();
    }


}

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章

如何在我的onClick处理程序中添加键盘侦听器?

如何在JPA中复制Hibernate的saveOrUpdate?

如何禁用JPA 2回调方法和实体侦听器

如何在jquery的sweetalert对话框中为html按钮添加事件侦听器

如何在“自定义”对话框中添加广播组选中的侦听器

如何在cameraX中添加侦听器以完成焦点

如何在日志侦听器中添加一些其他列?

如何在类内的html中添加具有函数回调的事件侦听器?

如何在Twilio可编程聊天中从多个渠道收听新消息?

NestJs:如何在实体侦听器中访问数据库?

如何在Twilio可编程聊天中的单个频道上收听消息

如何添加侦听器以删除MongoDB中的函数?

如何在Java中添加按钮侦听器?

如何在Ext JS的日历组件中添加侦听器?

如何在Ubuntu中关闭或调整聪明的制表符完成(可编程完成)

Hibernate:如何在Hibernate中删除多行?

如何在文档查看器中的“完成”按钮上添加侦听器

如何在Polymer中的自定义元素属性中添加事件侦听器?

如何在IONIC2中添加标记单击侦听器?

javafx:如何在集成演示中添加适当的侦听器?

Hibernate 中特定于实体的侦听器/事件/拦截器

如何以编程方式在预制件中向 UnityEvent 添加侦听器

如何在 GridView 中的 imageView 中添加单击侦听器?

如何以编程方式向 StackView 中的每个按钮添加单独的选择器/侦听器 swift 4.2

如何在 Twilio 可编程语音(会议)中构建管理功能

如何向 ReactJs 中的对象数组添加侦听器

如何在尚未在 DOM [no-jQuery] 中的元素上添加事件侦听器?

如何在 EXTJS 中添加窗口方向侦听器?

如何在 Javascript 中添加带有 HTML 模板文字的事件侦听器?