mybatis使用mapper代理开发方法 session需要关闭吗(session.close)

如题所述

现象1:如果使用原生mybatis进行数据操作,那么必须按照以下方式使用:
SqlSession sqlSession = null;
try {
sqlSession = sqlSessionFactory.openSession();
//namespace+id
sqlSession.insert("cn.jarjar.dao.BlogMapper.insertBlog", blog);
sqlSession.commit(true)
} catch (Exception e) {
e.printStackTrace();
sqlSession.rollback(true);
} finally {
sqlSession.close();
}

也就是要像原始的java.sql.Connection对象一样,必须按照:新建连接->执行SQL->提交(查询不需要)->如果操作数据存在异常需要回滚->释放数据库连接。注意第一点和最后一点,每个SqlSession新建之后必须释放,不然会造成数据库连接泄露的危险。也就是意味着SqlSession是个有状态的对象,是无法进行复用的,所以只能局限于request或者方法的范围,也就是所谓的线程不安全。
现象2:如果使用spring集成mybatis,官方提供了整和包mybatis-spring.jar,如果完成配置之后,使用方式及其简单,简单示例如下:
//注入spring中配置的SqlSessionTemplate对象,单例
@Resource(name="sqlSessionTemplate")
public SqlSessionTemplate sqlSessionTemplate;
public void saveTestTrans(){
this.sqlSessionTemplate.selectList("testdomain.selectAnySql", "select * from my_blog where id='1'");
}

这里的SqlSessionTemplate不仅是单例的,而且不需要手工新建和关闭SqlSession
问题1:
那么问题来了,为什么mybatis-spring.jar中的SqlSessionTemplate可以被多个dao复用,而且不会造成数据连接泄露呢,并且还可以自动新建和释放数据库连接看官方解答是因为SqlSessionTemplate是线程安全的,也就是确保每个线程使用的sqlSession的唯一并不互相冲突。
首先看了一下mybatis-spring的源码,发现SqlSessionTemplate是通过代理拦截和SqlSessionHolder实现的sqlsession线程安全和自动新建和释放连接的。看构造函数函数中构建代理类,该代理类实现SqlSession接口,定义了方法拦截器,如果调用代理类实例中实现SqlSession接口定义的方法,该调用则被导向SqlSessionInterceptor的invoke方法,这个方法中自动进行了SqlSession的自动请求和释放(如果不被spring托管则自己新建和释放sqlsession,如果被spring管理则使用SqlSessionHolder进行request和relase操作)
以下网址针对SqlSessionTemplate的线程安全特性进行了详细的探究:
问题2:
然后又想到这样一个问题,虽然现在几乎所有项目都使用spring作为java程序的基本框架,如果我不使用spring管理mybatis,仅仅使用原始的mybatis,怎么样才能构建一个和SqlSessionTemplate相似的对象呢看
首先想到必须使用java的treadLocal构建一个sqlsession的对象,如ThreadLocal sqlSession = new ThreadLocal
()。
经过查找,发现mybatis自身就有这样一个类实现了类似的功能,类路径:org.apache.ibatis.session.SqlSessionManager,但是没有注释,可能存在mybatis-spring这种神器之后,mybatis放弃了对这个类的维护。
该类实现了SqlSessionFactory, SqlSession并且在其中定义了一个treadLocal的sqlssion对象,同时使用了代理拦截进行了sqlsession的自动管理,具体代码可以自己查阅,对于理解mybatis原理和java的代理机制很有帮助。

那么写个简单的程序验证一下SqlSessionManager是否真的可以保证线程安全和自动新建和释放sqlssion:TestSqlManager.java
private static SqlSession sqlSession;
public static SqlSession getSqlSessionTest(){
if(sqlSession == null){
//构建使用的SqlSessionFactory
SqlSessionFactory sqlSessionFactory = MyBatisUtil.getSqlSessionFactory();
sqlSession = SqlSessionManager.newInstance(sqlSessionFactory);
}
return sqlSession;
}
public static void main(String[] args) throws InterruptedException {
Run run = new Run();
List

threads = new ArrayList

();
for (int i = 0; i < 100; i++) {
Thread t = new Thread(run);
threads.add(t);
System.out.println("thread:{"+t.getName()+"}, start");
t.start();
}
for (Thread t : threads) {
System.out.println("thread:{"+t.getName()+"},join");
t.join();
}
}

