前言

没想到会等到半年以后才来写这篇文章,我已经不记得当初自己想要在这篇文章中写什么了,还好有一些零散的笔记留着,就对照着上一篇文章及零散的笔记,把内容给补充完吧。

完善CRUD方法

完善DefaultSqlSession类实现查询单个及查询多个的接口

 1 package com.hardy.sqlSession;
2
3 import com.hardy.pojo.Configuration;
4 import com.hardy.pojo.MappedStatement;
5 import java.sql.SQLException;
6 import java.util.List;
7
8 public class DefaultSqlSession implements SqlSession {
9
10 private Configuration configuration;
11
12 public DefaultSqlSession(Configuration configuration) {
13 this.configuration = configuration;
14 }
15
16 // 处理器对象
17 private Executor simpleExcutor = new SimpleExecutor();
18
19 @Override
20 public <E> List<E> selectList(String statementId, Object... params) throws Exception {
21 // 对SimpleExecutor里的query方法的调用
22 SimpleExecutor simpleExecutor = new SimpleExecutor();
23 MappedStatement mappedStatement = configuration.getMappedStatementMap().get(statementId);
24 List<Object> list = simpleExecutor.query(configuration, mappedStatement, params);
25
26 return (List<E>) list;
27 }
28
29 @Override
30 public <T> T selectOne(String statementId, Object... params) throws Exception {
31 List<Object> objects = selectList(statementId, params);
32 if (objects.size() == 1) {
33 return (T) objects.get(0);
34 } else {
35 throw new RuntimeException("查询结果过多或返回结果过多");
36 }
37
38 }
39
40 public void close() throws SQLException {
41 simpleExcutor.close();
42 }
43
44 }

这里实现了单条记录查询即列表查询的方法。

编写User实体类

 1 package com.hardy.pojo;
2
3 /*
4 * 实体类,对应数据库的user表
5 * */
6 public class User {
7
8 private Integer id;
9
10 private String username;
11
12 public Integer getId() {
13 return id;
14 }
15
16 public void setId(Integer id) {
17 this.id = id;
18 }
19
20 public String getUsername() {
21 return username;
22 }
23
24 public void setUsername(String username) {
25 this.username = username;
26 }
27 }

创建Executor接口及SimpleExecutor实现类

 1 package com.hardy.sqlSession;
2
3 import com.hardy.pojo.Configuration;
4 import com.hardy.pojo.MappedStatement;
5
6 import java.sql.SQLException;
7 import java.util.List;
8
9 public interface Executor {
10
11 public <E> List<E> query(Configuration configuration, MappedStatement mappedStatement, Object... params) throws Exception;
12
13 void close() throws SQLException;
14
15 }
  1 package com.hardy.sqlSession;
