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

    总结

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

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

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

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

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

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

    作者:blayn
    出处:https://www.cnblogs.com/blayn/
    版权:本文版权归作者和博客园共有
    转载:欢迎转载,但未经作者同意,必须保留此段声明;必须在文章中给出原文连接;否则必究法律责任
  • 相关阅读:
    S2-001 远程代码执行漏洞
    Struts2 devMode远程代码执行漏洞检测利用
    CVE-2017-12615(Tomcat PUT方法任意写文件漏洞)
    Medium | LeetCode 343 | 剑指 Offer 14- I. 剪绳子 | 动态规划
    Medium | 剑指 Offer 38. 字符串的排列 | 回溯
    Medium | 剑指 Offer 60. n个骰子的点数 | 动态规划
    Medium | 剑指 Offer 46. 把数字翻译成字符串 | 回溯
    Medium | 剑指 Offer 59
    Hard | LeetCode 239 | 剑指 Offer 59
    Medium | 剑指 Offer 35. 复杂链表的复制
  • 原文地址:https://www.cnblogs.com/blayn/p/14270067.html
Copyright © 2020-2023  润新知