探讨整合Spring前提下Jpa的EntityManager和Mybatis的SqlSession在不加@Transactional时会不会占用连接不释放(待完善)

探讨整合Spring前提下Jpa的EntityManager和Mybatis的SqlSession在不加@Transactional时会不会占用连接不释放(核心方法TransactionSynchronizationManager#isSynchronizationActive()用于判断是否开启事务);
EntityManager会主动释放连接,
SqlSession不会主动释放连接,
但是Mapper动态代理类(引用了mybatis-spring.jar整合后产生的Mapper代理类中的SqlSession是代理类SqlSessionTemplate)会主动释放连接即SqlSessionTemplate会主动释放连接

SqlSession (此时连接池数量为2)

demo方法加了 @Transactional下面三个线程可以全部执行打印三个1;不加@Transactional只能执行两个,说明SqlSession不会主动释放连接。

@Service
public class UserServiceImpl implements UserService {
    
    
    @Autowired
    private UserMapper userMapper;
    @Autowired
    private SqlSessionFactory sessionFactory;
 	
 
    @Transactional
    public void demo(){
    
    
        User user1=new User();
        user1.setId("1");
        user1.setName("aaa");
        int update = sessionFactory.openSession().update("com.lago.mapper.UserMapper.updateUser", user1);
        System.out.println(update);
    }

    /**
     *  探讨整合Spring前提下Jpa的EntityManager和Mybatis的SqlSession在不加@Transactional时会不会占用连接不释放
     * @param args
     */
    public static void main(String[] args) {
    
    
       ClassPathXmlApplicationContext classPathXmlApplicationContext=new ClassPathXmlApplicationContext("applicationContext.xml");
        UserService userService = classPathXmlApplicationContext.getBean(UserService.class);
        User user1=new User();
        user1.setId("1");
        user1.setName("aaa");
        Thread thread = new Thread(new Runnable() {
    
    
            @Override
            public void run() {
    
    
                userService.demo();
            }
        });

        Thread thread2 = new Thread(new Runnable() {
    
    
            @Override
            public void run() {
    
    
                userService.demo();
            }
        });

        Thread thread3 = new Thread(new Runnable() {
    
    
            @Override
            public void run() {
    
    
                userService.demo();
            }
        });

        thread.start();
        thread2.start();
        thread3.start();
    }
}

Mapper的动态代理类或SqlSessionTemplate(此时连接池数量为2)

mapper动态代理类里的SqlSession其实是SqlSessionTemplate实例,SqlSessionTemplate是个代理类执行增删改成时会进入invoke方法
代理类在最后也有fianlly方法执行资源的释放(在没有@Transactional事务的情况下)。

SqlsessionTemplate.class

public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
    
    
            SqlSession sqlSession = SqlSessionUtils.getSqlSession(SqlSessionTemplate.this.sqlSessionFactory, SqlSessionTemplate.this.executorType, SqlSessionTemplate.this.exceptionTranslator);

            Object unwrapped;
            try {
    
    
                Object result = method.invoke(sqlSession, args);
                if (!SqlSessionUtils.isSqlSessionTransactional(sqlSession, SqlSessionTemplate.this.sqlSessionFactory)) {
    
    
                    sqlSession.commit(true);
                }

                unwrapped = result;
            } catch (Throwable var11) {
    
    
                unwrapped = ExceptionUtil.unwrapThrowable(var11);
                if (SqlSessionTemplate.this.exceptionTranslator != null && unwrapped instanceof PersistenceException) {
    
    
                    SqlSessionUtils.closeSqlSession(sqlSession, SqlSessionTemplate.this.sqlSessionFactory);
                    sqlSession = null;
                    Throwable translated = SqlSessionTemplate.this.exceptionTranslator.translateExceptionIfPossible((PersistenceException)unwrapped);
                    if (translated != null) {
    
    
                        unwrapped = translated;
                    }
                }

                throw (Throwable)unwrapped;
            } finally {
    
    
                if (sqlSession != null) {
    
    
                    SqlSessionUtils.closeSqlSession(sqlSession, SqlSessionTemplate.this.sqlSessionFactory);
                }

            }

            return unwrapped;
        }

EntityManager (此时连接池数量为2)