2
3 import com.hardy.pojo.Configuration;
4 import com.hardy.pojo.MappedStatement;
5 import com.hardy.utils.GenericTokenParser;
6 import com.hardy.utils.ParameterMapping;
7 import com.hardy.utils.ParameterMappingTokenHandler;
8
9 import java.beans.PropertyDescriptor;
10 import java.lang.reflect.Field;
11 import java.lang.reflect.InvocationTargetException;
12 import java.lang.reflect.Method;
13 import java.sql.*;
14 import java.util.ArrayList;
15 import java.beans.IntrospectionException;
16 import java.util.List;
17
18 public class SimpleExecutor implements Executor {
19
20 private Connection connection = null;
21
22 @Override
23 public <E> List<E> query(Configuration configuration, MappedStatement mappedStatement,Object[] params) throws SQLException, ClassNotFoundException, IllegalAccessException,
24 InstantiationException, NoSuchFieldException, IntrospectionException, InvocationTargetException {
25 // 1、注册驱动,获取连接
26 connection = configuration.getDataSource().getConnection();
27
28 // 2、获取sql语句:select * from user where id = #{id} and username = #{username}(解析前)
29 String sql = mappedStatement.getSql();
30
31 // 3、对sql进行处理
32 BoundSql boundSql = getBoundSql(sql);
33
34 // 4、获取转换后的sql语句:// select * from where id = ? and username = ? (解析后)
35 String finalSql = boundSql.getSqlText();
36
37 // 5、获取预编译preparedStatement对象
38 PreparedStatement preparedStatement = connection.prepareStatement(finalSql);
39
40 // 6、设置参数,获取参数全路径
41 String parameterType = mappedStatement.getParamterType();
42 Class<?> paramterTypeClass = getClassType(parameterType);
43
44
45
46 List<ParameterMapping> parameterMappingList = boundSql.getParameterMappingList();
47
48 for (int i = 0; i < parameterMappingList.size(); i++) {
49 ParameterMapping parameterMapping = parameterMappingList.get(i);
50 String name = parameterMapping.getName();
51
52 // 反射
53 Field declaredField = paramterTypeClass.getDeclaredField(name);
54 declaredField.setAccessible(true);
55
56 // 参数的值
57 Object o = declaredField.get(params[0]);
58
59 // 给占位符赋值
60 preparedStatement.setObject(i+1, o);
61 }
62
63 ResultSet resultSet = preparedStatement.executeQuery();
64 String resultType = mappedStatement.getResultType();
65 Class<?> resultTypeClass = getClassType(resultType);
66 ArrayList<E> results = new ArrayList<E>();
67 while (resultSet.next()) {
68 ResultSetMetaData metaData = resultSet.getMetaData();
69 E o = (E) resultTypeClass.newInstance();
70 int columnCount = metaData.getColumnCount();
71 for (int i = 1; i <= columnCount; i++) {
72 // 字段名
73 String columnName = metaData.getColumnName(i);
74
75 // 字段值
76 Object value = resultSet.getObject(columnName);
77
78 // 创建字段描述器,为属性生成读写方法
79 PropertyDescriptor propertyDescriptor = new PropertyDescriptor(columnName, resultTypeClass);
80
81 // 获取写方法
82 Method writeMethod = propertyDescriptor.getWriteMethod();
83
84 // 向类中写入值
85 writeMethod.invoke(o, value);
86 }
87
88 results.add(o);
89 }
90
91 return results;
92
93 }
94
95 private Class<?> getClassType(String parameterType) throws ClassNotFoundException {
96 if (parameterType != null) {
97 Class<?> aClass = Class.forName(parameterType);
98 return aClass;
99 }
100
101 return null;
102 }
103
104 @Override
105 public void close() throws SQLException {
106 connection.close();
107 }
108
109 private BoundSql getBoundSql(String sql) {
110 // 标记处理类:主要是配合通用标记解析器GenericTokenParser类完成对配置文件等的解析工作,其中TokenHandler主要完成对占位符的解析工作
111 ParameterMappingTokenHandler parameterMappingTokenHandler = new ParameterMappingTokenHandler();
112 // GenericTokenParser:通用的标记解析器,完成了代码片段中的占位符的解析,然后再根据给定的标记处理器(TokenHandler)来进行表达式的处理
113 // GenericTokenParser类 构造函数三个参数分别为openToken(开始标记)、closeToken(结束标记)、handler(标记处理器)
114 GenericTokenParser genericTokenParser = new GenericTokenParser("#{", "}", parameterMappingTokenHandler);
115 String parse = genericTokenParser.parse(sql);
116
117 List<ParameterMapping> parameterMappings = parameterMappingTokenHandler.getParameterMappings();
118
119 BoundSql boundSql = new BoundSql(parse, parameterMappings);
120
121 return boundSql;
122 }
123
124 }

测试自定义持久层框架

编写测试类

新建一个IPersistence_test项目,在IPersistence_test项目的pom.xml文件中引入相关依赖(注意:这里需要引入自定义好的持久层框架IPersistence,因此需要先将IPersistence进行maven install 打包):

 1 <?xml version="1.0" encoding="UTF-8"?>
