疑问:在MyBatis中,
SqlSession
对象为什么不写在方法外部呢? 在MyBatis中,SqlSession
对象通常不推荐写在方法外部(如类成员变量或静态变量)并且在整个类中共享的原因主要包括以下几个方面:
SqlSession
不是线程安全的对象,因此每个线程都应该拥有自己的SqlSession
实例。如果在类级别上声明一个全局的SqlSession
,多线程环境下可能会导致数据竞争和不可预测的结果。SqlSession
内部持有数据库连接资源,打开连接会消耗系统资源,而长时间不关闭连接可能导致资源泄露。最佳实践是在每次数据库操作完成后立即关闭SqlSession
以释放资源。将SqlSession
放在方法内,可以在方法结束时确保及时关闭。SqlSession
对应一个数据库事务,当在一个业务逻辑中需要多个数据库操作构成一个原子事务时,应该在一个方法内创建并开启事务,完成所有操作后再提交或回滚事务,这样能保证事务的一致性。若SqlSession
是全局的,事务边界将会变得模糊,不利于精确控制。SqlSession
可以通过依赖注入的方式在每次请求或者每个方法调用时获得新的实例,这符合面向切面编程(AOP)的原则,使得代码更加模块化和易于测试。 基于以上原因,在编写测试类或实际应用中的DAO层代码时,推荐的做法是每次执行CRUD操作时,在方法内部创建SqlSession
对象,执行完必要的操作后,立即将其关闭。例如:
public void testInsert(User user) { try (SqlSession session = sqlSessionFactory.openSession()) { UserMapper mapper = session.getMapper(UserMapper.class); mapper.insert(user); session.commit(); } catch (Exception e) { // 处理异常,可能需要回滚事务 } }
上述代码展示了在方法内部获取并使用SqlSession
的最佳实践,这样可以确保每次操作都独立于其他操作,避免了资源管理和并发问题。
代码展示:
AccountDao accountDao = (AccountDao)sqlSession.getMapper(AccountDao.class);
使用前提:AccountMapper.xml文件中的namespace必须和dao接口的全限定名称一致,id必须和dao接口中方法名一致。
将service中获取dao对象的代码再次修改,如下:
代码测试:
@Test
public void testInsert() {
SqlSession sqlSession = SqlSessionUtil.openSession();
CarMapper mapper = sqlSession.getMapper(CarMapper.class);
Car car = new Car(null , "3333" , "CT5" , 30.0 , "2023-10-10" , "燃油车");
int rows = mapper.insert(car);
System.out.println("插入数据:" + rows);
sqlSession.commit();
}
扫码关注腾讯云开发者
领取腾讯云代金券
Copyright © 2013 - 2025 Tencent Cloud. All Rights Reserved. 腾讯云 版权所有
深圳市腾讯计算机系统有限公司 ICP备案/许可证号:粤B2-20090059 深公网安备号 44030502008569
腾讯云计算(北京)有限责任公司 京ICP证150476号 | 京ICP备11018762号 | 京公网安备号11010802020287
Copyright © 2013 - 2025 Tencent Cloud.
All Rights Reserved. 腾讯云 版权所有