简单自定义mybatis流程!!
----简单自定义mybatis流程----
一.首先封装daoMapperxml文件和sqlMapconfig配置文件,如何封装:
(1).封装我们的Mapper.xml文件,提取名称空间namespace,提取方法名id,提取我们的结果类型resultType,再提取我们的sql语句sqlStatement创建实例对象封装.
(2).封装我们的sqlMapconfig.xml操作数据库的配置文件,提取数据源datasource(c3p0,德鲁伊...),再提取连接数据库四个步骤:driver驱动,地址URL,用户名username和密码password,还有最后一个接口映射文件信息,由于实际开发中会有多个,所以可以使用一个Map集合来定义Map<String,Mapper>datasource,接着创建实例封装.
二.解析xml文件,这里使用dom4j解析,然后创建我们的数据源对象:
(1).解析sqlMapconfig.xml文件
//这边使用无参构造方法来解析xml文件和加载数据源datasource!
public Configuration(){
loadXpathSqlMapConfig();
creatDatasource();
}
/**
* 解析数据库配置文件
*/
public void loadXpathSqlMapConfig(){
try {
//通过类加载器加载配置文件
InputStream resource = this.getClass().getClassLoader().getResourceAsStream("SqlMapConfig.xml");
//采用dom4j解析xml配置文件
SAXReader saxReader = new SAXReader();
Document read = saxReader.read(resource);
Element rootElement = read.getRootElement();
//System.out.println(rootElement);
List<Element> nodesList = rootElement.selectNodes("//property");//语法要求要加"//"
for (Element element : nodesList) {
String name = element.attributeValue("name");
String value = element.attributeValue("value");
if ("driver".equals(name)){
driver=value;
}
if ("url".equals(name)){
url=value;
}
if ("username".equals(name)){
username=value;
}
if ("password".equals(name)){
password=value;
}
}
List<Element> list = rootElement.selectNodes("//mapper");
for (Element element : list) {
String xpath = element.attributeValue("resource");
loadMapperXml(xpath);
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 创建数据源对象设置连接数据库参数
*
*/
public void creatDatasource(){
try {
//创建数据源对象
dataSource = new ComboPooledDataSource();
dataSource.setDriverClass(driver);
dataSource.setJdbcUrl(url);
dataSource.setUser(username);
dataSource.setPassword(password);
} catch (Exception e) {
e.printStackTrace();
}
}
(2).解析interfaceMapperXml文件.封装到我们的Mapper中!
/**
* 解析interfaceMapperXml文件
* @param xpath
*/
public void loadMapperXml(String xpath) {
mappers = new HashMap<>();
try {
InputStream inputStream = this.getClass().getClassLoader().getResourceAsStream(xpath);
SAXReader saxReader = new SAXReader();
Document document = saxReader.read(inputStream);
Element rootElement = document.getRootElement();
String namespace = rootElement.attributeValue("namespace");
List<Element> elements = rootElement.elements();
Mapper mapper = new Mapper();
for (Element element : elements) {
String id = element.attributeValue("id");
String resultType = element.attributeValue("resultType");
String sqlStatement = element.getText();
mapper.setId(id);
mapper.setNamespace(namespace);
mapper.setResultType(resultType);
mapper.setSqlStatement(sqlStatement);
String key=namespace+"."+id;
mappers.put(key,mapper);
}
} catch (Exception e) {
e.printStackTrace();
}
}
三.创建核心对象SqlSession对象,旧版Mybatis前常用SqlSession对象中的增删查改方法,现在新版Myatis常用getMapper方法,面向接口的编程方式,需要接口名与mapper的命名空间属性值保持一致,从而将接口与mapper文件对应起来。当namespace绑定某一接口之后,可以不用写该接口的实现类,MyBatis会通过接口的完整限定名查找到对应的mapper配置来执行SQL语句.里边使用了动态代理技术.
public class SqlSession {
public <T> T getMapper(Class<T> type){
T proxy= (T) Proxy.newProxyInstance(
this.getClass().getClassLoader(),
new Class[]{type},
new MapperProxy()
);
return proxy;
}
}
public class MapperProxy implements InvocationHandler {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//加载映射文件和配置文件
Configuration configuration = new Configuration();
//数据源
ComboPooledDataSource dataSource = configuration.getDataSource();
//执行的sql语句
Map<String, Mapper> mappers = configuration.getMappers();
String methodName = method.getName();
String className = method.getDeclaringClass().getName();
String key=className+"."+methodName;
System.out.println(key);
Mapper mapper = mappers.get(key);
return Executor.findAll(mapper,dataSource.getConnection());
}
}
四.创建我们的SqlSessionFactory会话工厂对象,通过里面的openSession()方法打开(得到)我们的核心Sqlsession会话对象;
* @Description: 会话工厂对象对象,此对象提供一个openSession()方法
*/
public class SqlSessionFactory {
public static SqlSession openSession(){
return new SqlSession();
}
}
五.创建Executor工具类 执行数据库操作并且封装结果集返回:
public class Executor {
public static <T> List<T> findAll(Mapper mapper, Connection connection){
List<T> resultList =new ArrayList<T>();
PreparedStatement preparedStatement=null;
ResultSet resultSet=null;
try {
//获取到sql语句
String sqlStatement = mapper.getSqlStatement();
//获取返回值类型
String resultType = mapper.getResultType();
//转成字节码对象
Class<?> aClass = Class.forName(resultType);
preparedStatement = connection.prepareStatement(sqlStatement);
//执行完返回resultSet 封装结果集
resultSet = preparedStatement.executeQuery();
handleResult(resultList,aClass,resultSet);
} catch (Exception e) {
e.printStackTrace();
}finally {
close(connection,preparedStatement,resultSet);
}
return resultList;
}
/**
* 处理结果集方法
* @param resultList
* @param aClass
* @param resultSet
*/
private static void handleResult(List resultList, Class<?> aClass, ResultSet resultSet) {
try {
//首先获取到元数据
ResultSetMetaData metaData = resultSet.getMetaData();
//获取元数据字段数量
int columnCount = metaData.getColumnCount();
//获取字段名称,因为多个,所以使用数组保存
String[] columnNames= new String[columnCount];
for (int i = 1; i <= columnNames.length; i++) {
columnNames[i-1]= metaData.getColumnName(i);
}
//循环取数据
while (resultSet.next()){
//通过反射技术给成员变量赋值
Object o = aClass.newInstance();//这个对象表示是User对象
//便利字段名称数组
for (int i = 0; i < columnNames.length; i++) {
//resultSet.getObject():获取此的当前行中指定列的值
Object object = resultSet.getObject(columnNames[i]);
Field field = aClass.getDeclaredField(columnNames[i]);
field.setAccessible(true);
field.set(o,object);
}
resultList.add(o) ;
}
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 释放资源
* @param connection
* @param preparedStatement
* @param resultSet
*/
private static void close(Connection connection, PreparedStatement preparedStatement, ResultSet resultSet) {
try {
if (connection!=null) connection.close();
if (preparedStatement!=null) preparedStatement.close();
if (resultSet!=null) resultSet.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
六.测试:
public class MybatisTest {
public static void main(String[] args) {
//测试
SqlSession sqlSession = SqlSessionFactory.openSession();
UserDao mapper = sqlSession.getMapper(UserDao.class);
List<User> userList = mapper.findAll();
for (User user : userList) {
System.out.println(user);
}
}
}
输出测试数据如下:

简单自定义mybatis流程!!的更多相关文章
- 搭建一个简单的mybatis框架
一.Mybatis介绍 MyBatis是一个支持普通SQL查询,存储过程和高级映射的优秀持久层框架.MyBatis消除了几乎所有的JDBC代码和参数的手工设置以及对结果集的检索封装.MyBatis可以 ...
- 【Mybatis】简单的mybatis增删改查模板
简单的mybatis增删改查模板: <?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE map ...
- 自定义 Mybatis 框架
分析流程 1. 引入dom4j <dependencies> <!--<dependency> <groupId>org.mybatis</groupI ...
- (转)sl简单自定义win窗体控件
sl简单自定义win窗体控件 相信大家接触过不少win窗体控件ChildWin子窗口就的sl自带的一个 而且网上也有很多类似的控件,而今天我和大家分享下自己制作个win窗体控件,希望对初学 ...
- 如何做个简单安卓App流程
有同学做毕业设计,问怎样做个简单安卓App流程,我是做服务端的,也算是经常接触app,想着做app应该很简单吧,不就做个页面,会跳转,有数据不就行了,我解释了半天,人家始终没听懂,算了,我第二天问了下 ...
- 【javascript】Promise/A+ 规范简单实现 异步流程控制思想
——基于es6:Promise/A+ 规范简单实现 异步流程控制思想 前言: nodejs强大的异步处理能力使得它在服务器端大放异彩,基于它的应用不断的增加,但是异步随之带来的嵌套.难以理解的代码让 ...
- SSM-MyBatis-01:IDEA的安装,永久注册和简单的MyBatis用例
一,IDEA的安装和永久注册 1.安装: 那到安装包,下一步,选路径,上面可以选操作系统64/32位,下面是程序的默认打开方式,可以不必勾选,也可以全选 路径一定不包含中文,重点 2.永久注册: 将此 ...
- Mybatis动态SQL简单了解 Mybatis简介(四)
动态SQL概况 MyBatis 的强大特性之一便是它的动态 SQL 在Java开发中经常遇到条件判断,比如: if(x>0){ //执行一些逻辑........ } Mybatis应用中,S ...
- UI设计篇·入门篇·绘制简单自定义矩形图/设置按钮按下弹起颜色变化/设置图形旋转
Android的基本控件和图形有限,难以满足所有的实际需要和设计需求,好在Android给出了相对完善的图形绘制和自定义控件的API,利用这些API,可以基本满足设计的需求. 自定义图像和控件的方法: ...
随机推荐
- 前端项目自动化构建工具——Webpack入门教程
参考资料:https://www.webpackjs.com/(中文文档) https://www.webpackjs.com/(官方文档) 首先有必要说明一下,本文侧重讲解webpack基本配置 ...
- Java抽象类构造方法
java中抽象类的子类的构造方法会隐含父类的无参构造方法. package com.zempty.abstractclass; public class AbstractDemo01 { public ...
- 关于git的认知
Git,官方的解释为一个开源的分布式版本控制系统,可以有效.高速地处理从很小到非常大的项目版本管理.是一个开放源码的版本控制软件. 就个人而言,这是一种不同开发者之间的代码交流.合并的途径,进而完成目 ...
- Day 1总结
- Spring IOC MVC DI简单实现
目录的大致情况:所有的类都会加进来. 1.首先先写基本的Controller Service ServiceImpl Controller Service ServiceImpl是用来验证下面写的框架 ...
- vue中事件修饰符详解(stop, prevent, self, once, capture, passive)
==.stop== 是阻止冒泡行为,不让当前元素的事件继续往外触发,如阻止点击div内部事件,触发div事件 ==.prevent== 是阻止事件本身行为,如阻止超链接的点击跳转,form表单的点击提 ...
- vscode Springboot 启动debug报错:Build failed, do you want to continue?
一,前言 vscode我感觉是一个特别好用的开发工具,我根据文章https://www.cnblogs.com/WangBoBlog/p/9464281.html去搭建一个简单的springboot工 ...
- 浅谈Spring的事务隔离级别与传播性
浅谈Spring的事务隔离级别与传播性 这篇文章以一个问题开始,如果你知道答案的话就可以跳过不看啦@(o・ェ・)@ Q:在一个批量任务执行的过程中,调用多个子任务时,如果有一些子任务发生异常,只是回滚 ...
- MySQL 相关规约(v1.0)
0)前言 a. 基本规约 [强制]表存储引擎必须使用InnoDB(针对主库一般是强制要求的) [强制]表字符集默认使用utf8,必要时候使用utf8mb4(个人踩坑:emoji表情存储问题) 说明: ...
- Spring MVC-从零开始-@RequestMapping结合@PathVariable (从URL路径中取值,作用于函数参数)
1.可以直接在RequestMapping中value元素中使用{key}描述属性键 2.也可以在{key}中使用正则限定key的取值范围,从而限定url的变化范围 package com.jt; i ...