一文搞懂mybatis Executor执行器体系
众所周知mybatis是目前主流的持久层框架,使用广泛。先来看下mybatis执行流程

接下来我们再复习下JDBC连接

代码演示
1 private Properties prop = new Properties();; 2 3 private Connection connection; 4 5 6 // 获取数据库连接 7 @Before 8 public void init() throws SQLException, IOException { 9 prop.load(this.getClass().getResourceAsStream("/app.properties")); 10 String URL = String.valueOf(prop.get("jdbc.url")); 11 String USERNAME = String.valueOf(prop.get("jdbc.username"));; 12 String PASSWORD = String.valueOf(prop.get("jdbc.password"));; 13 connection = DriverManager.getConnection(URL, USERNAME, PASSWORD); 14 } 15 16 @Test 17 public void jdbcTest() throws SQLException { 18 String sql = "SELECT * FROM user "; 19 // 解析sql 20 PreparedStatement sql1 = connection.prepareStatement(sql); 21 // 执行sql语句 22 sql1.execute(); 23 // 获取执行结果 24 ResultSet resultSet = sql1.getResultSet(); 25 while (resultSet.next()) { 26 System.out.println(resultSet.getString(2)); 27 } 28 resultSet.close(); 29 // 关闭连接 30 sql1.close(); 31 }
接下来着重介绍下下Executor执行器体系

Executor类图

