赞
踩
Spring Data JPA系列
2、Spring Data JPA Criteria查询、部分字段查询
3、Spring Data JPA数据批量插入、批量更新真的用对了吗
4、Spring Data JPA的一对一、LazyInitializationException异常、一对多、多对多操作
5、Spring Data JPA自定义Id生成策略、复合主键配置、Auditing使用
6、【源码】Spring Data JPA原理解析之Repository的自动注入(一)
7、【源码】Spring Data JPA原理解析之Repository的自动注入(二)
8、【源码】Spring Data JPA原理解析之Repository执行过程及SimpleJpaRepository源码
9、【源码】Spring Data JPA原理解析之Repository自定义方法命名规则执行原理(一)
10、【源码】Spring Data JPA原理解析之Repository自定义方法命名规则执行原理(二)
11、【源码】Spring Data JPA原理解析之Repository自定义方法添加@Query注解的执行原理
13、【源码】Spring Data JPA原理解析之事务注册原理
14、【源码】Spring Data JPA原理解析之事务执行原理
18、【源码】Spring Data JPA原理解析之Hibernate EventListener使用及原理
在Spring Data JPA自定义Id生成策略、复合主键配置、Auditing使用-CSDN博客这篇博文中,跟大家分享了JPA中的Auditing审计功能。JPA通过注解的方式,提供了对数据库表中的数据记录自动添加操作人及操作时间,同时还支持自定义监听器,实现实体插入、编辑、删除的监听,添加日志等。
在JPA中,提供了监听回调注解,实现数据不同持久化操作时的回调。注解如下:
@PrePersist:通过EntityManager.persist()新增持久化之前回调;
@PreRemove:通过EntityManager.remove()删除之前回调;
@PostPersist:通过EntityManager.persist()新增持久化之后回调;
@PostRemove:通过EntityManager.remove()删除之后回调;
@PreUpdate:数据库执行update操作之前回调;
@PostUpdate:数据库执行update操作之后回调;
@PostLoad:实体被加载或刷新之后回调;
3.1 自定义监听器,示例代码如下:
- package com.jingai.jpa.listener;
-
- @Slf4j
- public class UserAuditListener {
-
- @PostPersist
- public void postPersist(UserEntity entity) {
- log.info("user保存之后:{}, {}", entity.getId(), entity.getName());
- }
-
- @PostUpdate
- public void postUpdate(UserEntity entity) {
- log.info("user修改之后:{}", entity.getId());
- }
-
- @PostRemove
- public void postRemove(UserEntity entity) {
- log.info("user删除之后:{}", entity.getId());
- }
-
- }
3.2 在实体类的@EntityListeners中添加该监听器,示例如下:
- package com.jingai.jpa.dao.entity;
-
- @EntityListeners({AuditingEntityListener.class, UserAuditListener.class})
- @Table(name = "tb_user")
- public class UserEntity {
- // 省略其他
-
- }
3.3 另外一种实现方式是,直接在实体类中,使用回调注解,定义回调方法。示例如下:
- @Table(name = "tb_user")
- @Slf4j
- public class UserEntity {
-
- @Id
- @GeneratedValue(strategy = GenerationType.IDENTITY)
- private Long id;
-
- private String name;
- private String state;
-
- @PrePersist
- public void preSave() {
- log.info("pre save ...");
- }
- }
如上的代码,新增UserEntity时,会先执行preSave()方法。
在Hibernate中,对于3.1中提到的持久化监听注解有对应的一个枚举类CallbackType。源代码如下:
- public enum CallbackType {
- PRE_UPDATE( PreUpdate.class ),
- POST_UPDATE( PostUpdate.class ),
- PRE_PERSIST( PrePersist.class ),
- POST_PERSIST( PostPersist.class ),
- PRE_REMOVE( PreRemove.class ),
- POST_REMOVE( PostRemove.class ),
- POST_LOAD( PostLoad.class )
- ;
-
- private Class<? extends Annotation> callbackAnnotation;
-
- CallbackType(Class<? extends Annotation> callbackAnnotation) {
- this.callbackAnnotation = callbackAnnotation;
- }
-
- public Class<? extends Annotation> getCallbackAnnotation() {
- return callbackAnnotation;
- }
- }
实体类注入Spring容器过程中,会执行AnnotationBinder.bindCallbacks()。在该方法中,会遍历CallbackType的枚举类型,主要执行如下:
1)判断实体类中是否添加了对应CallbackType的注解的方法;
2)判断实体类是否添加了@EntityListeners注解且监听器有添加对应CallbackType的注解的方法【实现在CallbackDefinitionResolverLegacyImpl.getListeners()】;
3)将添加了CallbackType的枚举类型注解对应的信息封装成CallbackDefinition集合对象,保存到对应持久化对象的PersistentClass对象中。
在SessionFactoryImpl的构造方法中,会执行如下:
在EventEngine构造方法中,执行CallbacksFactory.buildCallbackRegistry()方法,返回CallbackRegistryImplementor对象。源码如下:
- package org.hibernate.jpa.event.internal;
-
- public final class CallbacksFactory {
- private static final Logger log = Logger.getLogger( CallbacksFactory.class );
-
- /**
- * @param entityBindings:持久化类信息集合
- */
- public static CallbackRegistryImplementor buildCallbackRegistry(SessionFactoryOptions options,
- ServiceRegistry serviceRegistry, Collection<PersistentClass> entityBindings) {
- if ( !jpaCallBacksEnabled( options ) ) {
- return new EmptyCallbackRegistryImpl();
- }
- ManagedBeanRegistry beanRegistry = serviceRegistry.getService( ManagedBeanRegistry.class );
- CallbackRegistryImplementor registry = new CallbackRegistryImpl();
- Set<Class<?>> entityClasses = new HashSet<>();
- // 遍历持久化类
- for ( PersistentClass persistentClass : entityBindings ) {
- if ( persistentClass.getClassName() == null ) {
- // we can have dynamic (non-java class) mapping
- continue;
- }
-
- Class<?> entityClass = persistentClass.getMappedClass();
-
- if ( !entityClasses.add( entityClass ) ) {
- if ( log.isDebugEnabled() ) {
- log.debugf(
- "Class [%s] already has callbacks registered; " +
- "assuming this means the class was mapped twice " +
- "(using hbm.xml entity-name support) - skipping subsequent registrations" +
- "to avoid duplicates",
- entityClass.getName()
- );
- }
- continue;
- }
- // persistentClass.getCallbackDefinitions():获取解析的监听器信息
- // 将监听器信息封装成Callback对象,添加到registry对象中
- registry.registerCallbacks( persistentClass.getMappedClass(),
- buildCallbacks( persistentClass.getCallbackDefinitions(), beanRegistry ) );
- // 持久化类中的方法添加的监听器封装成Callback对象,添加到registry对象中
- for ( @SuppressWarnings("unchecked") Iterator<Property> propertyIterator = persistentClass.getDeclaredPropertyIterator();
- propertyIterator.hasNext(); ) {
- final Property property = propertyIterator.next();
- registry.registerCallbacks( persistentClass.getMappedClass(),
- buildCallbacks( property.getCallbackDefinitions(), beanRegistry ) );
- }
- }
-
- return registry;
- }
-
- /**
- * 通过CallbackDefinition定义信息,转化为Callback数组
- */
- private static Callback[] buildCallbacks(List<CallbackDefinition> callbackDefinitions,
- ManagedBeanRegistry beanRegistry) {
- if ( callbackDefinitions == null || callbackDefinitions.isEmpty() ) {
- return null;
- }
- List<Callback> callbacks = new ArrayList<>();
- for ( CallbackDefinition definition : callbackDefinitions ) {
- callbacks.add( definition.createCallback( beanRegistry ) );
- }
- return callbacks.toArray( new Callback[0] );
- }
-
- private static boolean jpaCallBacksEnabled(SessionFactoryOptions options) {
- return options.areJPACallbacksEnabled();
- }
-
- }
CallbacksFactory.buildCallbackRegistry()方法的entityBindings集合参数为4.2中解析后的PersistentClass集合;
在该方法中,遍历PersistentClass,执行PersistentClass.getCallbackDefinitions()方法,获取监听器信息,封装成ListenerCallback【监听器、对应方法、监听类型(preUpdate、prePersist等)】对象,添加到CallbackRegistryImplementor中;
CallbackRegistryImpl相关代码如下:
- package org.hibernate.jpa.event.internal;
-
- @SuppressWarnings({"unchecked", "serial"})
- final class CallbackRegistryImpl implements CallbackRegistryImplementor {
- private HashMap<Class, Callback[]> preCreates = new HashMap<Class, Callback[]>();
- private HashMap<Class, Callback[]> postCreates = new HashMap<Class, Callback[]>();
- private HashMap<Class, Callback[]> preRemoves = new HashMap<Class, Callback[]>();
- private HashMap<Class, Callback[]> postRemoves = new HashMap<Class, Callback[]>();
- private HashMap<Class, Callback[]> preUpdates = new HashMap<Class, Callback[]>();
- private HashMap<Class, Callback[]> postUpdates = new HashMap<Class, Callback[]>();
- private HashMap<Class, Callback[]> postLoads = new HashMap<Class, Callback[]>();
-
- @Override
- public boolean hasRegisteredCallbacks(Class entityClass, CallbackType callbackType) {
- final HashMap<Class, Callback[]> map = determineAppropriateCallbackMap( callbackType );
- return notEmpty( map.get( entityClass ) );
- }
-
- @Override
- public void registerCallbacks(Class entityClass, Callback[] callbacks) {
- if ( callbacks == null || callbacks.length == 0 ) {
- return;
- }
- // 遍历回调
- for ( Callback callback : callbacks ) {
- // 返回对应类型的回调Map对象,key为对应实体类,value为对应类型的监听器的Callback数组,对于监听器,是ListenerCallback对象
- final HashMap<Class, Callback[]> map = determineAppropriateCallbackMap( callback.getCallbackType() );
- Callback[] entityCallbacks = map.get( entityClass );
- if ( entityCallbacks == null ) {
- entityCallbacks = new Callback[0];
- }
- entityCallbacks = ArrayHelper.join( entityCallbacks, callback );
- map.put( entityClass, entityCallbacks );
- }
- }
-
- /**
- * 根据类型,返回对应类型的Map对象
- */
- private HashMap<Class, Callback[]> determineAppropriateCallbackMap(CallbackType callbackType) {
- if ( callbackType == CallbackType.PRE_PERSIST ) {
- return preCreates;
- }
-
- if ( callbackType == CallbackType.POST_PERSIST ) {
- return postCreates;
- }
-
- if ( callbackType == CallbackType.PRE_REMOVE ) {
- return preRemoves;
- }
-
- if ( callbackType == CallbackType.POST_REMOVE ) {
- return postRemoves;
- }
-
- if ( callbackType == CallbackType.PRE_UPDATE ) {
- return preUpdates;
- }
-
- if ( callbackType == CallbackType.POST_UPDATE ) {
- return postUpdates;
- }
-
- if ( callbackType == CallbackType.POST_LOAD ) {
- return postLoads;
- }
-
- throw new PersistenceException( "Unrecognized JPA callback type [" + callbackType + "]" );
- }
-
- // 省略其他
- }
在CallbackRegistryImpl中,以实体类为key,对应类型的监听回调数组为value,将监听回调归类,存放在Map中。
将1.1)中创建的CallbackRegistryImplementor对象保存到EventListenerRegistryImpl中,并执行applyStandardListeners()方法,对数据操作的不同事件,注册默认的事件监听,并按类型归类存放。如post-update,为PostUpdateEventListenerStandardImpl。相关代码如下:
- public class EventListenerRegistryImpl implements EventListenerRegistry, Stoppable {
- public static class Builder {
- private final CallbackRegistryImplementor callbackRegistry;
- private final boolean jpaBootstrap;
-
- private final Map<EventType<?>,EventListenerGroup<?>> listenerGroupMap = new TreeMap<>(
- Comparator.comparing( EventType::ordinal )
- );
-
- /*
- * 保存信息,执行applyStandardListeners()
- */
- public Builder(CallbackRegistryImplementor callbackRegistry, boolean jpaBootstrap) {
- this.callbackRegistry = callbackRegistry;
- this.jpaBootstrap = jpaBootstrap;
-
- applyStandardListeners();
- }
-
- /*
- * 对不同的事件类型,添加默认的监听器
- */
- private void applyStandardListeners() {
-
- // 创建的默认监听器
- prepareListeners( PERSIST, new DefaultPersistEventListener() );
-
- // 创建刷新的默认监听器
- prepareListeners( PERSIST_ONFLUSH, new DefaultPersistOnFlushEventListener() );
-
- // 删除的默认监听器
- prepareListeners( DELETE, new DefaultDeleteEventListener() );
-
- // 修改后的监听器
- prepareListeners( POST_UPDATE, new PostUpdateEventListenerStandardImpl() );
-
- // 省略其他
- }
-
- public <T> void prepareListeners(EventType<T> eventType) {
- prepareListeners( eventType, null );
- }
-
- public <T> void prepareListeners(EventType<T> type, T defaultListener) {
- prepareListeners(
- type,
- defaultListener,
- t -> { // 不同类型监听器,创建监听组。即同一个类型,可以有多个监听器
- if ( type == EventType.POST_COMMIT_DELETE
- || type == EventType.POST_COMMIT_INSERT
- || type == EventType.POST_COMMIT_UPDATE ) {
- return new PostCommitEventListenerGroupImpl<>( type, callbackRegistry, jpaBootstrap );
- }
- else {
- return new EventListenerGroupImpl<>( type, callbackRegistry, jpaBootstrap );
- }
- }
- );
- }
-
- /*
- * 按类型、监听组分类,保存到Map中
- */
- @SuppressWarnings({"rawtypes", "unchecked"})
- public <T> void prepareListeners(
- EventType<T> type,
- T defaultListener,
- Function<EventType<T>,EventListenerGroupImpl<T>> groupCreator) {
- final EventListenerGroupImpl listenerGroup = groupCreator.apply( type );
-
- if ( defaultListener != null ) {
- listenerGroup.appendListener( defaultListener );
- }
-
- listenerGroupMap.put( type, listenerGroup );
- }
-
- // 省略其他
- }
- }
在Hibernate中针对不同的操作,提供了不同的EventListener。如PostUpdateEventListenerStandardImpl,实现了PostUpdateEventListener和CallbackRegistryConsumer,可以获得1.1)中的CallbackRegistryImplementor对象,并实现修改后的回调。在回调方法中,调用CallbackRegistryConsumer.postUpdate()方法,从而执行了添加@PostUpdate注解的监听回调。
在开发中,也可以通过实现对应的监听器,注入到Spring容器中,从而实现对应事件的监听。实现示例如下:
- package com.jingai.jpa.listener;
-
- @Component
- @Slf4j
- public class UserEventListener implements PersistEventListener, CallbackRegistryConsumer, InitializingBean {
-
- @Resource
- private SessionFactory sessionFactory;
-
- @Override
- public void onPersist(PersistEvent event) throws HibernateException {
- log.info("UserEventListener onPersist ....");
- }
-
- @Override
- public void onPersist(PersistEvent event, Map createdAlready) throws HibernateException {
- log.info("UserEventListener onPersist222 ....");
- }
-
- @Override
- public void injectCallbackRegistry(CallbackRegistry callbackRegistry) {
- log.info("UserEventListener callbackRegistry ....");
- }
-
- @Override
- public void afterPropertiesSet() throws Exception {
- log.info("init SessionFactoryImplementor {}", sessionFactory);
- // 将监听器添加到SessionFactory中
- if(sessionFactory != null) {
- sessionFactory.getSessionFactory().getServiceRegistry()
- .getService(EventListenerRegistry.class)
- .prependListeners(EventType.PERSIST, UserEventListener.class);
- }
- }
- }
执行listenerRegistryBuilder.buildRegistry( registeredEventTypes )。在该方法中,通过1.2)的builder,创建一个EventListenerRegistryImpl对象。将builder中的监听组,按类型为下标,存放在EventListenerRegistryImpl的EventListenerGroup[] eventListeners数组中。
将1.3)中的EventListenerRegistryImpl归类的监听器获取出来,按类型归类,存放到EventListenerGroup中,即集合。FastSessionServices的源码如下:
- package org.hibernate.internal;
-
- public final class FastSessionServices {
-
- public final EventListenerGroup<AutoFlushEventListener> eventListenerGroup_AUTO_FLUSH;
- public final EventListenerGroup<ClearEventListener> eventListenerGroup_CLEAR;
- public final EventListenerGroup<DeleteEventListener> eventListenerGroup_DELETE;
- public final EventListenerGroup<PersistEventListener> eventListenerGroup_PERSIST;
- public final EventListenerGroup<PersistEventListener> eventListenerGroup_PERSIST_ONFLUSH;
-
-
- FastSessionServices(SessionFactoryImpl sf) {
- Objects.requireNonNull( sf );
- final ServiceRegistryImplementor sr = sf.getServiceRegistry();
- final JdbcServices jdbcServices = sf.getJdbcServices();
- final SessionFactoryOptions sessionFactoryOptions = sf.getSessionFactoryOptions();
-
- // 获取EventListenerRegistry,在EventListenerRegistry中保存归类的监听器
- final EventListenerRegistry eventListenerRegistry = sr.getService( EventListenerRegistry.class );
- this.eventListenerGroup_AUTO_FLUSH = listeners( eventListenerRegistry, EventType.AUTO_FLUSH );
- this.eventListenerGroup_CLEAR = listeners( eventListenerRegistry, EventType.CLEAR );
- this.eventListenerGroup_DELETE = listeners( eventListenerRegistry, EventType.DELETE );
- this.eventListenerGroup_DIRTY_CHECK = listeners( eventListenerRegistry, EventType.DIRTY_CHECK );
-
- // 省略其他
- }
-
- // 省略其他
-
- }
通过SessionFactoryImpl创建SessionImpl时,在SessionImpl中保存FastSessionServices对象。
在SessionImpl中,当执行对应持久化方法时,会执行FastSessionServices对象对应类型的EventListenerGroup。
如执行persist()方法,会执行PersistEventListener::onPersist方法,默认为DefaultPersistEventListener.onPersist(),该方法会执行performSaveOrUpdate() -> entityIsPersistent() -> entityIsTransient() -> saveWithGeneratedId() -> callbackRegistry.preCreate( entity ),从而回调@PrePersist注解的方法
限于篇幅,本篇先分享到这里。以下做一个小结:
1)JPA提供了持久化的监听回调注解;
2)Spring解析实体类时,会解析实体类中添加的监听回调注解的监听器;或者实体类中的@EntityListeners注解中的监听器,并归类存放在FastSessionServices中,然后将FastSessionServices传给SessionImpl对象;
3)JPA通过SessionImpl执行持久化操作时,会调用FastSessionServices中对应操作类型的监听器,从而实现监听回调;
关于本篇内容你有什么自己的想法或独到见解,欢迎在评论区一起交流探讨下吧。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。