EntityManager是个代理类执行find方法时进入代理类的invoke方法,最后有个finally方法判断是新的EntityManager是自动释放资源(此处)。 EntityManagerFactoryUtils.doGetTransactionalEntityManager(this.targetFactory, this.properties, this.synchronizedWithTransaction);在有无声明式事务时有所不同,后面再研究。

SharedEntityManagerCreator.class
 public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
    
    
            if (method.getName().equals("equals")) {
    
    
                return proxy == args[0];
            } else if (method.getName().equals("hashCode")) {
    
    
                return this.hashCode();
            } else if (method.getName().equals("toString")) {
    
    
                return "Shared EntityManager proxy for target factory [" + this.targetFactory + "]";
            } else if (method.getName().equals("getEntityManagerFactory")) {
    
    
                return this.targetFactory;
            } else if (!method.getName().equals("getCriteriaBuilder") && !method.getName().equals("getMetamodel")) {
    
    
                if (method.getName().equals("unwrap")) {
    
    
                    Class<?> targetClass = (Class)args[0];
                    if (targetClass != null && targetClass.isInstance(proxy)) {
    
    
                        return proxy;
                    }
                } else {
    
    
                    if (method.getName().equals("isOpen")) {
    
    
                        return true;
                    }

                    if (method.getName().equals("close")) {
    
    
                        return null;
                    }

                    if (method.getName().equals("getTransaction")) {
    
    
                        throw new IllegalStateException("Not allowed to create transaction on shared EntityManager - use Spring transactions or EJB CMT instead");
                    }
                }
				// 此处有无事务不一样 关注下TransactionSynchronizationManager#isSynchronizationActive()
                EntityManager target = EntityManagerFactoryUtils.doGetTransactionalEntityManager(this.targetFactory, this.properties, this.synchronizedWithTransaction);
                if (method.getName().equals("getTargetEntityManager")) {
    
    
                    if (target == null) {
    
    
                        throw new IllegalStateException("No transactional EntityManager available");
                    } else {
    
    
                        return target;
                    }
                } else {
    
    
                    if (method.getName().equals("unwrap")) {
    
    
                        Class<?> targetClass = (Class)args[0];
                        if (targetClass == null) {
    
    
                            return target != null ? target : proxy;
                        }

                        if (target == null) {
    
    
                            throw new IllegalStateException("No transactional EntityManager available");
                        }
                    } else if (SharedEntityManagerCreator.transactionRequiringMethods.contains(method.getName()) && (target == null || !TransactionSynchronizationManager.isActualTransactionActive() && !target.getTransaction().isActive())) {
    
    
                        throw new TransactionRequiredException("No EntityManager with actual transaction available for current thread - cannot reliably process '" + method.getName() + "' call");
                    }

                    boolean isNewEm = false;
                    if (target == null) {
    
    
                        this.logger.debug("Creating new EntityManager for shared EntityManager invocation");
                        target = !CollectionUtils.isEmpty(this.properties) ? this.targetFactory.createEntityManager(this.properties) : this.targetFactory.createEntityManager();
                        isNewEm = true;
                    }

                    Object var18;
                    try {
    
    
                        Object result = method.invoke(target, args);
                        if (result instanceof Query) {
    
    
                            Query query = (Query)result;
                            if (isNewEm) {
    
    
                                Class<?>[] ifcs = ClassUtils.getAllInterfacesForClass(query.getClass(), this.proxyClassLoader);
                                result = Proxy.newProxyInstance(this.proxyClassLoader, ifcs, new SharedEntityManagerCreator.DeferredQueryInvocationHandler(query, target));
                                isNewEm = false;
                            } else {
    
    
                                EntityManagerFactoryUtils.applyTransactionTimeout(query, this.targetFactory);
                            }
                        }

                        var18 = result;
                    } catch (InvocationTargetException var14) {
    
    
                        throw var14.getTargetException();
                    } finally {
    
    
                        if (isNewEm) {
    
    
                            EntityManagerFactoryUtils.closeEntityManager(target);
                        }

                    }

                    return var18;
                }
            } else {
    
    
                try {
    
    
                    return EntityManagerFactory.class.getMethod(method.getName()).invoke(this.targetFactory);
                } catch (InvocationTargetException var13) {
    
    
                    throw var13.getTargetException();
                }
            }
        }

猜你喜欢

转载自blog.csdn.net/yangxiaofei_java/article/details/113781579
今日推荐