原理--JDK动态代理产生mapper动态代理对象
1.通过反射获取方法注解或者xml文件中的sql语句 2.获取数据库连接(jdbc) 3.解析sql语句 4.执行sql语句 4.获取动态代理对象(最终对象,可以直接调用方法)
自己实现简单的mybatis动态代理
获取jdbc连接
import java.sql.Connection; import java.sql.DriverManager; import java.sql.SQLException; public class DBManager { public static Connection getConn() { try { Class.forName("com.mysql.cj.jdbc.Driver"); String url = "jdbc:mysql://localhost:3306/test?serverTimezone=UTC"; String user = "root"; String pass = "1234567890"; return DriverManager.getConnection(url, user, pass); } catch (ClassNotFoundException e) { e.printStackTrace(); } catch (SQLException e) { e.printStackTrace(); } return null; } }
获取Mapper的动态代理
import java.lang.reflect.Proxy; public class MapperProxy { public static Object getMapper(Class clazz) { /** * 传入三个参数 * classLoader 代理对象的类加载器对象 * Class<?>[] interfaces 代理类实现的接口的数组(可能会代理多个接口) *InvocationHandler h 方法调用分派给的invocationHandler */ return Proxy.newProxyInstance(MapperProxy.class.getClassLoader(), new Class[]{clazz}, new MyInvocationHandler()); } }
Mapper类
import com.example.mybatisdemo.entity.User; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Select; import java.util.List; public interface UserMapper { @Select("select * from user") List<User> queryAll(); }
实体类User
import lombok.Data; @Data public class User { private int id; private String username; private String name; private int age; private int balance; }
自定义类实现InvocationHandler
package com.example.mybatisdemo.test; import com.example.mybatisdemo.entity.User; import org.apache.ibatis.annotations.Select; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.util.ArrayList; import java.util.List; public class MyInvocationHandler implements InvocationHandler { @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { //获取sql语句 Select annotation = method.getAnnotation(Select.class); String sql = annotation.value()[0]; System.out.println(sql); //解析sql语句 Connection conn = DBManager.getConn(); PreparedStatement ps = conn.prepareStatement(sql); //执行sql语句 jdbc ResultSet rs = ps.executeQuery(); List<User> users = new ArrayList<>(); while (rs.next()) { User user = new User(); user.setId(rs.getInt("id")); user.setUsername(rs.getString("username")); user.setName(rs.getString("name")); user.setAge(rs.getInt("age")); user.setBalance(rs.getInt("balance")); users.add(user); } conn.close(); rs.close(); return users; } }
测试类
import com.example.mybatisdemo.dao.UserMapper; import com.example.mybatisdemo.entity.User; import java.util.List; public class TestMain { public static void main(String [] arg) { UserMapper userMapper = (UserMapper) MapperProxy.getMapper(UserMapper.class); List<User> users = userMapper.queryAll(); for (User user : users) { System.out.println( user.getId() + " " + user.getUsername() + " " + user.getName() + " " + user.getAge() + " " + user.getBalance() ); } } }
SQL文件
/* Navicat Premium Data Transfer Source Server : localhostMysql Source Server Type : MySQL Source Server Version : 50726 Source Host : localhost:3306 Source Schema : test Target Server Type : MySQL Target Server Version : 50726 File Encoding : 65001 Date: 07/10/2019 20:01:36 */ SET NAMES utf8mb4; SET FOREIGN_KEY_CHECKS = 0; -- ---------------------------- -- Table structure for user -- ---------------------------- DROP TABLE IF EXISTS `user`; CREATE TABLE `user` ( `id` int(10) UNSIGNED NOT NULL AUTO_INCREMENT, `username` varchar(40) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '', `name` varchar(20) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL, `age` int(11) NOT NULL, `balance` int(11) UNSIGNED ZEROFILL NOT NULL, PRIMARY KEY (`id`) USING BTREE ) ENGINE = InnoDB AUTO_INCREMENT = 6 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic; -- ---------------------------- -- Records of user -- ---------------------------- INSERT INTO `user` VALUES (1, 'accout1', 'zhangsan', 20, 00000000100); INSERT INTO `user` VALUES (2, 'accout2', 'lisi', 28, 00000000180); INSERT INTO `user` VALUES (3, 'accout3', 'wangwu', 32, 00000000250); INSERT INTO `user` VALUES (4, 'accout4', 'saozhu', 18, 00000000200); INSERT INTO `user` VALUES (5, 'accout5', 'zhangtao', 22, 00000000540); SET FOREIGN_KEY_CHECKS = 1;
笔者也是初学,写博客分享,有错误的地方以及不足的地方欢迎大家指正哈!