说明
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
--Posted from Rpc