2 <project xmlns="http://maven.apache.org/POM/4.0.0"
3 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
4 xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
5 <modelVersion>4.0.0</modelVersion>
6
7 <groupId>com.hardy</groupId>
8 <artifactId>IPersistence_test</artifactId>
9 <version>1.0-SNAPSHOT</version>
10
11 <properties>
12 <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
13 <maven.compiler.encoding>UTF-8</maven.compiler.encoding>
14 <java.version>1.8</java.version>
15 <maven.compiler.source>1.8</maven.compiler.source>
16 <maven.compiler.target>1.8</maven.compiler.target>
17 </properties>
18
19 <!-- 引入自定义持久层框架的依赖 -->
20 <dependencies>
21 <dependency>
22 <groupId>com.hardy</groupId>
23 <artifactId>IPersistence</artifactId>
24 <version>1.0-SNAPSHOT</version>
25 </dependency>
26 </dependencies>
27
28 </project>

编写测试类:

 1 package com.hardy.test;
2
3 import com.hardy.io.Resources;
4 import com.hardy.pojo.User;
5 import com.hardy.sqlSession.SqlSession;
6 import com.hardy.sqlSession.SqlSessionFactory;
7 import com.hardy.sqlSession.SqlSessionFactoryBuilder;
8 import org.junit.Test;
9
10 import java.io.InputStream;
11 import java.util.List;
12
13 public class IPersistenceTest {
14
15 @Test
16 public void test() throws Exception {
17 InputStream resourceAsStream = Resources.getResourceAsStream("sqlMapConfig.xml");
18 SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().builder(resourceAsStream);
19 SqlSession sqlSession = sqlSessionFactory.openSession();
20
21 System.out.println("自定义持久层框架,GO!");
22 // 调用
23 User user = new User();
24 user.setId(1);
25 user.setUsername("hardy");
26 User user2 = sqlSession.selectOne("User.selectOne", user);
27 System.out.println("查询单条记录:"+ user2);
28
29 System.out.println("-----------------------------------------");
30
31 List<User> users = sqlSession.selectList("User.selectList");
32 System.out.println("查询多条记录:");
33 for (User user1 : users) {
34 System.out.println(user1);
35 }
36
37 }
38 }

执行测试类,结果如下所示:

