【问题标题】:how to add entity listener programmable in Hibernate JPA如何在 Hibernate JPA 中添加可编程的实体侦听器
【发布时间】:2017-09-20 12:10:32
【问题描述】:

我用的是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());

【问题讨论】:

    标签: spring hibernate jpa-2.1


    【解决方案1】:

    基于hibernate-orm docs 和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();
        }
    
    
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-10-03
      • 2012-05-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-10-07
      相关资源
      最近更新 更多