前言

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

完善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. git提交本地文件到远程仓库及参与的项目仓库

    1.git提交本地文件到组织 1.先再组织中建立个用于存放文件的仓库建然后复制仓库地址: 2.进入要上传的文件的根目录下右击 git Bash 进入git控制台,我要上传的文件如下: 3.进入后: 1 ...

  2. python--requests模块详解

    GET请求 首先构造一个最简单的get请求,请求的链接为http://httpbin.org/get import requests 2 r = requests.get("http://h ...

  3. 最小生成树,Prim和Kruskal的原理与实现

    文章首先于微信公众号:小K算法,关注第一时间获取更新信息 1 新农村建设 大清都亡了,我们村还没有通网.为了响应国家的新农村建设的号召,村里也开始了网络工程的建设. 穷乡僻壤,人烟稀少,如何布局网线, ...

  4. elementui 表格 如何使操作中隐藏一个按钮

    <el-table-column label="权限"min-width="100"> <template scope="scope ...

  5. 使用 EPPlus 封装的 excel 表格导入功能 (.net core c#)

    使用 EPPlus 封装的 excel 表格导入功能 前言 最近做系统的时候有很多 excel导入 的功能,以前我前后端都做的时候是在前端解析,然后再做个批量插入的接口 我觉着这样挺好的,后端部分可以 ...

  6. UnitThreeSummary

    目录 一.JML的梳理与总结 二.SMT Solver的部署与验证 三.JMLUnitNG的部署与测试 四.作业的设计与总结 第一次作业 第二次作业 第三次作业 五.BUG 六.总结与反思 一.JML ...

  7. OO电梯系列总结与反思

    目录 前言 HW5 度量分析 UML类图与协作图 bug分析 HW6 度量分析 UML类图与协作图 bug分析 HW7 度量分析 UML类图与协作图 bug分析 SOLID原则 感想 前言 紧张刺激的 ...

  8. windows2003安装php ,mysql,fastgui

    在上一章中,windows2003的iis搭建已经完成,但是我们现在用的多的也包含php,该如何让Windows2003成功使用php文件呢? windows2003需要先行安装vc9运行库才能与fa ...

  9. 对象存储服务MinIO安装部署分布式及Spring Boot项目实现文件上传下载

    目录 一.MinIO快速入门 1. MinIO简介 2. CentOS7更换成阿里云镜像 3. 安装 3.1 下载 3.2 运行测试 4. 配置脚本执行文件 4.1 创建配置执行文件 4.2 执行 二 ...

  10. try - with - resource

    本文详细介绍了自 JDK 7 引入的 try-with-resources 语句的原理和用法,以及介绍了 JDK 9 对 try-with-resources 的改进,使得用户可以更加方便.简洁的使用 ...