Mybatis核心配置文件就是为了配置Configration
因此要首先会解析Mybatis核心配置文件
首先使用dom4J解析Mybatis核心配置文件
新建模块演示dom4j解析.xml
引入依赖
从原来项目可以拷贝过来
就些简单配置就好
解析核心配置文件和解析xxxMapper.xml映射文件代码
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.Node;
import org.dom4j.io.SAXReader;
import org.junit.Test;
import java.io.InputStream;
import java.util.List;
/**
* @author hrui
* @date 2023/9/10 18:24
*/
public class ParseXMLByDom4JTest {
//解析Mapper映射文件
@Test
public void testParseSqlMapperXML() throws DocumentException {
//创建SAXReader对象
SAXReader reader=new SAXReader();
//获取输入流(将resources目录下的mybatis-config1.xml转输入流)
InputStream inputStream = ClassLoader.getSystemClassLoader().getResourceAsStream("mapper/CarMapperABC.xml");
//读XML文件
Document document=reader.read(inputStream);
String xpath="/mapper";
Element mapper =(Element) document.selectSingleNode(xpath);
String namespace = mapper.attributeValue("namespace");
System.out.println(namespace);//aaa
//获取mapper节点下所有子节点
List elements = mapper.elements();
elements.forEach(e->{
//获取sqlId
String id = e.attributeValue("id");
//获取resultType 没有返回null
System.out.println(id);
//获取标签中的sql语句,取出前后空白
String sql = e.getTextTrim();
System.out.println(sql);//insert into t_car(id,car_num,brand,guide_price,produce_time,car_type) values(null,#{carNum},#{brand},#{guidePrice},#{produceTime},#{carType})
//现在是:insert into t_car(id,car_num,brand,guide_price,produce_time,car_type) values(null,#{carNum},#{brand},#{guidePrice},#{produceTime},#{carType})
//内部肯定使用JDBC:insert into t_car(id,car_num,brand,guide_price,produce_time,car_type) values(null,?,?,?,?,?)
//转换
String newSql = sql.replaceAll("#\\{[0-9A-Za-z_$]*}", "?");//使用正则替换
System.out.println(newSql);//insert into t_car(id,car_num,brand,guide_price,produce_time,car_type) values(null,?,?,?,?,?)
});
}
//解析核心配置文件
@Test
public void testParseMybatisConfigXML() throws DocumentException {
//创建SAXReader对象
SAXReader reader=new SAXReader();
//获取输入流(将resources目录下的mybatis-config1.xml转输入流)
InputStream inputStream = ClassLoader.getSystemClassLoader().getResourceAsStream("mybatis-config1.xml");
//读XML文件
Document document=reader.read(inputStream);
//System.out.println(document);
//获取根标签
Element root = document.getRootElement();
//System.out.println(root.getName());//configuration
//获取跟标签后肯定是去获取环境 environments 获取里面的default数据库id
//获取默认的环境id
//xpath是做标签路径匹配的.能够让我们快速定位XML文件中的元素
//以下的xpath:从跟下开始找configuration,然后找configuration标签下的子标签environments
String xpath="/configuration/environments";
Element element = (Element)document.selectSingleNode(xpath);
//System.out.println(element);
//获取属性的值 默认环境id
String aDefaultEnvivironmentId = element.attributeValue("default");
//System.out.println("默认环境id是:"+aDefaultEnvivironmentId);//development
//去找environment的 id属性,然后和默认环境id比较,确定默认使用哪个数据库
//下面是xpath的写法 意思找
xpath="/configuration/environments/environment[@id='"+aDefaultEnvivironmentId+"']";
Element enviroment =(Element) document.selectSingleNode(xpath);
//System.out.println(enviroment.getName());environment
//获取environment节点下的transactionManager
Element transactionManager = enviroment.element("transactionManager");
String transactionType = transactionManager.attributeValue("type");
//System.out.println("事务管理器的类型:"+transactionType);//获取事务管理器类型----->JDBC
//接着获取datasource节点
Element datasource = enviroment.element("dataSource");
String dataSourcetype = datasource.attributeValue("type");
System.out.println("数据源的类型:"+dataSourcetype);//POOLED
//获取dataSource下的所有子节点
List propertyElements = datasource.elements();
//遍历
propertyElements.forEach(e->{
String name = e.attributeValue("name");
String value = e.attributeValue("value");
System.out.println("name="+name+",value="+value);
});
//获取所有的mapper标签
//如果你不想从跟下开始获取,而是想从任意位置开始,获取某个标签,xpath可以这样写
xpath="//mapper";// 两个//开始
List mappers = document.selectNodes(xpath);
//遍历
mappers.forEach(n->{
Element e=(Element)n;
String resource = e.attributeValue("resource");
System.out.println(resource);
});
}
}
新建module
引入依赖
可以回顾下标准写法
逆推下
Resources
SqlSessionFactoryBuilder
SqlSessionFactory
transaction
SqlSession
SQL Mapper
思路:1.Resources用来加载核心配置文件,返回一个InputStream流,
2.SqlSessionFactoryBuilder里有个build方法,该方法用来返回一个SqlSessionFactory对象
这里要考虑,SqlSessionFactory里有些什么,用来做什么.
那么这样就明了了,build方法用来解析核心配置文件,用以给SqlSessionFactory里的属性赋值,而属性有哪些,就是上面这些呗(事务管理器,JDBC连接需要的driver,url,username,password)
另外
和映射文件
是否考虑用一个容器Map存放,key为sql的id value是其他
将这个对象也封装到SqlSessionFactory中
这个对象中该有哪些属性:暂时放sql语句和resultType 当然实际放的不只这两个 获取不到就是null
SqlSessionFactory中还需要一个事务管理器,这个事务管理器可以是JDBC也可以是MANAGED,那么可以定义为接口,另外定义两个具体的实现 这里使用JDBC事务管理器
而我们定义了事务管理器之后,事务管理器需要搞定的就三个方法,commit,rollback,close
但是这三个方法需要连接对象,而要获取连接对象可以定义个数据源
在核心配置文件中,数据源有三个选项,分别是POOLED UNPOOLED JNDI
那好办,定义为接口呗
这里有个JDK规范,不管你是POOLED UNPOOLED JNDI所有的数据源都需要实现JDK里的DataSource接口 那么接口也不用定义了 直接写三个实现类 这里使用UNPOOLED 不使用连接池
那么在实现类里需要driver url username password属性
然后又个SqlSession对象
里面又insert方法 xxx 方法 需要用到什么,再解决
基本思路就是这样
整体结构
1.Resources
package com.gmybatis.utils;
import java.io.InputStream;
/**
* 工具类
* 用于"类路径"中资源的加载
* @author hrui
* @date 2023/9/10 20:25
*/
public class Resources {
//工具类建议构造方法私有化,因为工具类一般方法都是静态的,是种编程习惯
public Resources() {
}
/**
* 用于"类路径"种加载资源
* @param resource
* @return
*/
public static InputStream getResourceAsStream(String resource){
return ClassLoader.getSystemClassLoader().getResourceAsStream(resource);
}
}
2.SqlSessionFactoryBuilder 构建器对象
package com.gmybatis.core;
import com.gmybatis.utils.Resources;
import jdk.nashorn.internal.ir.ReturnNode;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.Node;
import org.dom4j.io.SAXReader;
import javax.sql.DataSource;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* SqlSessionFactory的构建器对象
* 通过SqlSessionFactoryBuilder的build方法来解析核心配置文件,
* 然后创建SqlSessionFactory对象
* @author hrui
* @date 2023/9/10 20:31
*/
public class SqlSessionFactoryBuilder {
public SqlSessionFactoryBuilder() {
}
/**
* 解析核心配置文件,来构建SqlSessionFactory
* @param in
* @return
*/
public SqlSessionFactory build(InputStream in){
SqlSessionFactory sqlSessionFactory=null;
try {
//解析核心配置文件
//创建SAXReader对象
SAXReader reader=new SAXReader();
//读XML文件
Document document=reader.read(in);
//获取environments
Element environments =(Element) document.selectSingleNode("/configuration/environments");
//获取default属性值
String defaultId = environments.attributeValue("default");
//拿匹配的环境节点
Element environment = (Element)document.selectSingleNode("/configuration/environments/environment[@id='"+defaultId+"']");
//获取transactionManager
Element transactionManagerEle = environment.element("transactionManager");
//获取dataSource
Element dataSourceEle = environment.element("dataSource");
//获取mapper
List mapperList = document.selectNodes("//mapper");//获取整个配置文件中所有的mapper标签
//用于封装所有mappers里面的mapper的路径
List sqlMapperXMLPathList=new ArrayList<>();
mapperList.forEach(n->{
Element e=(Element) n;
String resource = e.attributeValue("resource");
sqlMapperXMLPathList.add(resource);
});
//获取数据源对象
DataSource dataSource=getDataSource(dataSourceEle);
//定义事务管理器
Transaction transaction=getTransaction(transactionManagerEle,dataSource);
//key是namespase+sql的id
Map MappedStatements=getMappedStatements(sqlMapperXMLPathList);
//解析完成之后,构建出SqlSessionFactory对象
sqlSessionFactory=new SqlSessionFactory(transaction,MappedStatements);
} catch (Exception e) {
e.printStackTrace();
}
return sqlSessionFactory;
}
private Map getMappedStatements(List sqlMapperXMLPathList) {
Map map=new HashMap<>();
sqlMapperXMLPathList.forEach(path->{
try {
//创建SAXReader对象
SAXReader reader=new SAXReader();
//读XXXMapper.XML映射文件
Document document=reader.read(Resources.getResourceAsStream(path));
//解析映射文件
Element mapper = (Element)document.selectSingleNode("mapper");//带不带/都可以
String namespace = mapper.attributeValue("namespace");
List elements = mapper.elements();
elements.forEach(e->{
String id = e.attributeValue("id");
//namespase+id
String sqlId=namespace+"."+id;
String resultType = e.attributeValue("resultType");
String sqlContent = e.getTextTrim();
MappedStatement mappedStatement=new MappedStatement(sqlContent,resultType);
map.put(sqlId,mappedStatement);
});
} catch (DocumentException e) {
e.printStackTrace();
}
});
return map;
}
private DataSource getDataSource(Element dataSourceEle) {
Map map=new HashMap<>();
//获取节点下所有property
List propertys = dataSourceEle.elements("property");
propertys.forEach(e->{
String name = e.attributeValue("name");
String value = e.attributeValue("value");
map.put(name,value);
});
DataSource dataSource=null;
//type 可能是 POOLED UNPOOLED JNDI
String type = dataSourceEle.attributeValue("type");
// if(type.equalsIgnoreCase("POOLED")){ //这里简易定义常量类
//
// }
if(type.equalsIgnoreCase(Const.POOLED_DATASOURCE)){
dataSource=new POOLEDDataSource();
}
if(type.equalsIgnoreCase(Const.UN_POOLED_DATASOURCE)){//只对这个做了实现
dataSource=new UNPOOLEDDataSource(map.get("driver"),map.get("url"),map.get("username"),map.get("password"));
}
if(type.equalsIgnoreCase(Const.JNDI_DATASOURCE)){
dataSource=new JNDIDataSource();
}
return dataSource;
}
private Transaction getTransaction(Element transactionManager, DataSource dataSource) {
Transaction transaction=null;
String type = transactionManager.attributeValue("type");
if(type.equalsIgnoreCase(Const.JDBC_TRANSACTION)){
transaction=new JDBCTransaction(dataSource,false );//只对JDBCTransaction做了实现
}
if(type.equalsIgnoreCase(Const.MANAGED_TRANSACTION)){
transaction=new MANAGEDTransaction();
}
return transaction;
}
}
3.SqlSessionFactory
package com.gmybatis.core;
import java.util.Map;
/**
*SqlSessionFactory对象,一个数据库对应一个SqlSessionFactory对象
* 通过SqlSessionFactory对象可以获得SqlSession对象(开启会话)
* 一个SqlSessionFactory对象可以开启多个SqlSession会话
* @author hrui
* @date 2023/9/10 20:34
*/
public class SqlSessionFactory {
//事务管理器 可以是JDBC:原生JDBC事务 也可以是MANAGED:交容器管理,比如Spring 可以灵活切换建议定义为接口
private Transaction transaction;
//数据源属性 因为已经在事务管理器里定义了数据源,因此这里不需要定义 可以通过事务管理器来获取
private Map mappedStatementMap;
public SqlSessionFactory() {
}
public SqlSessionFactory(Transaction transaction, Map mappedStatementMap) {
this.transaction = transaction;
this.mappedStatementMap = mappedStatementMap;
}
public Transaction getTransaction() {
return transaction;
}
public void setTransaction(Transaction transaction) {
this.transaction = transaction;
}
public Map getMappedStatementMap() {
return mappedStatementMap;
}
public void setMappedStatementMap(Map mappedStatementMap) {
this.mappedStatementMap = mappedStatementMap;
}
// public SqlSession openSession(boolean flag){
// return null;
// }
}
Transaction接口及实现类,这里只实现了JDBCTransaction
package com.gmybatis.core;
import java.sql.Connection;
/**
* 事务管理器接口,所有的事务管理器都应该实现该接口
* JDBC事务管理器,MANAGED事务管理器都应该实现这个接口
* 提供控制事务的方法
* @author hrui
* @date 2023/9/10 21:14
*/
public interface Transaction {
//提交事务
void commit();
//回滚事务
void rollback();
//关闭事务
void close();
/**
* 是否需要其他方法后续再看
* 真正开启数据库连接
*/
void openConnection();
Connection getConnection();
}
JDBCTransaction
package com.gmybatis.core;
import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.SQLException;
/**
* JDBC事务管理器
* @author hrui
* @date 2023/9/10 21:19
*/
public class JDBCTransaction implements Transaction{
//数据源属性
private DataSource dataSource;
/**
* 自动提交标志
* true为自动提交
* false为不自动提交
*/
private Boolean aotoCommit;
private Connection connection;
/**
* 用于外界获取Connection
* 外界用的Connection对象 必须和事务管理器的是同一个
* 这样才可以在事务管理器里 commit rollback closed
* @return
*/
@Override
public Connection getConnection() {
return connection;
}
//用于给属性connection赋值 只要事务管理器不换 连接就是同一个连接、
@Override
public void openConnection(){
if(connection==null){
try {
connection=dataSource.getConnection();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
public JDBCTransaction(DataSource dataSource, Boolean aotoCommit) {
this.dataSource = dataSource;
this.aotoCommit = aotoCommit;
}
@Override
public void commit() {
//控制事务的时候需要调用JDBC里的连接对象 需要数据源
try {
connection.commit();
} catch (SQLException e) {
e.printStackTrace();
}
}
@Override
public void rollback() {
try {
connection.rollback();
} catch (SQLException e) {
e.printStackTrace();
}
}
@Override
public void close() {
try {
connection.commit();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
MANAGEDTransaction
package com.gmybatis.core;
import java.sql.Connection;
/**
* MANAGED事务管理器
* @author hrui
* @date 2023/9/10 21:19
*/
public class MANAGEDTransaction implements Transaction{
@Override
public void commit() {
}
@Override
public void rollback() {
}
@Override
public void close() {
}
@Override
public void openConnection() {
}
@Override
public Connection getConnection() {
return null;
}
}
实现DataSource的3个实现 只实现了UNPOOLEDDataSource
package com.gmybatis.core;
import javax.sql.DataSource;
import java.io.PrintWriter;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.SQLFeatureNotSupportedException;
import java.util.logging.Logger;
/**
* 数据源的实现类--->UNPOOLED
* 不使用数据库连接池
* @author hrui
* @date 2023/9/10 21:33
*/
public class UNPOOLEDDataSource implements DataSource {
private String driver;
private String url;
private String username;
private String password;
public UNPOOLEDDataSource(String driver, String url, String username, String password) {
try {
//直接注册驱动
Class.forName("com.mysql.cj.jdbc.Driver");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
this.driver = driver;
this.url = url;
this.username = username;
this.password = password;
}
@Override
public Connection getConnection() throws SQLException {
//需要driver url username password 定义为属性
Connection connection = DriverManager.getConnection(url, username, password);
return connection;
}
@Override
public Connection getConnection(String username, String password) throws SQLException {
return null;
}
@Override
public T unwrap(Class iface) throws SQLException {
return null;
}
@Override
public boolean isWrapperFor(Class> iface) throws SQLException {
return false;
}
@Override
public PrintWriter getLogWriter() throws SQLException {
return null;
}
@Override
public void setLogWriter(PrintWriter out) throws SQLException {
}
@Override
public void setLoginTimeout(int seconds) throws SQLException {
}
@Override
public int getLoginTimeout() throws SQLException {
return 0;
}
@Override
public Logger getParentLogger() throws SQLFeatureNotSupportedException {
return null;
}
}
package com.gmybatis.core;
import javax.sql.DataSource;
import java.io.PrintWriter;
import java.sql.Connection;
import java.sql.SQLException;
import java.sql.SQLFeatureNotSupportedException;
import java.util.logging.Logger;
/**
* 数据源的实现类--->POOLED
* 使用数据库连接池 这里不写连接池
* @author hrui
* @date 2023/9/10 21:32
*/
public class POOLEDDataSource implements DataSource {
@Override
public Connection getConnection() throws SQLException {
//从数据库连接池获取Connection对象 这里不写连接池
return null;
}
@Override
public Connection getConnection(String username, String password) throws SQLException {
return null;
}
@Override
public T unwrap(Class iface) throws SQLException {
return null;
}
@Override
public boolean isWrapperFor(Class> iface) throws SQLException {
return false;
}
@Override
public PrintWriter getLogWriter() throws SQLException {
return null;
}
@Override
public void setLogWriter(PrintWriter out) throws SQLException {
}
@Override
public void setLoginTimeout(int seconds) throws SQLException {
}
@Override
public int getLoginTimeout() throws SQLException {
return 0;
}
@Override
public Logger getParentLogger() throws SQLFeatureNotSupportedException {
return null;
}
}
JNDIDataSource
package com.gmybatis.core;
import javax.sql.DataSource;
import java.io.PrintWriter;
import java.sql.Connection;
import java.sql.SQLException;
import java.sql.SQLFeatureNotSupportedException;
import java.util.logging.Logger;
/**
* 数据源的实现类--->JNDI
* 使用第三方的数据库连接池获取Connection对象
* @author hrui
* @date 2023/9/10 21:33
*/
public class JNDIDataSource implements DataSource {
@Override
public Connection getConnection() throws SQLException {
return null;
}
@Override
public Connection getConnection(String username, String password) throws SQLException {
return null;
}
@Override
public T unwrap(Class iface) throws SQLException {
return null;
}
@Override
public boolean isWrapperFor(Class> iface) throws SQLException {
return false;
}
@Override
public PrintWriter getLogWriter() throws SQLException {
return null;
}
@Override
public void setLogWriter(PrintWriter out) throws SQLException {
}
@Override
public void setLoginTimeout(int seconds) throws SQLException {
}
@Override
public int getLoginTimeout() throws SQLException {
return 0;
}
@Override
public Logger getParentLogger() throws SQLFeatureNotSupportedException {
return null;
}
}
定义了一个常量类
package com.gmybatis.core;
/**
* 整个框架的常量类
* @author hrui
* @date 2023/9/10 22:26
*/
public class Const {
public static final String UN_POOLED_DATASOURCE="UNPOOLED";
public static final String POOLED_DATASOURCE="POOLED";
public static final String JNDI_DATASOURCE="JNDI";
public static final String JDBC_TRANSACTION="JDBC";
public static final String MANAGED_TRANSACTION="MANAGED";
}
注意测试时候事务管理要选用JDBC 数据源类型要选用UNPOOLED
mapper路径要写对
测试基本没问题
下面把SqlSession加进去
package com.gmybatis.core;
import java.lang.reflect.Method;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Locale;
/**
* 专门负责执行SQL语句的会话对象
* @author hrui
* @date 2023/9/10 23:40
*/
public class SqlSession {
private SqlSessionFactory sqlSessionFactory;
public SqlSession(SqlSessionFactory sqlSessionFactory) {
this.sqlSessionFactory = sqlSessionFactory;
}
//测试
public static void main(String[] args) {
String sql="insert into t_car values(#{id},#{asd},#{name})";
int fromIndex=0;
int index=1;
while(true) {
int jingIndex = sql.indexOf("#",fromIndex);
if(jingIndex<0){
break;
}
System.out.println(index);
index++;
int youkuohaoIndex = sql.indexOf("}",fromIndex);
String propertyName = sql.substring(jingIndex + 2, youkuohaoIndex).trim();
System.out.println(propertyName);
fromIndex = youkuohaoIndex + 1;
}
}
public int insert(String sqlId,Object obj){
//JDBC代码
Connection connection=null;
PreparedStatement ps=null;
ResultSet rs=null;
int count = 0;
try {
connection=sqlSessionFactory.getTransaction().getConnection();
String sql=sqlSessionFactory.getMappedStatementMap().get(sqlId).getSql();
String sql1 = sql.replaceAll("#\\{[0-9A-Za-z_$]*}", "?");//使用正则替换
ps = connection.prepareStatement(sql1);
//有几个?号 不知道将pojo对象中的哪个属性给哪个 暂时全当String
int fromIndex=0;
int index=1;
while(true) {
int jingIndex = sql.indexOf("#",fromIndex);
if(jingIndex<0){
break;
}
//System.out.println(index);
int youkuohaoIndex = sql.indexOf("}",fromIndex);
String propertyName = sql.substring(jingIndex + 2, youkuohaoIndex).trim();
//System.out.println(propertyName);
fromIndex = youkuohaoIndex + 1;
String getMethodName="get"+propertyName.toUpperCase().charAt(0)+propertyName.substring(1);
Method getMethod=obj.getClass().getDeclaredMethod(getMethodName);
Object invoke = getMethod.invoke(obj);
ps.setString(index,invoke.toString());
index++;
}
count = ps.executeUpdate();
} catch (Exception e) {
e.printStackTrace();
}
//这里不要加 不然直接关闭了
// finally {
// if(rs!=null){
// try {
// rs.close();
// } catch (SQLException e) {
// e.printStackTrace();
// }
// }
// if(ps!=null){
// try {
// ps.close();
// } catch (SQLException e) {
// e.printStackTrace();
// }
// }
// if(connection!=null){
// try {
// connection.close();
// } catch (SQLException e) {
// e.printStackTrace();
// }
// }
// }
return count;
}
public Object selectOne(){
return null;
}
public void commit(){
sqlSessionFactory.getTransaction().commit();
}
public void rollback(){
sqlSessionFactory.getTransaction().rollback();
}
public void close(){
sqlSessionFactory.getTransaction().close();
}
}
修改sqlSessionFactory
package com.gmybatis.core;
import java.util.Map;
/**
*SqlSessionFactory对象,一个数据库对应一个SqlSessionFactory对象
* 通过SqlSessionFactory对象可以获得SqlSession对象(开启会话)
* 一个SqlSessionFactory对象可以开启多个SqlSession会话
* @author hrui
* @date 2023/9/10 20:34
*/
public class SqlSessionFactory {
//事务管理器 可以是JDBC:原生JDBC事务 也可以是MANAGED:交容器管理,比如Spring 可以灵活切换建议定义为接口
private Transaction transaction;
//数据源属性 因为已经在事务管理器里定义了数据源,因此这里不需要定义 可以通过事务管理器来获取
private Map mappedStatementMap;
public SqlSessionFactory() {
}
public SqlSessionFactory(Transaction transaction, Map mappedStatementMap) {
this.transaction = transaction;
this.mappedStatementMap = mappedStatementMap;
}
public Transaction getTransaction() {
return transaction;
}
public void setTransaction(Transaction transaction) {
this.transaction = transaction;
}
public Map getMappedStatementMap() {
return mappedStatementMap;
}
public void setMappedStatementMap(Map mappedStatementMap) {
this.mappedStatementMap = mappedStatementMap;
}
/**
* 获取sql会话对象
* @param flag
* @return
*/
public SqlSession openSession(){
//开启会话的前提是开启连接
transaction.openConnection();
//创建SqlSession对象
SqlSession sqlSession=new SqlSession(this);
return sqlSession;
}
}
JDBCTransaction的openConnection的代码加上开启事务
package com.gmybatis.core;
import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.SQLException;
/**
* JDBC事务管理器
* @author hrui
* @date 2023/9/10 21:19
*/
public class JDBCTransaction implements Transaction{
//数据源属性
private DataSource dataSource;
/**
* 自动提交标志
* true为自动提交
* false为不自动提交
*/
private boolean aotoCommit;
private Connection connection;
/**
* 用于外界获取Connection
* 外界用的Connection对象 必须和事务管理器的是同一个
* 这样才可以在事务管理器里 commit rollback closed
* @return
*/
@Override
public Connection getConnection() {
return connection;
}
//用于给属性connection赋值 只要事务管理器不换 连接就是同一个连接、
@Override
public void openConnection(){
if(connection==null){
try {
connection=dataSource.getConnection();
//开启事务
connection.setAutoCommit(aotoCommit);
} catch (SQLException e) {
e.printStackTrace();
}
}
}
public JDBCTransaction(DataSource dataSource, Boolean aotoCommit) {
this.dataSource = dataSource;
this.aotoCommit = aotoCommit;
}
@Override
public void commit() {
//控制事务的时候需要调用JDBC里的连接对象 需要数据源
try {
connection.commit();
} catch (SQLException e) {
e.printStackTrace();
}
}
@Override
public void rollback() {
try {
connection.rollback();
} catch (SQLException e) {
e.printStackTrace();
}
}
@Override
public void close() {
try {
connection.commit();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
引入mysql依赖测试 新建表
新建实体类
package com.gmybatis.core;
/**
* @author hrui
* @date 2023/9/11 0:31
*/
public class Car {
private String id;
private String name;
private String age;
public Car() {
}
public Car(String id, String name, String age) {
this.id = id;
this.name = name;
this.age = age;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getAge() {
return age;
}
public void setAge(String age) {
this.age = age;
}
}
映射文件