MyBatis笔记——通过过滤器Filter简化创建SqlSession对象

一 提出问题:为什么要优化代码


首先,先看不使用过滤器Filter,直接在方法里面创建SqlSessionFactory工厂

public class StudentService {
	public int insStudent(Student student) {
		InputStream iStream = null;
		int index = 0;
		try {
			iStream = Resources.getResourceAsStream("mybatis.xml");
			SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(iStream);
			SqlSession session = factory.openSession();
			StudentMapper mapper = session.getMapper(StudentMapper.class);  //接口绑定
			index = mapper.insStudent(student);
			if(index > 0) {
				session.commit();   // 提交
				session.close();
			}else {
				session.rollback();  // 插入失败,回滚
				session.close();
			}
		} catch (IOException e) {
			e.printStackTrace();
		}
		return index;
	}
}

问题:每创建一个类或者写一个方法,就要重新写创建SqlSession的代码,这样代码就冗余了。而且创建工厂是一个比较消耗性能的过程,我们不能为了制造一支笔,而去创建一个笔厂,所以最好保证有且只有一个factory。

二 分析问题

  1. 怎么才能简化代码,保证只有一个工厂呢?
  2. 怎么才能在加载servlet之前就创建好SqlSession对象呢?
  3. 答案是利用过滤器Filter

三 解决问题

首先,先封装一个MyBatisUtil工具类,方便以后复用

public class MyBatisUtil {
	private static SqlSessionFactory factory;
	
	/**
	 * ThreadLocal线程容器,java的一个类,给线程绑定一个 Object 内容后,只要线程不变,可以随时取出。
	 * 通过get()方法获取设置的对象,set(Object value)设置对象到线程容器里
	 * 
	 * SqlSession对象绑定在线程里,这样就保证了过滤器Filter和Servlet里的SqlSession是同一个
	 */
	private static ThreadLocal<SqlSession> tLocal = new ThreadLocal<>();
	static {
		InputStream is;
		try {
			is = Resources.getResourceAsStream("mybatis.xml");  //加载全局配置文件
			factory = new SqlSessionFactoryBuilder().build(is);  //创建工厂
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
	/**
	 * 获取SqlSession的方法
	 * @return
	 */
	public static SqlSession getSession() {
		SqlSession session = tLocal.get();
		if(session == null) {     
			tLocal.set(factory.openSession());
		}
		return tLocal.get();
	}
	
	/**
	 * 关闭SqlSession
	 */
	public static void closeSession() {
		SqlSession session = tLocal.get();
		if(session != null) {
			session.close();
			tLocal.set(null);
		}
	}
}

创建过滤器SessionFilter类

@WebFilter("/*")
public class SessionFilter implements Filter{

	@Override
	public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
			throws IOException, ServletException {
			SqlSession session = MyBatisUtil.getSession(); //获取SqlSession对象
			try {
				chain.doFilter(request, response);
				session.commit();       //提交
			} catch (Exception e) {
				session.rollback();      //出异常,回滚到初始状态
				e.printStackTrace();
			}finally {
				MyBatisUtil.closeSession();          //关闭
			}
	}
	
}

这样只要程序一加载servlet,就必须进过过滤器Filter,从而创建SqlSession对象,只要线程不变,SqlSession对象就不变。最后,上面StudentService类里的方法就可以简化为

public class StudentService {
	public int insStudent(Student student) {
		SqlSession session = MyBatisUtil.getSession();
		StudentMapper mapper = session.getMapper(StudentMapper.class);  //接口绑定
		return mapper.insStudent(student);
	}
}

四 总结

通过过滤器Filter把创建SqlSession对象的公共代码提取出来,这样在你的项目中不管创建多少个类,多少个方法,创建SqlSession的代码只要写一遍,既简化了代码,也避免了频繁创建工厂,提高程序的效率。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值