简单手写Mybatis大致原理
- 大致原理
- 项目结构
- 项目代码
- 代码测试
大致原理
底层基于JDK动态代理技术实现
项目结构
项目代码
pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com</groupId>
<artifactId>mybatis-jdk-proxy</artifactId>
<version>1.0-SNAPSHOT</version>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>8</source>
<target>8</target>
</configuration>
</plugin>
</plugins>
</build>
<dependencies>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.18</version>
</dependency>
</dependencies>
</project>
config.properties
driverClass=com.mysql.cj.jdbc.Driver
url=jdbc:mysql://127.0.0.1:3306/db_mybatis?serverTimezone=UTC
user=root
password=admin
UserEntity.java
package com.mybatis.entity;
/**
* @author honey
* @date 2023-07-26 15:29:38
*/
public class UserEntity {
private Integer id;
private String name;
@Override
public String toString() {
return "UserEntity{" +
"id=" + id +
", name='" + name + '\'' +
'}';
}
}
UserMapper.java
package com.mybatis.mapper;
import com.mybatis.proxy.Insert;
/**
* @author honey
* @date 2023-07-26 21:04:23
*/
public interface UserMapper {
/**
* 新增用户
*
* @return int
*/
@Insert("INSERT INTO `tb_user` (`id`, `name`) VALUES (null, 'Faker');")
int insertUser();
}
Insert.java
package com.mybatis.proxy;
import java.lang.annotation.*;
/**
* @author honey
* @date 2023-07-27 20:48:38
*/
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface Insert {
String value();
}
JdbcUtils.java
package com.mybatis.proxy;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.Statement;
import java.util.Properties;
/**
* @author honey
* @date 2023-07-27 20:57:08
*/
public class JdbcUtils {
private JdbcUtils() {
}
private static String url;
private static String user;
private static String password;
static {
try {
InputStream resourceAsStream = JdbcUtils.class.getClassLoader().
getResourceAsStream("config.properties");
Properties properties = new Properties();
properties.load(resourceAsStream);
String driverClass = properties.getProperty("driverClass");
url = properties.getProperty("url");
user = properties.getProperty("user");
password = properties.getProperty("password");
Class.forName(driverClass);
} catch (Exception e) {
e.printStackTrace();
}
}
public static Connection getConnection() {
try {
return DriverManager.getConnection(url, user, password);
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
public static void closeConnection(ResultSet resultSet, Statement statement, Connection connection) {
try {
if (resultSet != null) {
resultSet.close();
}
if (statement != null) {
statement.close();
}
if (connection != null) {
connection.close();
}
} catch (Exception e) {
e.printStackTrace();
}
}
public static void closeConnection(Statement statement, Connection connection) {
closeConnection(null, statement, connection);
}
}
MapperProxy.java
package com.mybatis.proxy;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.sql.Connection;
import java.sql.PreparedStatement;
/**
* @author honey
* @date 2023-07-27 20:17:23
*/
public class MapperProxy implements InvocationHandler {
private final Class<?> mapperClass;
public MapperProxy(Class<?> mapperClass) {
this.mapperClass = mapperClass;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
// 使用Java反射技术获取该方法上的注解
Insert declaredAnnotation = method.getDeclaredAnnotation(Insert.class);
String insertSql = declaredAnnotation.value();
// 执行sql语句
Connection connection = JdbcUtils.getConnection();
PreparedStatement preparedStatement = connection.prepareStatement(insertSql);
return preparedStatement.executeUpdate();
}
public <T> T getProxy() {
return (T) Proxy.newProxyInstance(mapperClass.getClassLoader(), new Class[]{mapperClass}, this);
}
}
SqlSession.java
package com.mybatis.proxy;
/**
* @author honey
* @date 2023-07-27 21:10:30
*/
public class SqlSession {
public static <T> T getMapper(Class<T> type) {
return new MapperProxy(type).getProxy();
}
}
MybatisTest.java
package com.mybatis.test;
import com.mybatis.mapper.UserMapper;
import com.mybatis.proxy.SqlSession;
/**
* @author honey
* @date 2023-07-26 15:26:48
*/
public class MybatisTest {
public static void main(String[] args) {
System.getProperties().put("sun.misc.ProxyGenerator.saveGeneratedFiles", "true");
UserMapper userMapper = SqlSession.getMapper(UserMapper.class);
int result = userMapper.insertUser();
System.out.println(result);
}
}
代码测试
运行MybatisTest类
SqlSession.java
MapperProxy.java
MybatisTest.java
MapperProxy.java
MybatisTest.java
运行结果