使用Mybatis时的重复操作
我们在使用mybatis来进行数据库的相关操作时,无论是增删改,还是查询,都需要做的就是:
1、读取mybatis.xml配置文件。
2、利用配置文件创建SqlSessionFactory类的对象。
3、利用SqlSessionFactory类的对象来获取SqlSession
4、进行数据库操作之后,关闭SqlSession。
上面这几步,如果不封装为一个工具类,那么就需要在每一个serviceImpl中写一次,当service数量较大时,代码的冗余就会比较明显。另外,上面这几步都涉及到对象的创建与销毁,如果客户端每次发起一个请求,请求处理过程中,如果涉及到多个java文件的相互配合,那么,就需要在每一个涉及到的每一个java文件中都写一次,产生不必要的开销,因为一个请求由一个线程解决,可以通过线程的共享数据来实现节约资源。
封装的Mybatis工具类
package lixin.gan.util; import java.io.IOException; import java.io.InputStream; import org.apache.ibatis.io.Resources; import org.apache.ibatis.session.SqlSession; import org.apache.ibatis.session.SqlSessionFactory; import org.apache.ibatis.session.SqlSessionFactoryBuilder; public class MyBatisUtil { private static SqlSessionFactory factory = null; private static ThreadLocal<SqlSession> threadlocal = new ThreadLocal<>(); // 静态初始块,用来创建一个SqlSessionFactory,不需要每次使用这个工具类都去创建一个工厂。 static { try{ InputStream config = Resources.getResourceAsStream("mybatis.xml"); factory = new SqlSessionFactoryBuilder().build(config); } catch (IOException e) { e.printStackTrace(); } } /** * 获取mybatis连接数据库返回的sqlsession * @return org.apache.ibatis.session.SqlSession */ public static SqlSession getSqlSession() { SqlSession sqlSession = threadlocal.get(); if (sqlSession == null) { sqlSession = factory.openSession(); threadlocal.set(sqlSession); } return sqlSession; } /** * 关闭当前线程的mybatis的sqlSession连接 */ public static void closeSqlSession() { SqlSession sqlSession = threadlocal.get(); if (sqlSession != null) { sqlSession.close(); } threadlocal.set(null); } }
封装后的小问题
封装后,可以分别调用两个静态方法getSqlSession()和closeSqlSession()来实现sqlSession的获取与销毁,但是我们在业务逻辑中,还需要手动写这两行代码,对吗,其实这还是有一点冗余的,这个时候,我们可以尝试使用OpenSessionInView的思想。
OpenSessionInView
平时的业务处理流程如下:
1、用户请求
2、serlvet接受请求
3、servlet实例化serviceImpl来处理业务
4、serviceImpl实例化mapper或者dao
上面的过程,我们可以找到一个缝隙,将获取和销毁sqlSession的操作,塞到这个缝隙中,而这个缝隙就是在1和2之间,也就是filter(过滤器)。
package lixin.gan.filter; import java.io.IOException; import javax.servlet.Filter; import javax.servlet.FilterChain; import javax.servlet.FilterConfig; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; import javax.servlet.annotation.WebFilter; import org.apache.ibatis.session.SqlSession; import lixin.gan.util.MyBatisUtil; /** * Servlet Filter implementation class OpenSessionInView */ @WebFilter("/*") public class OpenSessionInView implements Filter { @Override public void init(FilterConfig fConfig) throws ServletException { // TODO Auto-generated method stub } /** * 在正式处理请求之前,获取SqlSession * 在请求处理完毕之后,销毁SqlSession */ @Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { SqlSession sqlSession = MyBatisUtil.getSqlSession(); // 调用getSqlSession()后,ThreadLocal容器中可以通过get()来获取此处创建的sqlSession。 try { chain.doFilter(request, response); } catch(Exception e) { sqlSession.rollback(); e.printStackTrace(); } finally { MyBatisUtil.closeSqlSession(); } } @Override public void destroy() { // TODO Auto-generated method stub } }