我本机装的mysql,通过监控语句:select SUBSTRING_INDEX(host,’:’,1) as ip , count(*) from information_schema.processlist group by ip;发现执行过程中存在连接并发的情况,但是执行之后全部释放掉了。
温馨提示:内容为网友见解,仅供参考
无其他回答

Mybatis使用Mapper还用DAO层吗
mapper开发更好,原始dao开发存在以下问题:存在一定量的模板代码。比如:通过SqlSessionFactory创建SqlSession;调用SqlSession的方法操作数据库;关闭Sqlsession。存在一些硬编码。mapper层的作用是对数据库进行数据持久化操作,他的方法语句是直接针对数据库操作的现在用mybatis逆向工程生成的。mapper层,其实就是da...

JAVA SE之 MyBatis Mapper代理
Mapper代理的实现步骤如下:1. 定义接口EmployeeMapper,用于表示数据库操作的接口。2. 创建EmployeeMapper.xml映射文件,文件名应与接口名一致。3. 在映射文件中配置映射规则,注意使用#{}确保使用PreparedStatement,避免SQL注入风险。4. 在测试类中使用session的getMapper方法获取EmployeeMapper的代理对象,直...

mybatis的namespace可以绑定接口,如果不写接口,直接用session进行操作的...
首先,要明确namespace的作用,是mapper.xml中配置的作为唯一标识的名称,并没有什么特别的要求,只需要保证所有的mapper中名称空间唯一即可。注意必须有~再其次明确你所说的绑定接口,也就是使用动态代理Mapper,不需要再书写接口的实现类。这时对namesapce就有要求了,要书写对应mapper接口的全路径,也就是...

MyBatis最新面试题汇总(只看这篇就够了)
1、创建SQLSessionFactory 2、使用SQLSessionFactory创建SQLSession 3、通过SQLSession执行数据库操作 4、调用session.commit()提交事物 5、调用session.close()关闭会话 模糊查询的实现 使用like %xx%结构,推荐使用字符串拼接函数避免错误。使用Mybatis的mapper接口调用要求 确保接口方法名、输入参数类型和结果类...

Mybatis 教程之Mybatis注解开发
首先我们需要获取 SqlSession :参数设置为 true 表示开启自动提交模式。session 在注解形式的使用方式如:所以mybatis 的使用使用三部分:这里主要讲解 Mapper 层的开发规则。sql 类型主要分成 : select @Select(${sql}) , update @Update(${sql}) , insert @Insert($sql) , delete (${sql}) .Re...

mybatis的mapper.xml里面可以使用全局变量么
Mapper代理方法(程序员只需要mapper接口,相当于dao接口)Mapper接口需要遵循一些开发规范,mybatis可以自动生成mapper接口实现类代理对象。开发规范:1.在mapper.xml中namespace等于mapper.Java接口地址(<mapper namespace="com.zucc.dao.UserMapper">)2.Mapper.java接口中的方法名和mapper.xml中statement的id...

mybatis中xml映射和方法注解两种配置sql语句的方式是否可以同时存在...
不能进行同时设置。执行会找不到接口的mapper代理工厂。mybatis会先解析xml文件,将解析后的sql封装在mapperstament中并放进Configuration的mappedStatements中,将命名空间和方法名(也就是id)作为key,mappedStatements是个自定义map。然后生成接口的代理工程,生产代理工厂后会解析注解,解析完注解,也会生成...

...session = sqlSessionFactory.openSession(); 报空指针异常_百度知 ...
你得先把创建sqlSessionFactory那段代码放入static代码块里面吧 保证在类初始化的时候就创建好sqlSessionFactory, 还有一种原因就是你没有导入mybatis的jar包

Java框架MyBatis工作流程是怎样的?
无论是用过的hibernate,mybatis,你都可以法相他们有一个共同点:从配置文件(通常是XML配置文件中)得到 sessionfactory.由sessionfactory 产生 session 在session 中完成对数据的增删改查和事务提交等.在用完之后关闭session 。在java 对象和 数据库之间有做mapping 的配置文件,也通常是xml 文件。功能架构...

Mybatis高频面试题总结(2022最新)
Mybatis通过RowBounds进行内存分页,支持直接在SQL中添加物理分页参数或使用插件实现。分页插件利用动态代理和责任链模式修改SQL实现物理分页。插件是通过实现Interceptor接口,指定拦截的接口和方法,然后在配置文件中启用。Mybatis支持association和collection的延迟加载,通过CGLIB创建代理对象来实现。{ } 和 ${ ...

相似回答