前言

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

完善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. 京东数科面试真题:常见的 IO 模型有哪些?Java 中的 BIO、NIO、AIO 有啥区别?

    本文节选自<Java面试进阶指北 打造个人的技术竞争力> 面试中经常喜欢问的一个问题,因为通过这个问题,面试官可以顺便了解一下你的操作系统的水平. IO 模型这块确实挺难理解的,需要太多计 ...

  2. 攻防世界 reverse android-app-100

     android-app-100  suctf-2016 jeb启动,找到点击事件: 验证流程: 输入作为参数 --> processObjectArrayFromNative 得到一返回值(r ...

  3. [2020年10月28日普级组]1408.MSWORLD

    1408. M S W O R L D 1408.MSWORLD 1408.MSWORLD 题目描述 Bessie , Farmer John 的优选牛,刚刚获得了一个牛科动物选美比赛的冠军!并得到了 ...

  4. Laravel源码解析 — 服务容器

    前言 本文对将系统的对 Laravel 框架知识点进行总结,如果错误的还望指出 阅读书籍 <Laravel框架关键技术解析> 陈昊 学习课程 Laravel5.4快速开发简书网站 轩脉刃 ...

  5. java正则匹配${xxx} 排除单引号双引号内的内容,前提引号必须成对出现

    public static void main(String[] a) { String wpp = "select 1, ${mark} '``this is, `/message22` ...

  6. HTML5和CSS3 PC端静态网页琐碎知识点

    1.PC端为了兼容IE9以及IE9以下,尽量要使用float进行布局,兼容性好,一般不要用flex进行布局. 2.问起CSS选择器的分类,先说id选择器,类选择器,属性选择器,伪类选择器,伪元素选择器 ...

  7. 软工AI Bot NABCD分析

    目标: 打造一个基于大数据的 IT 问答机器人服务,通过运用人工和AI 技术,极大提高问答产品的用户满意度. 适合高校<软件工程>,<人工智能>课程作为结对编程或者团队项目. ...

  8. 基于sinc的音频重采样(二):实现

    上篇(基于sinc的音频重采样(一):原理)讲了基于sinc方法的重采样原理,并给出了数学表达式,如下:                  (1) 本文讲如何基于这个数学表达式来做软件实现.软件实现的 ...

  9. 配置Jupyter环境:安装+补全+美化+常用库

    1 Jupyter简介 Jupyter Notebook是一个交互式笔记本,支持运行40多种编程语言,本质是一个Web应用程序,便于创建和共享文学化程序文档,支持实时代码,数学方程,可视化和Markd ...

  10. ServletConfig和ServletContext接口

    ServletConfig 在web.xml文件中使用一个或多个init-param元素进行配置后,Tomcat初始化Servlet时,都会将该Servlet的配置信息封装到一个ServletConf ...