浅入mybatis(2)(手写简单的mybatis)
浅入mybatis(1)中 我们已经完整的配置了mybatis过程。可以实现通过简单的xml文件就实现了数据库的增删改查,那么神奇之处
在哪里呢?这一章我们简单的实现下mybatis的实现原理,不足之处 敬请谅解
首先我个人手写的一个流程图如下 (我们可以先敲代码 再反过来看这个图)
我写的demo流程如下:
一:建立User实体类
二:按照流程图所示 创建userMapperXml 将id和 sql存起来(这里将xml写成java文件 其实原始的也是将xml文件解析为map id作为key sql作为value的方式存储起来的 这里就不做详细介绍)
三:mapper接口 改接口对应我们xml对应的id的方法
四:创建自己的sqlSession工厂 这里使用动态代理 将我们所有的mapper传进来 但是我们用代理类去完成所有的操作
(这里体现动态代理的优越性)
五:建立数据库的连接 并使用sqlSession 的工厂类对象实现数据库的增删查找
完整的demo目录结构如下:
1.user 类:
package com.mybatis.handWriteMybatis; public class User { private int id; private String name; private Integer age; public int getId() { return id; } public void setId(int id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public Integer getAge() { return age; } public void setAge(Integer age) { this.age = age; } }
2.xml文件的代替类(我们模拟将id 和class存入map中)
package com.mybatis.handWriteMybatis; import java.util.HashMap; import java.util.Map; public class UserMapperXml { // 类xml的命名空间 public static final String namespate = "com.mybatis.handWriteMybatis.UserMapper"; public static final Map<String, String> map = new HashMap<String, String>(); static { // 模拟xml中的id与sql语句 实际中是xml文件 被解析之后放入map中 通过id去找那个对应的sql map.put("getUserById", "select * from user where id = ?"); } }
3 操作数据库接口类
package com.mybatis.handWriteMybatis; public interface UserMapper { public User getUserById(int id); } 4.这里是重点 创建自己的sqlsession
package com.mybatis.handWriteMybatis; import java.lang.reflect.Proxy; public class Sqlsession { private ExcutorImp excutorImp = new ExcutorImp(); //查询数据库操作 public <T> T selectOne(String statement, Object parameter) { return excutorImp.query(statement, parameter); } //用动态代理完成传入的Mapper接口要完成的操作 public <T> T getMapper(Class<T> tClass) { return (T) Proxy.newProxyInstance( tClass.getClassLoader(), new Class[] {tClass}, new MyMapperHandler<T>(this)); } }
代理类MyMapperHandler如下:
package com.mybatis.handWriteMybatis; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; public class MyMapperHandler<T> implements InvocationHandler { Sqlsession sqlsession = null; public MyMapperHandler(Sqlsession sqlsession) { this.sqlsession = sqlsession; } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println("运行invoke方法"); System.out.println(method.getDeclaringClass().getName()); System.out.println("args " + args[0]); if (method.getDeclaringClass().getName().equals(UserMapperXml.namespate)) { String sql = UserMapperXml.map.get(method.getName()); System.out.println(sql); return sqlsession.selectOne(sql, String.valueOf(args[0])); } return null; } }
5.建立连接 进行测试
<1>增删查找的总接口
package com.mybatis.handWriteMybatis; public interface ConnectionExcutor { public <T> T query(String statement, Object parament); }
<2>数据库的连接以及实现上面接口的操作 package com.mybatis.handWriteMybatis; import org.junit.Test; import java.sql.*; public class ExcutorImp implements ConnectionExcutor { @Override public <T> T query(String statement, Object parament) { Connection connection = null; PreparedStatement preparedStatement = null; connection = getConnection(); try { PreparedStatement pre = connection.prepareStatement(statement); String str = (String) parament; pre.setInt(1, Integer.parseInt(str)); ResultSet set = pre.executeQuery(); User user = new User(); while (set.next()) { user.setName(set.getString(2)); } return (T) user; } catch (SQLException e) { e.printStackTrace(); } return null; } private static Connection getConnection() { String driver = "com.mysql.jdbc.Driver"; String url = "jdbc:mysql://localhost:3306/generator?characterEncoding=UTF-8"; String username = "root"; String password = "123456"; try { Class.forName(driver); Connection connection = DriverManager.getConnection(url, username, password); System.out.println("连接成功"); return connection; } catch (Exception e) { e.printStackTrace(); } return null; } @Test public void testCon() { Connection connection = ExcutorImp.getConnection(); System.out.println(connection); } }
测试代码:
package com.mybatis.handWriteMybatis; public class TestMybatis { public static void main(String[] args) { Sqlsession sqlsession = new Sqlsession(); UserMapper mapper = sqlsession.getMapper(UserMapper.class); User userById = mapper.getUserById(6); System.out.println(userById.getName()); } }
测试结果如下:
以上就是简单的实现mybatis的实现 其中最主要的还是动态代理的设计思想。