前言
接上文,这里只是出于强迫症,凭借着半年前的笔记来把之前没写完的文章写完,这里是最后一篇了。
前面自定义的持久层框架存在的问题
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 }
运行结果如下所示:
总结
这半年多来,经过工作中的磨练及空闲时间的自学,虽然我依旧是个菜鸟,但是开发能力还是比之前强了不少,回想半年多以前自己写这个系列文章的时候,对当中很多概念都不太清楚,现在倒是觉得很简单了。
之前是挺想一直坚持写下去的,不过由于那段时间项目太赶,工作强度比较大,导致学习积极性下降了很多。另一方面,也是因为自己的心态没有调整好,对于未来没有明确的目标。
我还算比较幸运,后面有机会换了一份比较好的工作,工作强度不那么大,这几个月自学的时间相当多,技术方面进步了不少。
可惜一直没有下定决心来好好写技术博客,新年新气象,正好最近自学也快告一段落了,是时候通过输出倒逼输入了,今年的目标之一就是坚持每周写一点博客,每月发布几篇。
也许我在很长的一段时间内都写不出什么好文章,但是 管它呢,自己喜欢就好,有个平台可以免费写点东西,顺便还能复习下自己学到的知识,这本身就是一种回报。
话虽如此,还是要精益求精,尽可能写多点有技术含量的东西,所以,要好好学习咯。