Mybatis学习之自定义持久层框架(七) 自定义持久层框架优化

时间:2023-03-09 07:10:13
Mybatis学习之自定义持久层框架(七) 自定义持久层框架优化

前言

接上文,这里只是出于强迫症,凭借着半年前的笔记来把之前没写完的文章写完,这里是最后一篇了。

前面自定义的持久层框架存在的问题

Dao层若使用实现类,会存在代码重复,整个操作的过程模版重复(加载配置文件、创建sqlSessionFactory、生产sqlSession)

解决思路

使用代理模式生成Dao层接口的代理实现类(去掉原Dao层的代理实现类)

代码实现

在IPersistence_test项目中添加Dao层及接口类:
 1 package com.hardy.dao;
2
3 import com.hardy.pojo.User;
4
5 import java.util.List;
6
7 public interface IUserDao {
8
9 // 查询所有用户
10 public List<User> findAll() throws Exception;
11
12 // 根据条件进行用户查询
13 public User findByCondition(User user) throws Exception;
14
15 }
在SqlSession接口类中添加getMapper接口:
 1 package com.hardy.sqlSession;
2
3 import java.util.List;
4
5 public interface SqlSession {
6
7 /* 查询所有:
8 根据statementId,找到Mapper.xml文件中对应的sql语句
9 Object...Parameter 表示支持传递多个参数值进行查询
10 */
11 public <E> List<E> selectList(String statementId, Object... Parameter) throws Exception;
12
13 // 根据条件查询单个
14 public <T> T selectOne(String statementId, Object... Parameter) throws Exception;
15
16 //为Dao接口生成代理实现类
17 public <T> T getMapper(Class<?> mapperClass);
18
19 }
在SqlSession的实现类中重写getMapper接口:
 1 package com.hardy.sqlSession;
2
3 import com.hardy.pojo.Configuration;
4 import com.hardy.pojo.MappedStatement;
5
6 import java.lang.reflect.*;
7 import java.lang.reflect.Proxy;
8 import java.sql.SQLException;
9 import java.util.List;
10
11 public class DefaultSqlSession implements SqlSession {
12
13 private Configuration configuration;
14
15 public DefaultSqlSession(Configuration configuration) {
16 this.configuration = configuration;
17 }
18
19 // 处理器对象
20 private Executor simpleExecutor = new SimpleExecutor();
21
22 @Override
23 public <E> List<E> selectList(String statementId, Object... params) throws Exception {
24 // 对SimpleExecutor里的query方法的调用 7
25 SimpleExecutor simpleExecutor = new SimpleExecutor();
26 MappedStatement mappedStatement = configuration.getMappedStatementMap().get(statementId);
27 List<Object> list = simpleExecutor.query(configuration, mappedStatement, params);
28
29 return (List<E>) list;
30 }
31
32 @Override
33 public <T> T selectOne(String statementId, Object... params) throws Exception {
34 List<Object> objects = selectList(statementId, params);
35 if (objects.size() == 1) {
36 return (T) objects.get(0);
37 } else {
38 throw new RuntimeException("查无此数据或查询结果过多");
39 }
40
41 }
42
43 @Override
44 public <T> T getMapper(Class<?> mapperClass) {
45 // 使用JDK动态代理来为Dao接口生成代理对象,并返回
46 Object proxyInstance = Proxy.newProxyInstance(DefaultSqlSession.class.getClassLoader(), new Class[]{mapperClass}, new InvocationHandler() {
47 @Override
48 public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
49 // 底层都还是去执行JDBC代码
50 // 根据不同情况,来调用selctList或者selectOne
51 // 准备参数 1:statmentid :sql语句的唯一标识:namespace.id = 接口全限定名.方法名
52 String methodName = method.getName();
53 String className = method.getDeclaringClass().getName();
54
55 String statementId = className + "." + methodName;
56
57 // 准备参数2:params:args
58 // 获取被调用方法的返回值类型
59 Type genericReturnType = method.getGenericReturnType();
60 // 判断是否进行了 泛型类型参数化
61 if (genericReturnType instanceof ParameterizedType) {
62 List<Object> objects = selectList(statementId, args);
63 return objects;
64 }
65
66 return selectOne(statementId, args);
67 }
68 });
69
70 return (T) proxyInstance;
71 }
72
73 public void close() throws SQLException {
74 simpleExecutor.close();
75 }
76
77 }
修改测试类:
 1 package com.hardy.test;
2
3 import com.hardy.dao.IUserDao;
4 import com.hardy.io.Resources;
5 import com.hardy.pojo.User;
6 import com.hardy.sqlSession.SqlSession;
7 import com.hardy.sqlSession.SqlSessionFactory;
8 import com.hardy.sqlSession.SqlSessionFactoryBuilder;
9 import org.junit.Test;
10
11 import java.io.InputStream;
12 import java.util.List;
13
14 public class IPersistenceTest {
15
16 @Test
17 public void test() throws Exception {
18 InputStream resourceAsStream = Resources.getResourceAsStream("sqlMapConfig.xml");
19 SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().builder(resourceAsStream);
20 SqlSession sqlSession = sqlSessionFactory.openSession();
21
22 System.out.println("自定义持久层框架,GO!");
23 // 调用
24 // User user = new User();
25 // user.setId(1);
26 // user.setUsername("hardy");
27 // User user2 = sqlSession.selectOne("User.selectOne", user);
28 // System.out.println("查询单条记录:"+ user2);
29 //
30 // System.out.println("-----------------------------------------");
31 //
32 // List<User> users = sqlSession.selectList("User.selectList");
33 // System.out.println("查询多条记录:");
34 // for (User user1 : users) {
35 // System.out.println(user1);
36 // }
37
38 IUserDao userDao = sqlSession.getMapper(IUserDao.class);
39
40 List<User> allUsers = userDao.findAll();
41 for (User user1 : allUsers) {
42 System.out.println(user1);
43 }
44
45 }
46 }
运行结果如下所示:

Mybatis学习之自定义持久层框架(七) 自定义持久层框架优化

总结

这半年多来,经过工作中的磨练及空闲时间的自学,虽然我依旧是个菜鸟,但是开发能力还是比之前强了不少,回想半年多以前自己写这个系列文章的时候,对当中很多概念都不太清楚,现在倒是觉得很简单了。

之前是挺想一直坚持写下去的,不过由于那段时间项目太赶,工作强度比较大,导致学习积极性下降了很多。另一方面,也是因为自己的心态没有调整好,对于未来没有明确的目标。

我还算比较幸运,后面有机会换了一份比较好的工作,工作强度不那么大,这几个月自学的时间相当多,技术方面进步了不少。

可惜一直没有下定决心来好好写技术博客,新年新气象,正好最近自学也快告一段落了,是时候通过输出倒逼输入了,今年的目标之一就是坚持每周写一点博客,每月发布几篇。

也许我在很长的一段时间内都写不出什么好文章,但是 管它呢,自己喜欢就好,有个平台可以免费写点东西,顺便还能复习下自己学到的知识,这本身就是一种回报。

话虽如此,还是要精益求精,尽可能写多点有技术含量的东西,所以,要好好学习咯。