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 }
运行结果如下所示:

总结

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

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

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

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

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

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

posted @ 2021-01-13 00:17  blayn  阅读(138)  评论(0编辑  收藏  举报