说明
MyBatis版本:3.5.1
相关历史文章(阅读本文之前,您可能需要先看下之前的系列)
Spring Boot MyBatis最全教程:你值得拥有MyBatis能脱离Spring吗一图纵览MyBatis的工作原理
前言
通过上面我们已经可以构建了SqlSessionFactory,接下来的话就是要怎么获取一个SqlSession。
一、分析
对于SqlSession的构建的话,需要有一个属性Configuration,这个属性在上面的SqlSessionFactory已经有了;另外对于SqlSession的真正的Sql执行是交给了Executor,Executor是真正和数据库进行交互了,所以需要将数据库配置信息传给Executor。
二、编码
2.1 Executor
构造SqlSession需要有Executor,我们先创建一个Executor接口:
package com.kfit.mybatis.session; import java.util.List; import com.kfit.mybatis.config.MapperStatement; public interface Executor { <E> List<E> query(MapperStatement ms, Object parameter); }
我们实现一个最基本的SimpleExecutor:
package com.kfit.mybatis.session.impl; import java.util.List; import com.kfit.mybatis.config.JdbcProperties; import com.kfit.mybatis.config.MapperStatement; import com.kfit.mybatis.session.Executor; public class SimpleExecutor implements Executor { private JdbcProperties jdbcProperties; public SimpleExecutor(JdbcProperties jdbcProperties) { this.jdbcProperties = jdbcProperties; } public <E> List<E> query(MapperStatement ms, Object parameter) { //具体的方法待实现 return null; } }
说明:
(1)这里我们实现了最基本的Simple,在MyBatis有3种情况需要处理,我们实现最简单的方式。
(2)这里我们接收了jdbcproperties为了之后直接进行数据库的连接操作,在mybatis数据库的连接关闭,提交,回滚是有一个事务类Transaction。
2.2 SqlSessionFactory
在SqlSessionFactory中添加一个获取SqlSession的方法:
public interface SqlSessionFactory { public Configuration getConfiguration(); public SqlSession openSession(); }
在DefaultSqlSessionFactory实现openSession()方法:
public SqlSession openSession() { Executor executor = new SimpleExecutor(configuration.getJdbcProperties()); SqlSession sqlSession = new DefaultSqlSession(configuration, executor); return sqlSession; }
2.3 SimpleExecutor数据库操作
我们这个对数据库操作的核心代码:
package com.kfit.mybatis.session.impl; import java.lang.reflect.Field; import java.lang.reflect.Type; import java.sql.Connection; import java.sql.DriverManager; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.util.ArrayList; import java.util.List; import com.kfit.mybatis.config.JdbcProperties; import com.kfit.mybatis.config.MapperStatement; import com.kfit.mybatis.session.Executor; public class SimpleExecutor implements Executor { private JdbcProperties jdbcProperties; public SimpleExecutor(JdbcProperties jdbcProperties) { this.jdbcProperties = jdbcProperties; } public <E> List<E> query(MapperStatement ms, Object parameter) { List<E> ret = new ArrayList<E>(); // 具体的方法待实现 try { // 加载驱动 Class.forName(jdbcProperties.getDriver()); } catch (ClassNotFoundException e) { e.printStackTrace(); } Connection connection = null; PreparedStatement preparedStatement = null; ResultSet resultSet = null; try { // 获取连接 connection = DriverManager.getConnection(jdbcProperties.getUrl(), jdbcProperties.getUsername(), jdbcProperties.getPassword()); // 预编译sql语句 preparedStatement = connection.prepareStatement(ms.getSql()); // 处理sql语句中的占位符 parameterize(preparedStatement, parameter); // 执行sql语句 resultSet = preparedStatement.executeQuery(); // 处理结果 handlerResultSet(resultSet, ret, ms.getResultType()); } catch (SQLException e) { e.printStackTrace(); } return ret; } private void parameterize(PreparedStatement preparedStatement, Object parameter) throws SQLException { if (parameter instanceof String) { preparedStatement.setString(1, (String) parameter); } else if (parameter instanceof Long) { preparedStatement.setLong(1, (Long) parameter); } else if (parameter instanceof Integer) { preparedStatement.setInt(1, (Integer) parameter); } } private <E> void handlerResultSet(ResultSet resultSet, List<E> ret, String className) { Class<E> clazz = null; try { clazz = (Class<E>) Class.forName(className); } catch (ClassNotFoundException e) { e.printStackTrace(); } try { while (resultSet.next()) { // 通过反射实例化对象 Object entity = clazz.newInstance(); // 使用反射工具将resultSet中的数据填充到entity中 // id,name,sex,age // 获取实体类的所有属性,返回Field数组 Field[] fields = clazz.getDeclaredFields(); for (Field field : fields) { field.setAccessible(true); String fname = field.getName(); Type type = field.getGenericType(); if (type.toString().equals("class java.lang.String")) { String column = resultSet.getString(fname); field.set(entity, column); }else if (type.toString().equals("long")) { Long column = resultSet.getLong(fname); field.set(entity, column); } } ret.add((E) entity); } } catch (SQLException e) { e.printStackTrace(); } catch (InstantiationException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } } }
说明:
(1)在MyBatis中这个代码是分好几个类进行处理的,这里为了讲解方便,统一放在一个类中。
(2)数据库的连接操作:这里使用jdbc连接数据库获取到connection进行操作。
(3)使用泛型处理返回的结果(handlerResultSet)。
2.4 SqlSession的方法
到这里,我们就可以编写SqlSession的方法了,这里定义两个方法SelectOne和SelectList();
public interface SqlSession { <T> T selectOne(String statement, Object parameter); <E> List<E> selectList(String statement); <E> List<E> selectList(String statement, Object parameter); }
对应的DefaultSqlSession:
package com.kfit.mybatis.session.impl; import java.util.List; import com.kfit.mybatis.config.Configuration; import com.kfit.mybatis.session.Executor; import com.kfit.mybatis.session.SqlSession; public class DefaultSqlSession implements SqlSession { private Configuration configuration; private Executor executor; public DefaultSqlSession(Configuration configuration,Executor executor) { this.configuration= configuration; this.executor = executor; } public <E> List<E> selectList(String statement) { return executor.query(configuration.getMapperStatement(statement),null); } public <E> List<E> selectList(String statement,Object parameter) { return executor.query(configuration.getMapperStatement(statement), parameter); } public <T> T selectOne(String statement,Object parameter) { List<T> list = executor.query(configuration.getMapperStatement(statement),parameter); if(list.size()>0) { return list.get(0); } return null; } }
说明:DefaultSqlSession的具体处理交给了Executor,所以这里的具体的实现就比较简单了。
2.5 测试下
在main方法来进行测试一下吧:
public static void main(String[] args) { String resource = "mybatis-config.xml"; InputStream inputStream = App.class.getClassLoader().getResourceAsStream(resource); SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream); System.out.println(sqlSessionFactory); System.out.println(sqlSessionFactory.getConfiguration().getJdbcProperties().getUrl()); SqlSession sqlSession = sqlSessionFactory.openSession(); Demo demo = null; List<Demo> demos = null; //使用sqlSession直接查询 demo = sqlSession.selectOne("com.kfit.mybatis.demo.mapper.DemoMapper.getById",1L); System.out.println(demo); demos = sqlSession.selectList("com.kfit.mybatis.demo.mapper.DemoMapper.getAll"); System.out.println(demos); }
这个方法和之前写mybatis的使用方式上是一模一样的,运行看下效果吧:
Demo[id=1, name=张三1]
[Demo [id=1, name=张三1], Demo [id=9, name=张三], Demo [id=10, name=张三], Demo [id=11, name=张三], Demo [id=12, name=张三], Demo [id=13, name=张三]]
看到如此帅气的结果,这是爽歪歪,厉害了我的哥。本篇就先介绍到这里,下一篇我们将会介绍无敌的Mapper实现。
我就是我,是颜色不一样的烟火。
我就是我,是与众不同的小苹果。
à悟空学院:http://t.cn/Rg3fKJD
学院中有Spring Boot相关的课程!点击「阅读原文」进行查看!
SpringBoot视频:http://t.cn/R3QepWG
Spring Cloud视频:http://t.cn/R3QeRZc
SpringBoot Shiro视频:http://t.cn/R3QDMbh
SpringBoot交流平台:http://t.cn/R3QDhU0
SpringData和JPA视频:http://t.cn/R1pSojf
SpringSecurity5.0视频:http://t.cn/EwlLjHh
Sharding-JDBC分库分表实战:http://t.cn/E4lpD6e