探讨整合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();
                }
            }
        }

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

躺平程序猿

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值