Executor是MyBatis的SQL顶层执行器接口,声明了对数据库所有的增删改查操作。其中 query()和queryCursor()方法用于执行查询操作,update()方法用于执行插入、删除、修改操作。
BaseExecutor是Executor的抽象实现类,采用模板设计模式,它声明的抽象方法由子类SimpleExecutor、ReuseExecutor、BatchExecutor实现。
1 protected abstract int doUpdate(MappedStatement ms, Object parameter) 2 throws SQLException; 3 4 protected abstract List<BatchResult> doFlushStatements(boolean isRollback) 5 throws SQLException; 6 7 protected abstract <E> List<E> doQuery(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) 8 throws SQLException; 9 10 protected abstract <E> Cursor<E> doQueryCursor(MappedStatement ms, Object parameter, RowBounds rowBounds, BoundSql boundSql) 11 throws SQLException;
SimpleExecutor是基础的Executor,能够完成基本的增删改查操作
1 private static Configuration configuration; 2 private static Transaction jdbcTransaction; 3 private static MappedStatement ms; 4 private static SqlSessionFactory factory; 5 6 @Before 7 public void init() throws IOException { 8 // 获取构建器 9 SqlSessionFactoryBuilder factoryBuilder = new SqlSessionFactoryBuilder(); 10 // 解析XML 并构造会话工厂 11 factory = factoryBuilder.build(Resources.getResourceAsStream("mybatis-config.xml")); 12 configuration = factory.getConfiguration(); 13 jdbcTransaction = new JdbcTransaction(factory.openSession().getConnection()); 14 // 获取SQL映射 15 ms = configuration.getMappedStatement("org.coderead.mybatis.UserMapper.selectByid"); 16 } 17 18 // 简单执行器测试 19 @Test 20 public void simpleTest() throws SQLException { 21 SimpleExecutor executor = new SimpleExecutor(configuration, jdbcTransaction); 22 List<Object> list = executor.doQuery(ms, 10, RowBounds.DEFAULT, 23 SimpleExecutor.NO_RESULT_HANDLER, ms.getBoundSql(10)); 24 25 executor.doQuery(ms, 10, RowBounds.DEFAULT, 26 SimpleExecutor.NO_RESULT_HANDLER, ms.getBoundSql(10)); 27 System.out.println(list.get(0)); 28 }
ResueExecutor对JDBC中的Statement对象做了缓存,当执行相同的SQL语句时,直接从缓存中取出Statement对象进行复用,避免了频繁创建和销毁Statement对象,从而提升系统性能,这是享元思想的应用。
1 private static Configuration configuration; 2 private static Transaction jdbcTransaction; 3 private static MappedStatement ms; 4 private static SqlSessionFactory factory; 5 6 @Before 7 public void init() throws IOException { 8 // 获取构建器 9 SqlSessionFactoryBuilder factoryBuilder = new SqlSessionFactoryBuilder(); 10 // 解析XML 并构造会话工厂 11 factory = factoryBuilder.build(Resources.getResourceAsStream("mybatis-config.xml")); 12 configuration = factory.getConfiguration(); 13 jdbcTransaction = new JdbcTransaction(factory.openSession().getConnection()); 14 // 获取SQL映射 15 ms = configuration.getMappedStatement("org.coderead.mybatis.UserMapper.selectByid"); 16 } 17 // 重用执行器 18 @Test 19 public void ReuseTest() throws SQLException { 20 ReuseExecutor executor = new ReuseExecutor(configuration, jdbcTransaction); 21 List<Object> list = executor.doQuery(ms, 10, RowBounds.DEFAULT, 22 SimpleExecutor.NO_RESULT_HANDLER, ms.getBoundSql(10)); 23 // 相同的SQL 会缓存对应的 PrepareStatement-->缓存周期:会话 24 executor.doQuery(ms, 10, RowBounds.DEFAULT, 25 SimpleExecutor.NO_RESULT_HANDLER, ms.getBoundSql(10)); 26 System.out.println(list.get(0)); 27 }
BatchExecutor则会对调用同一个Mapper执行的update、insert和delete操作,调用Statement对象的批量操作功能。
1 private static Configuration configuration; 2 private static Transaction jdbcTransaction; 3 private static MappedStatement ms; 4 private static SqlSessionFactory factory; 5 6 @Before 7 public void init() throws IOException { 8 // 获取构建器 9 SqlSessionFactoryBuilder factoryBuilder = new SqlSessionFactoryBuilder(); 10 // 解析XML 并构造会话工厂 11 factory = factoryBuilder.build(Resources.getResourceAsStream("mybatis-config.xml")); 12 configuration = factory.getConfiguration(); 13 jdbcTransaction = new JdbcTransaction(factory.openSession().getConnection()); 14 // 获取SQL映射 15 ms = configuration.getMappedStatement("org.coderead.mybatis.UserMapper.selectByid"); 16 } 17 // 批处理执行器 18 @Test 19 public void BatchTest() throws SQLException { 20 BatchExecutor executor = new BatchExecutor(configuration, jdbcTransaction); 21 MappedStatement setName = configuration 22 .getMappedStatement("org.coderead.mybatis.UserMapper.setName"); 23 Map param = new HashMap<>(); 24 param.put("arg0", 10); 25 param.put("arg1", "鲁班大叔 is good man"); 26 executor.doUpdate(setName, param); //设置 27 executor.doUpdate(setName, param);// 设置 28 executor.doFlushStatements(false); 29 }
另外,我们知道MyBatis支持一级缓存和二级缓存,当MyBatis开启了二级缓存功能时,会使用CachingExecutor对SimpleExecutor、ResueExecutor、BatchExecutor进行装饰,为查询操作增加二级缓存功能,这是装饰器模式的应用。
1 private static Configuration configuration; 2 private static Transaction jdbcTransaction; 3 private static MappedStatement ms; 4 private static SqlSessionFactory factory; 5 6 @Before 7 public void init() throws IOException { 8 // 获取构建器 9 SqlSessionFactoryBuilder factoryBuilder = new SqlSessionFactoryBuilder(); 10 // 解析XML 并构造会话工厂 11 factory = factoryBuilder.build(Resources.getResourceAsStream("mybatis-config.xml")); 12 configuration = factory.getConfiguration(); 13 jdbcTransaction = new JdbcTransaction(factory.openSession().getConnection()); 14 // 获取SQL映射 15 ms = configuration.getMappedStatement("org.coderead.mybatis.UserMapper.selectByid"); 16 } 17 @Test 18 public void cacheExecutorTest() throws SQLException { 19 // BaseExecutor 20 Executor executor = new SimpleExecutor(configuration, jdbcTransaction); 21 // 装饰器模式 22 Executor cachingExecutor = new CachingExecutor(executor);// 二级缓存相关逻辑 执行数据操作逻辑 23 24 cachingExecutor.query(ms, 10, RowBounds.DEFAULT, Executor.NO_RESULT_HANDLER); 25 cachingExecutor.commit(true); 26 // 提交之后才会更新 27 cachingExecutor.query(ms, 10, RowBounds.DEFAULT, Executor.NO_RESULT_HANDLER); 28 29 }

浙公网安备 33010602011771号