浅入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的实现 其中最主要的还是动态代理的设计思想。