手写简单版mybatis
时间: 2023-06-19 15:07:47 浏览: 140
项目:简易Mybatis
Mybatis 是一款优秀的持久层框架,它可以对 JDBC 进行封装,使得开发者可以通过 XML 文件或注解来配置 SQL 语句,从而避免了手写 JDBC 代码的繁琐和重复。下面,我将简单介绍如何手写一个简单版的 Mybatis。
1. 创建配置文件
在 resources 目录下创建一个 mybatis-config.xml 文件,用于配置 Mybatis 的各种参数。其中包括数据库连接信息、mapper 文件路径、缓存配置、插件等。以下是一个简单的配置文件示例:
```
<configuration>
<dataSource type="POOLED">
<property name="driver" value="${driver}"/>
<property name="url" value="${url}"/>
<property name="username" value="${username}"/>
<property name="password" value="${password}"/>
</dataSource>
<mappers>
<mapper resource="com/example/mapper/UserMapper.xml"/>
</mappers>
</configuration>
```
2. 创建数据库连接池
在 Mybatis 中,我们可以通过数据源来获取数据库连接。下面是一个简单的数据源示例:
```
public class PooledDataSource {
private static final String driver = "com.mysql.jdbc.Driver";
private static final String url = "jdbc:mysql://localhost:3306/mybatis";
private static final String username = "root";
private static final String password = "root";
private static final int initialSize = 5;
private static final int maxActive = 10;
private static final int maxIdle = 8;
private static final int minIdle = 5;
private static final long maxWait = 60000;
private static DataSource dataSource;
static {
try {
GenericObjectPoolConfig<Connection> poolConfig = new GenericObjectPoolConfig<>();
poolConfig.setMinIdle(minIdle);
poolConfig.setMaxIdle(maxIdle);
poolConfig.setMaxTotal(maxActive);
poolConfig.setMaxWaitMillis(maxWait);
ConnectionFactory connectionFactory = new DriverManagerConnectionFactory(url, username, password);
PoolableConnectionFactory poolableConnectionFactory = new PoolableConnectionFactory(connectionFactory, null);
poolableConnectionFactory.setValidationQuery("SELECT 1");
dataSource = new PoolingDataSource(poolableConnectionFactory.getPool());
} catch (Exception e) {
e.printStackTrace();
}
}
public static DataSource getDataSource() {
return dataSource;
}
}
```
3. 创建 SqlSession
SqlSession 是 Mybatis 中用于执行 SQL 语句的核心接口,它提供了各种方法来执行 SQL 语句、获取 Mapper 等。下面是一个简单的 SqlSession 实现:
```
public class DefaultSqlSession implements SqlSession {
private final Configuration configuration;
private final Executor executor;
public DefaultSqlSession(Configuration configuration, Executor executor) {
this.configuration = configuration;
this.executor = executor;
}
@Override
public <T> T selectOne(String statement, Object parameter) {
return executor.query(statement, parameter);
}
@Override
public <T> T getMapper(Class<T> type) {
return configuration.getMapper(type, this);
}
}
```
4. 创建 Executor
Executor 是 Mybatis 中用于执行 SQL 语句的实现类,它提供了各种方法来执行 SQL 语句、获取结果等。下面是一个简单的 Executor 实现:
```
public class SimpleExecutor implements Executor {
private final DataSource dataSource;
public SimpleExecutor(DataSource dataSource) {
this.dataSource = dataSource;
}
@Override
public <T> T query(String statement, Object parameter) {
Connection connection = null;
PreparedStatement preparedStatement = null;
ResultSet resultSet = null;
try {
connection = dataSource.getConnection();
preparedStatement = connection.prepareStatement(statement);
preparedStatement.setString(1, parameter.toString());
resultSet = preparedStatement.executeQuery();
if (resultSet.next()) {
return (T) resultSet.getString(1);
}
} catch (SQLException e) {
e.printStackTrace();
} finally {
try {
resultSet.close();
preparedStatement.close();
connection.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
return null;
}
}
```
5. 创建 Mapper
Mapper 是 Mybatis 中用于定义 SQL 语句的接口,它包含了各种方法来执行 SQL 语句、获取结果等。下面是一个简单的 Mapper 接口示例:
```
public interface UserMapper {
@Select("SELECT * FROM user WHERE id = #{id}")
User selectById(Integer id);
}
```
6. 创建 Configuration
Configuration 是 Mybatis 中用于配置各种参数的类,它负责解析配置文件、创建 SqlSession 和 Mapper 等。下面是一个简单的 Configuration 实现:
```
public class Configuration {
private final Properties properties;
private final Map<Class<?>, MapperProxyFactory<?>> mapperProxyFactoryMap = new HashMap<>();
public Configuration(Properties properties) {
this.properties = properties;
}
public <T> T getMapper(Class<T> type, SqlSession sqlSession) {
MapperProxyFactory<T> mapperProxyFactory = (MapperProxyFactory<T>) mapperProxyFactoryMap.get(type);
if (mapperProxyFactory == null) {
mapperProxyFactory = new MapperProxyFactory<>(type);
mapperProxyFactoryMap.put(type, mapperProxyFactory);
}
return mapperProxyFactory.newInstance(sqlSession);
}
}
```
7. 创建 MapperProxyFactory 和 MapperProxy
MapperProxyFactory 是 Mybatis 中用于创建 MapperProxy 的工厂类,它负责创建 MapperProxy 并维护 Mapper 接口和对应的 MapperProxy。MapperProxy 是 Mybatis 中用于动态代理 Mapper 接口的类,它负责解析 Mapper 接口中定义的 SQL 语句,并将其转化为对应的 SQL 语句执行器。下面是一个简单的 MapperProxyFactory 和 MapperProxy 实现:
```
public class MapperProxyFactory<T> {
private final Class<T> mapperInterface;
public MapperProxyFactory(Class<T> mapperInterface) {
this.mapperInterface = mapperInterface;
}
public T newInstance(SqlSession sqlSession) {
return (T) Proxy.newProxyInstance(mapperInterface.getClassLoader(), new Class[]{mapperInterface}, new MapperProxy(sqlSession, mapperInterface));
}
}
public class MapperProxy<T> implements InvocationHandler {
private final SqlSession sqlSession;
private final Class<T> mapperInterface;
public MapperProxy(SqlSession sqlSession, Class<T> mapperInterface) {
this.sqlSession = sqlSession;
this.mapperInterface = mapperInterface;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Select select = method.getAnnotation(Select.class);
if (select != null) {
String sql = select.value()[0];
return sqlSession.selectOne(sql, args[0]);
}
throw new RuntimeException("No such method: " + method.getName());
}
}
```
至此,我们就手写了一个简单版的 Mybatis,它包含了配置文件、数据库连接池、SqlSession、Executor、Mapper 等核心组件。虽然这个实现比较简单,但它足以帮助我们理解 Mybatis 的核心原理。
阅读全文