Mybatis学习之自定义持久层框架(六) 自定义持久层框架:完善CRUD方法并进行测试的更多相关文章

  1. 【MyBatis学习笔记】

    [MyBatis学习笔记]系列之预备篇一:ant的下载与安装 [MyBatis学习笔记]系列之预备篇二:ant入门示例 [MyBatis学习笔记]系列之一:MyBatis入门示例 [MyBatis学习 ...

  2. Mybatis(一):手写一套持久层框架

    作者 : 潘潘 未来半年,有幸与导师们一起学习交流,趁这个机会,把所学所感记录下来. 「封面图」 自毕业以后,自己先创业后上班,浮沉了近8年,内心着实焦躁,虽一直是走科班路线,但在技术道路上却始终没静 ...

  3. Django框架(六)--模板层:变量、过滤器、标签、自定义标签和过滤器

    将页面的设计和Python的代码分离开会更干净简洁更容易维护. 我们可以使用 Django的 模板系统 (Template System)来实现这种模式 # django模板修改的视图函数 def c ...

  4. mybatis学习笔记之基础框架(2)

    mybatis学习笔记之基础框架(2) mybatis是一个持久层的框架,是apache下的顶级项目. mybatis让程序将主要精力放在sql上,通过mybatis提供的映射方式,自由灵活生成满足s ...

  5. 【MyBatis学习01】宏观上把握MyBatis框架

    今天开始学习mybatis框架,博客主要记录学习过程中的一些总结,如有错误之处,欢迎留言指正~先用mybatis的鸟鸟来镇个楼,咳咳~~ mybatis框架是一个持久层框架,是Apache下的顶级项目 ...

  6. mybatis 学习笔记(三):mapper 代理开发 dao 层

    mybatis 学习笔记(三):mapper 代理开发 dao 层 优势 通过使用mapper 代理,我们可以不需要去编写具体的实现类(使用 getMapper() 方法自动生成),只需编写接口即可, ...

  7. WisDom.Net 框架设计(八) 持久层

    WisDom.Net ---持久层  1.什么是持久层        持久层负责最基础的功能支撑,为项目提供一个高层,统一,和并发的数据持久机制,提供了比如建立数据库连接,关闭数据库连接,执行sql语 ...

  8. mybatis学习笔记(六) -- maven+spring+mybatis从零开始搭建整合详细过程(下)

    继续 mybatis学习笔记(五) -- maven+spring+mybatis从零开始搭建整合详细过程(上) 五.使用监听器启动Spring容器 1.修改pom.xml文件,添加Spring-we ...

  9. Unity3D学习笔记(二十六):MVC框架下的背包系统(1)

    MVC背包 需求: 1.背包格子的装备是可以拖动的 2.装备栏的装备也是可以拖动的 3.当背包格子的装备拖动到装备栏时,如果是装备类型和装备栏类型是一致的能装上 4.背包的装备是按照顺序放在格子中的, ...

随机推荐

  1. Python的多进程和多线程

    进程和线程 进程是系统进行资源分配的最小单位,线程是系统进行调度执行的最小单位: 一个应用程序至少包含一个进程,一个进程至少包含一个线程: 每个进程在执行过程中拥有独立的内存空间,而一个进程中的线程之 ...

  2. java例题_37 有 n 个人围成一圈,顺序排号。从第一个人开始报数(从 1 到 3 报数),凡报到 3 的人退出圈子, 3 问最后留下的是原来第几号的那位。

    1 /*37 [程序 37 报数] 2 题目:有 n 个人围成一圈,顺序排号.从第一个人开始报数(从 1 到 3 报数),凡报到 3 的人退出圈子, 3 问最后留下的是原来第几号的那位. 4 */ 5 ...

  3. 系统编程-信号-总体概述和signal基本使用

    信号章节 -- 信号章节总体概要 信号基本概念 信号是异步事件,发送信号的线程可以继续向下执行而不阻塞. 信号无优先级. 1到31号信号是非实时信号,发送的信号可能会丢失,不支持信号排队. 31号信号 ...

  4. 多任务学习(MTL)在转化率预估上的应用

    今天主要和大家聊聊多任务学习在转化率预估上的应用. 多任务学习(Multi-task learning,MTL)是机器学习中的一个重要领域,其目标是利用多个学习任务中所包含的有用信息来帮助每个任务学习 ...

  5. k8s删除节点

    k8s 删除节点 线上环境 # ctl get nodes NAME STATUS ROLES AGE VERSION 10.0.0.123 Ready <none> 104d v1.20 ...

  6. Java后端进阶-网络编程(NIO/BIO)

    Socket编程 BIO网络编程 BIO Server package com.study.hc.net.bio; import java.io.BufferedReader; import java ...

  7. matlab数值类型

    matlab数值类型 数值类型的分类 整数类型    整数类型有8种.上面的数字为其内存大小,如:int8,整数所占内存大小为8个字节.除了int64 和 uint64不能进行数值运算之外都可以. 类 ...

  8. 判断请求是否属于Ajax请求

    我们有时候需要根据请求类型来判断返回视图名称还是JSON数据,这里记录一个判断Ajax的工具类方便日后好找 通过传入Request对象获取头信息,根据头信息判断是否属于Ajax请求 public cl ...

  9. win10 添加全局快捷键

    前言 好久没写博客了,今天水一下 如何在win10 下添加一个全局唤醒的快捷键(打开截图软件) 步骤 win + Q 输入 管理工具 添加快捷方式 这里没有管理员权限,可以直接把创建好的 快捷方式 粘 ...

  10. Typora+PicGo配置图床神器(图片链接URL)

    目录 1.下载Typora 2.下载PicGo 3.Typora 配置 1.下载Typora 有能力科学的小伙伴,可以从官网下载,地址为Typora 向下滚动,点击Downloda后,选择自己的操作系 ...