这篇文章的开头,写给我的兄弟: 在程序的世界,只有实践才会得到自己想要的答案。 再高明的计算机,再高明的工具,都无法将空的代码执行成最美的秘密。
上一章简单介绍了MyBatis的Mapper 代理的增删改查操作(三),如果没有看过,请观看上一章。
一. MyBatis 在创建的过程中,所使用到的重要类
在创建Mapper 的过程中,所使用到的工具类 SqlSessionFactoryUtils 。
package com.yjl.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;
/**
@author:两个蝴蝶飞
@date: 2019年6月15日 上午11:13:26
@Description 类的相关描述
*/
public class SqlSessionFactoryUtils {
/*创建SqlSession的工厂 SqlSessionFactory对象*/
private static SqlSessionFactory sqlSessionFactory=null;
private SqlSessionFactoryUtils(){
}
/**
* 单例模式 获取实例
* @author 两个蝴蝶飞
* @return
*/
public static SqlSessionFactory getInstance(){
synchronized(SqlSessionFactoryUtils.class){
if(sqlSessionFactory==null){
InputStream input=null;
// Mybatis 核心配置文件名
String resource_name="SqlMapConfig.xml";
try {
input=Resources.getResourceAsStream(resource_name);
sqlSessionFactory=new SqlSessionFactoryBuilder().build(input);
} catch (IOException e) {
e.printStackTrace();
}
}
}
return sqlSessionFactory;
}
/**
*
* @author 两个蝴蝶飞
* @return 获取当前的Session
*/
public static SqlSession getSession(){
if(sqlSessionFactory==null){
getInstance();
}
return sqlSessionFactory.openSession();
}
}
在创建的过程中,使用到了 SqlSessionFactoryBuilder 类,SqlSessionFactory 接口,SqlSession 接口,SqlMapper 接口。
用一张图表示就是:
下面,简单讲解一下,这几个类的使用。
二. SqlSessionFactoryBuilder
通过调用. builder(资源文件inputstream) 来达到创建SqlSessionFactory 工厂.
package org.apache.ibatis.session;
import java.io.IOException;
import java.io.InputStream;
import java.io.Reader;
import java.util.Properties;
import javax.security.auth.login.Configuration;
public class SqlSessionFactoryBuilder {
//调用字符流创建 SqlSessionFactory 工厂。
public SqlSessionFactory build(Reader reader) {
return build(reader, null, null);
}
public SqlSessionFactory build(Reader reader, String environment) {
return build(reader, environment, null);
}
public SqlSessionFactory build(Reader reader, Properties properties) {
return build(reader, null, properties);
}
public SqlSessionFactory build(Reader reader, String environment, Properties properties) {
try {
XMLConfigBuilder parser = new XMLConfigBuilder(reader, environment, properties);
return build(parser.parse());
} catch (Exception e) {
throw ExceptionFactory.wrapException("Error building SqlSession.", e);
} finally {
ErrorContext.instance().reset();
try {
reader.close();
} catch (IOException localIOException1) {
}
}
}
// 调用字节流 创建SqlSessionFactory 工厂
public SqlSessionFactory build(InputStream inputStream) {
return build(inputStream, null, null);
}
public SqlSessionFactory build(InputStream inputStream, String environment) {
return build(inputStream, environment, null);
}
public SqlSessionFactory build(InputStream inputStream, Properties properties) {
return build(inputStream, null, properties);
}
public SqlSessionFactory build(InputStream inputStream, String environment, Properties properties) {
try {
XMLConfigBuilder parser = new XMLConfigBuilder(inputStream, environment, properties);
return build(parser.parse());
} catch (Exception e) {
throw ExceptionFactory.wrapException("Error building SqlSession.", e);
} finally {
ErrorContext.instance().reset();
try {
inputStream.close();
} catch (IOException localIOException1) {
}
}
}
// 采用代码形式,构建Configuration 对象,来创建工厂。
public SqlSessionFactory build(Configuration config) {
return new DefaultSqlSessionFactory(config);
}
}
SqlSessionFactoryBuilder 会根据配置信息或者代码来生成SqlSessionFactory 。
提供了三种方式, 字符流,字节流, 和代码Configuration 类三种形式来创建SqlSessionFactory 类。
三. SqlSessionFactory 类
package org.apache.ibatis.session;
import java.sql.Connection;
public abstract interface SqlSessionFactory
{
//打开openSession()
public abstract SqlSession openSession();
public abstract SqlSession openSession(boolean paramBoolean);
//根据连接创建
public abstract SqlSession openSession(Connection paramConnection);
//根据事务
public abstract SqlSession openSession(TransactionIsolationLevel paramTransactionIsolationLevel);
public abstract SqlSession openSession(ExecutorType paramExecutorType);
public abstract SqlSession openSession(ExecutorType paramExecutorType, boolean paramBoolean);
public abstract SqlSession openSession(ExecutorType paramExecutorType, TransactionIsolationLevel paramTransactionIsolationLevel);
public abstract SqlSession openSession(ExecutorType paramExecutorType, Connection paramConnection);
//获取代码配置的Configuration 对象信息
public abstract Configuration getConfiguration();
}
主要用于创建SqlSession 接口。 用 openSession() 方法即可。
有两个实现类: DefaultSqlSessionFactory 和SqlSessionManager。 目前用前者, SqlSessionManager 还没有使用。
有两个方式 创建SqlSessionFactory ,一种是配置文件的方式,另外一种是代码的方式, 即Configuration 类,
org.apache.ibatis.session.Configuration
后面还有很多, 定义了大量的 setter 和getter 方法,来设置和获取配置的信息。 与xml 配置的属性是一样的。 Configuration 对象存储在整个Mybatis 运行的生命周期内,以便重复的读取和运用。
三.一 xml 配置文件的方式创建SqlSessionFactory
就是前三章所用的形式。
<?xml version="1.0" encoding="UTF-8"?>
<!-- 引入约束 -->
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<!-- 配置别名 -->
<typeAliases>
<typeAlias type="com.yjl.pojo.User" alias="user"/>
</typeAliases>
<!-- 开发环境 development -->
<environments default="development">
<environment id="development">
<!-- 事务管理 -->
<transactionManager type="JDBC"></transactionManager>
<!-- 数据源 ,为pooled 连接池 -->
<dataSource type="pooled">
<property name="driver" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/mybatis?characterEncoding=utf8"/>
<property name="username" value="root"/>
<property name="password" value="abc123"/>
</dataSource>
</environment>
</environments>
<mappers>
<!-- 引入文件资源 -->
<mapper resource="com/yjl/mapper/UserMapper.xml"/>
</mappers>
</configuration>
三.二 代码样式创建SqlSessionFactory
package com.yjl.util;
import javax.sql.DataSource;
import org.apache.ibatis.datasource.pooled.PooledDataSource;
import org.apache.ibatis.mapping.Environment;
import org.apache.ibatis.session.Configuration;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.apache.ibatis.transaction.TransactionFactory;
import org.apache.ibatis.transaction.jdbc.JdbcTransactionFactory;
import com.yjl.mapper.UserMapper;
import com.yjl.pojo.User;
/**
@author:两个蝴蝶飞
@date: 2019年6月15日 上午11:13:26
@Description 类的相关描述
*/
public class SqlSessionFactoryUtils {
/*创建SqlSession的工厂 SqlSessionFactory对象*/
private static SqlSessionFactory sqlSessionFactory=null;
private SqlSessionFactoryUtils(){
}
/**
* 单例模式 获取实例
* @author 两个蝴蝶飞
* @return
*/
public static SqlSessionFactory getInstance(){
synchronized(SqlSessionFactoryUtils.class){
if(sqlSessionFactory==null){
try {
String driver = "com.mysql.jdbc.Driver";
String url = "jdbc:mysql://localhost:3306/mybatis?characterEncoding=utf8";
String username="root";
String password="abc123";
//设置数据库的数据源
DataSource dataSource =new PooledDataSource(driver,url,username,password);
//事务为jdbc处理
TransactionFactory transactionFactory = new JdbcTransactionFactory();
//环境为development 环境
Environment environment = new Environment("development", transactionFactory, dataSource);
//创建Configuration
Configuration configuration = new Configuration(environment);
//设置别名
configuration.getTypeAliasRegistry().registerAlias("user",User.class);
//配置文件 UserMapper
configuration.addMapper(UserMapper.class);
//创建SqlSessionFactory
sqlSessionFactory=new SqlSessionFactoryBuilder().build(configuration);
} catch (Exception e) {
e.printStackTrace();
}
}
}
return sqlSessionFactory;
}
/**
*
* @author 两个蝴蝶飞
* @return 获取当前的Session
*/
public static SqlSession getSession(){
if(sqlSessionFactory==null){
getInstance();
}
return sqlSessionFactory.openSession();
}
}
测试方法
@Test
public void findAllTest(){
SqlSession sqlSession=SqlSessionFactoryUtils.getSession();
UserMapper userMapper=sqlSession.getMapper(UserMapper.class);
List<User> allList=userMapper.findAll();
allList.forEach(n ->System.out.println(n));
}
正常的查询了出来, 代码创建是没有错的。
但是代码创建时,是硬编码写入,并且别名和映射文件都是写入的,每次都要进行修改。
建议,使用XML 配置的方式。
四. SqlSession 接口
package org.apache.ibatis.session;
import java.io.Closeable;
import java.sql.Connection;
import java.util.List;
import java.util.Map;
import org.apache.ibatis.cursor.Cursor;
import org.apache.ibatis.executor.BatchResult;
public abstract interface SqlSession
extends Closeable
{
// 查询单个对象
public abstract <T> T selectOne(String paramString);
public abstract <T> T selectOne(String paramString, Object paramObject);
//查询多个集合对象
public abstract <E> List<E> selectList(String paramString);
public abstract <E> List<E> selectList(String paramString, Object paramObject);
public abstract <E> List<E> selectList(String paramString, Object paramObject, RowBounds paramRowBounds);
// 查询Map 形式
public abstract <K, V> Map<K, V> selectMap(String paramString1, String paramString2);
public abstract <K, V> Map<K, V> selectMap(String paramString1, Object paramObject, String paramString2);
public abstract <K, V> Map<K, V> selectMap(String paramString1, Object paramObject, String paramString2, RowBounds paramRowBounds);
// 查询光标
public abstract <T> Cursor<T> selectCursor(String paramString);
public abstract <T> Cursor<T> selectCursor(String paramString, Object paramObject);
public abstract <T> Cursor<T> selectCursor(String paramString, Object paramObject, RowBounds paramRowBounds);
// 利用ResultHandler 处理来理查询
public abstract void select(String paramString, Object paramObject, ResultHandler paramResultHandler);
public abstract void select(String paramString, ResultHandler paramResultHandler);
public abstract void select(String paramString, Object paramObject, RowBounds paramRowBounds, ResultHandler paramResultHandler);
//插入-
public abstract int insert(String paramString);
public abstract int insert(String paramString, Object paramObject);
//更新
public abstract int update(String paramString);
public abstract int update(String paramString, Object paramObject);
//删除
public abstract int delete(String paramString);
public abstract int delete(String paramString, Object paramObject);
//事务提交
public abstract void commit();
public abstract void commit(boolean paramBoolean);
//事务回滚
public abstract void rollback();
public abstract void rollback(boolean paramBoolean);
public abstract List<BatchResult> flushStatements();
//关闭 SqlSession
public abstract void close();
//清理缓存
public abstract void clearCache();
//获取Configuration 对象
public abstract Configuration getConfiguration();
//获取SqlMapper
public abstract <T> T getMapper(Class<T> paramClass);
//获取Connection 连接对象
public abstract Connection getConnection();
}
SqlSession 相当于JDBC 时的 Connection 对象,用于 查询 (selectOne,selectList,selectMap,select), 插入(insert),删除(delete),修改(update), 也用于获取SqlMapper 接口。
SqlSession 有两个实现类, DefaultSqlSession,SqlSessionManager, 目前用的是 前者。
五. 生命周期
五.一 SqlSessionFactoryBuilder 方法局部
它的作用是一个构建器,一旦构建了SqlSessionFactory,它的作用就完结了,失去了存在的意义,必须废除,将其回收。所以它只存在于方法的局部。
五.二 SqlSessionFactory 整个MyBatis 生命周期中
责任是唯一的,就是创建SqlSession. 是单例模式
五.三 Configuration 整个MyBatis 生命周期中
用于 注册 别名,处理器,映射文件等。
五.三 SqlSession 数据库处理事务的过程中
是一个线程不安全的对象, 用finally 来close() 关闭连接 。
五.四 SqlMapper SqlSession事务方法之内
是一个接口,没有任何实现类,作用就是 发送SQL语句,返回结果 ,或者是执行sql语句,修改数据。
归纳成一个图就是:
谢谢!!!