package com.kkb.mybatis.test;
import java.io.InputStream;
import java.lang.reflect.Field;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;
import javax.sql.DataSource;
import org.apache.commons.dbcp.BasicDataSource;
import org.dom4j.Document;
import org.dom4j.Element;
import org.dom4j.Node;
import org.dom4j.Text;
import org.dom4j.io.SAXReader;
import org.junit.Test;
import com.kkb.mybatis.framework.config.Configuration;
import com.kkb.mybatis.framework.config.MappedStatement;
import com.kkb.mybatis.framework.sqlnode.IfSqlNode;
import com.kkb.mybatis.framework.sqlnode.MixedSqlNode;
import com.kkb.mybatis.framework.sqlnode.StaticTextSqlNode;
import com.kkb.mybatis.framework.sqlnode.TextSqlNode;
import com.kkb.mybatis.framework.sqlnode.iface.SqlNode;
import com.kkb.mybatis.framework.sqlsource.BoundSql;
import com.kkb.mybatis.framework.sqlsource.DynamicSqlSource;
import com.kkb.mybatis.framework.sqlsource.ParameterMapping;
import com.kkb.mybatis.framework.sqlsource.RawSqlSource;
import com.kkb.mybatis.framework.sqlsource.iface.SqlSource;
import com.kkb.mybatis.framework.utils.SimpleTypeRegistry;
import com.kkb.mybatis.po.User;
/**
* 目的是使用XML来表达mybatis的全局配置信息,和业务相关的SQL映射信息 (映射文件) 其次,优化数据连接的创建(使用连接池)
*
* @author 灭霸詹
*
*/
public class MybatisV2 {
/**
* 封装了全局配置文件和映射文件中的所有信息
*/
private Configuration configuration = new Configuration();
private String namespace;
private boolean isDynamic = false;
@Test
public void test() {
loadConfiguration();
User user = new User();
user.setId(1);
user.setUsername("王五");
List<User> users = selectList("test.findUserById", user);
System.out.println(users);
}
private void loadConfiguration() {
// 指定全局配置文件的路径
String location = "mybatis-config.xml";
// 获取对应的InputStream对象
InputStream inputStream = getInputStream(location);
// 获取Document对象
Document document = createDocument(inputStream);
// 按照全局配置文件和映射文件的XML语义进行解析
loadConfigurationElement(document.getRootElement());
}
/**
*
* @param rootElement
* <configuration>
*/
private void loadConfigurationElement(Element rootElement) {
Element environments = rootElement.element("environments");
parseEnvironments(environments);
Element mappers = rootElement.element("mappers");
parseMappers(mappers);
}
/**
*
* @param mappers
* <mappers>
*/
@SuppressWarnings("unchecked")
private void parseMappers(Element mappers) {
List<Element> mapperElements = mappers.elements("mapper");
for (Element mapperElement : mapperElements) {
parseMapper(mapperElement);
}
}
private void parseMapper(Element mapperElement) {
String resource = mapperElement.attributeValue("resource");
InputStream inputStream = this.getClass().getClassLoader().getResourceAsStream(resource);
Document document = createDocument(inputStream);
// 按照映射文件的语义进行解析
parseXmlMapper(document.getRootElement());
}
@SuppressWarnings("unchecked")
private void parseXmlMapper(Element rootElement) {
// 为了方便管理statement,需要使用statement唯一标识
namespace = rootElement.attributeValue("namespace");
List<Element> selectElements = rootElement.elements("select");
for (Element selectElement : selectElements) {
parseStatementElement(selectElement);
}
}
private void parseStatementElement(Element selectElement) {
String statementId = selectElement.attributeValue("id");
if (statementId == null || selectElement.equals("")) {
return;
}
// 一个CURD标签对应一个MappedStatement对象
// 一个MappedStatement对象由一个statementId来标识,所以保证唯一性
// statementId = namespace + "." + CRUD标签的id属性
statementId = namespace + "." + statementId;
String parameterType = selectElement.attributeValue("parameterType");
Class<?> parameterClass = resolveType(parameterType);
String resultType = selectElement.attributeValue("resultType");
Class<?> resultClass = resolveType(resultType);
String statementType = selectElement.attributeValue("statementType");
statementType = statementType == null || statementType == "" ? "prepared" : statementType;
// SqlSource的封装过程
SqlSource sqlSource = createSqlSource(selectElement);
// TODO 建议使用构建者模式去优化
MappedStatement mappedStatement = new MappedStatement(statementId, parameterClass, resultClass, statementType,
sqlSource);
configuration.addMappedStatement(statementId, mappedStatement);
}
private SqlSource createSqlSource(Element selectElement) {
SqlSource sqlSource = parseScriptNode(selectElement);
return sqlSource;
}
private SqlSource parseScriptNode(Element selectElement) {
// 解析select标签下的所有SQL脚本信息,比如sql文本片段、动态标签等,最终封装成SqlNode集合
MixedSqlNode rootSqlNode = parseDynamicTags(selectElement);
// 在解析SqlNode的时候,我们需要知道这些Sql文本中是否包含${},或者sql脚本中是否包含动态标签
// 包含${}和动态标签的这种SQL信息,我们封装到DynamicSqlSource
SqlSource sqlSource = null;
if (isDynamic) {
sqlSource = new DynamicSqlSource(rootSqlNode);
} else {
sqlSource = new RawSqlSource(rootSqlNode);
}
// 如果整个SQL信息中只包含#{}或者说什么特殊字符都没有,那么我们将这些SQL信息封装到RawSqlSource
return sqlSource;
}
private MixedSqlNode parseDynamicTags(Element selectElement) {
List<SqlNode> sqlNodes = new ArrayList<>();
// 获取select并且的子节点
int nodeCount = selectElement.nodeCount();
// 遍历所有节点
for (int i = 0; i < nodeCount; i++) {
Node node = selectElement.node(i);
// 判断节点是文本节点还是Element节点,如果是文本节点
if (node instanceof Text) {
// 获取SQL文本
String sqlText = node.getText().trim();
if (sqlText == null || "".equals(sqlText)) {
continue;
}
// 判断文本节点中是否包含${}
TextSqlNode textSqlNode = new TextSqlNode(sqlText);
// 如果包含${},那么将文本节点的SQL文本封装到TextSqlNode
if (textSqlNode.isDynamic()) {
sqlNodes.add(textSqlNode);
isDynamic = true;
} else {
// 如果不包含${},那么将文本节点的SQL文本封装到StaticTextSqlNode
sqlNodes.add(new StaticTextSqlNode(sqlText));
}
} else if (node instanceof Element) {
// 如果是Element节点,那么需要获取节点名称
Element element = (Element) node;
String name = element.getName();
// TODO 此处使用策略模式去优化
// 根据名称创建对应Element的SqlNode对象,封装对应Element的节点数据,比如if标签对应IfSqlNode
if ("if".equals(name)) {
// 获取判断表达式
String test = element.attributeValue("test");
// 递归给if标签动态解析,获取它的子标签SqlNode节点集合
MixedSqlNode mixedSqlNode = parseDynamicTags(element);
IfSqlNode ifSqlNode = new IfSqlNode(test, mixedSqlNode);
sqlNodes.add(ifSqlNode);
} else if ("where".equals(name)) {
// TODO 。。。。
}
}
}
return new MixedSqlNode(sqlNodes);
}
private Class<?> resolveType(String parameterType) {
try {
Class<?> clazz = Class.forName(parameterType);
return clazz;
} catch (ClassNotFoundException e) {
没有合适的资源?快使用搜索试试~ 我知道了~
手写mybaits框架代码
共68个文件
class:27个
java:26个
xml:6个
需积分: 1 0 下载量 49 浏览量
2023-04-22
22:57:34
上传
评论
收藏 28KB 7Z 举报
温馨提示
手写mybaits框架代码手写mybaits框架代码手写mybaits框架代码手写mybaits框架代码手写mybaits框架代码手写mybaits框架代码手写mybaits框架代码手写mybaits框架代码手写mybaits框架代码手写mybaits框架代码手写mybaits框架代码手写mybaits框架代码手写mybaits框架代码手写mybaits框架代码手写mybaits框架代码手写mybaits框架代码手写mybaits框架代码手写mybaits框架代码手写mybaits框架代码手写mybaits框架代码手写mybaits框架代码手写mybaits框架代码手写mybaits框架代码手写mybaits框架代码手写mybaits框架代码手写mybaits框架代码手写mybaits框架代码手写mybaits框架代码手写mybaits框架代码手写mybaits框架代码手写mybaits框架代码手写mybaits框架代码手写mybaits框架代码手写mybaits框架代码手写mybaits框架代码手写mybaits框架代码手写mybaits框架代码手写mybaits框架代码手写myba
资源推荐
资源详情
资源评论
收起资源包目录
mybatis-demo-13(1).7z (68个子文件)
mybatis-demo-13
.classpath 1KB
.settings
org.eclipse.jdt.core.prefs 243B
org.eclipse.core.resources.prefs 93B
org.eclipse.m2e.core.prefs 90B
pom.xml 2KB
src
test
resources
java
main
resources
mapper
UserMapper.xml 662B
jdbc.properties 399B
mybatis-config.xml 688B
java
com
kkb
mybatis
utils
SimpleTypeRegistry.java 2KB
framework
utils
SimpleTypeRegistry.java 2KB
OgnlUtils.java 1KB
ParameterMappingTokenHandler.java 974B
GenericTokenParser.java 3KB
TokenHandler.java 796B
sqlnode
DynamicContext.java 659B
TextSqlNode.java 2KB
iface
SqlNode.java 248B
IfSqlNode.java 791B
StaticTextSqlNode.java 437B
MixedSqlNode.java 660B
sqlsource
DynamicSqlSource.java 2KB
iface
SqlSource.java 451B
StaticSqlSource.java 705B
BoundSql.java 927B
ParameterMapping.java 566B
RawSqlSource.java 2KB
config
MappedStatement.java 2KB
Configuration.java 732B
test
MybatisV1.java 5KB
JdbcDemo.java 2KB
OgnlDemo.java 4KB
MybatisV3.java 64B
MybatisV2.java 14KB
po
User.java 973B
target
classes
mapper
UserMapper.xml 662B
jdbc.properties 399B
mybatis-config.xml 688B
META-INF
MANIFEST.MF 129B
maven
com.kkb
mybatis-demo-13
pom.properties 245B
pom.xml 2KB
com
kkb
mybatis
utils
SimpleTypeRegistry.class 1KB
framework
utils
ParameterMappingTokenHandler.class 2KB
SimpleTypeRegistry.class 1KB
GenericTokenParser.class 2KB
OgnlUtils.class 2KB
TokenHandler.class 240B
sqlnode
TextSqlNode.class 2KB
IfSqlNode.class 1KB
TextSqlNode$BindingTokenHandler.class 2KB
StaticTextSqlNode.class 818B
iface
SqlNode.class 247B
MixedSqlNode.class 1KB
DynamicContext.class 1KB
sqlsource
DynamicSqlSource.class 2KB
StaticSqlSource.class 1KB
iface
SqlSource.class 276B
RawSqlSource.class 2KB
ParameterMapping.class 1KB
BoundSql.class 2KB
config
MappedStatement.class 2KB
Configuration.class 2KB
test
JdbcDemo.class 3KB
MybatisV3.class 294B
MybatisV1.class 6KB
OgnlDemo.class 3KB
MybatisV2.class 14KB
po
User.class 2KB
test-classes
.project 567B
共 68 条
- 1
资源评论
Java码库
- 粉丝: 2359
- 资源: 6186
上传资源 快速赚钱
- 我的内容管理 展开
- 我的资源 快来上传第一个资源
- 我的收益 登录查看自己的收益
- 我的积分 登录查看自己的积分
- 我的C币 登录后查看C币余额
- 我的收藏
- 我的下载
- 下载帮助
最新资源
资源上传下载、课程学习等过程中有任何疑问或建议,欢迎提出宝贵意见哦~我们会及时处理!
点击此处反馈
安全验证
文档复制为VIP权益,开通VIP直接复制
信息提交成功