MyBatis是一个ORM工具,封装了JDBC的操作,简化业务编程;
Mybatis在web工程中,与Spring集成,提供业务读写数据库的能力。
采用Maven包依赖管理,mybatis-3.5.5版本;同时需要数据库连接驱动
org.mybatis
mybatis
3.5.5
mysql
mysql-connector-java
5.1.49
配置文件配置数据库连接源,及映射文件。
定义实体
package com.xiongxin.mybatis.entity;
public class User {
private String username;
private String password;
...getter&&setter
}
接口定义
package com.xiongxin.mybatis.mapper;
import com.xiongxin.mybatis.entity.User;
import java.util.List;
public interface UserMapper {
List queryUser();
}
定义映射文件
package com.xiongxin.mybatis;
import com.alibaba.fastjson.JSON;
import com.xiongxin.mybatis.entity.User;
import com.xiongxin.mybatis.mapper.UserMapper;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import java.io.IOException;
import java.io.Reader;
import java.util.List;
public class TestMain {
public static void main(String[] args) throws IOException {
String resource = "mybatis-config.xml";
//加载 mybatis 的配置文件(它也加载关联的映射文件)
Reader reader = Resources.getResourceAsReader(resource);
//构建 sqlSession 的工厂
SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder().build(reader);
//创建能执行映射文件中 sql 的 sqlSession
SqlSession session = sessionFactory.openSession();
UserMapper userMapper = session.getMapper(UserMapper.class);
List users = userMapper.queryUser();
System.out.println(JSON.toJSONString(users));
}
}
---------------------------------
..consule print..
[{"password":"password","username":"xiongxin"}]
到这里,这个Mybatis的使用环节结束。
整个实现过程中,我们并未编写Mapper的实现类,框架是如何在无实现类的场景下实现接口方法返回的呢?
这里就不得不说到接口的动态代理方法了。
SqlSession接口的实现中,获取Mapper的代理实现类
使用了JDK动态代理的功能
代理类执行方法调用
方法调用中执行MethodInvoker
最终执行execue方法。
获取返回结果Result
前置知识:
源码:
com.alibaba
fastjson
1.2.74
com.h2database
h2
1.4.199
package com.dbutil.session;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
import java.lang.reflect.*;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.List;
import static java.lang.annotation.ElementType.*;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
/**
* @author xiongxin
*/
public class SqlSession {
public static Connection getConnH2() throws Exception {
String url = "jdbc:h2:mem:db_h2;MODE=MYSQL;INIT=RUNSCRIPT FROM './src/main/resources/schema.sql'";
String user = "root";
String password = "123456";
//1.加载驱动程序
Class.forName("org.h2.Driver");
//2.获得数据库链接
Connection conn = DriverManager.getConnection(url, user, password);
return conn;
}
/**
* 自定义注解
*/
@Target({TYPE, FIELD, METHOD})
@Retention(RUNTIME)
public @interface QueryList {
public String value();
}
/**
* 动态代理
*
* @param mapperInterface
* @param
* @return
*/
public static T getMapper(Class mapperInterface) {
return (T) Proxy.newProxyInstance(mapperInterface.getClassLoader(), new Class[]{mapperInterface}, new MapperInvocationHandler());
}
/**
* 代理类方法
*/
public static class MapperInvocationHandler implements InvocationHandler {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
String sql = method.getAnnotation(QueryList.class).value();
Class> returnType = method.getReturnType();
//返回类型为List
if (returnType == List.class) {
Type genericReturnType = method.getGenericReturnType();
String typeName = genericReturnType.getTypeName();
String replace = typeName.replace("java.util.List<", "").replace(">", "");
//获取泛型类型
Class> forName = Class.forName(replace);
return SqlSession.queryList(sql, forName);
}
return null;
}
}
/**
* 结果集转换
*
* @param
*/
public interface ResultMap {
T convert(ResultSet resultSet) throws Exception;
}
/**
* 创建连接并执行
*
* @param sql
* @param resultMap
* @param
* @return
* @throws Exception
*/
public static List queryList(String sql, ResultMap resultMap) throws Exception {
//jdbc数据库
Connection conn = getConnH2();
//3.通过数据库的连接操作数据库,实现增删改查(使用Statement类)
Statement st = conn.createStatement();
ResultSet rs = st.executeQuery(sql);
List list = new ArrayList<>();
//4.处理数据库的返回结果(使用ResultSet类)
while (rs.next()) {
T convert = resultMap.convert(rs);
list.add(convert);
}
//关闭资源
rs.close();
st.close();
conn.close();
return list;
}
/**
* 查询数据集
*
* @param sql
* @param returnType
* @param
* @return
* @throws Exception
*/
public static List queryList(String sql, Class returnType) throws Exception {
List list = SqlSession.queryList(sql, rs -> {
T obj = returnType.newInstance();
Field[] declaredFields = returnType.getDeclaredFields();
for (Field declaredField : declaredFields) {
Class> type = declaredField.getType();
//类型为String时的处理方法
if (type == String.class) {
String value = rs.getString(declaredField.getName());
String fieldName = declaredField.getName();
Method method = returnType.getDeclaredMethod(
"set".concat(fieldName.substring(0, 1).toUpperCase().concat(fieldName.substring(1))),
String.class);
method.invoke(obj, value);
}
if (type == Long.class) {
Long value = rs.getLong(declaredField.getName());
String fieldName = declaredField.getName();
Method method = returnType.getDeclaredMethod(
"set".concat(fieldName.substring(0, 1).toUpperCase().concat(fieldName.substring(1))),
Long.class);
method.invoke(obj, value);
}
//其他类型处理方法
}
return obj;
});
return list;
}
}
schema.sql文件
drop table if exists user;
CREATE TABLE user
(
id int(11) NOT NULL AUTO_INCREMENT,
username varchar(255) DEFAULT NULL,
password varchar(255) DEFAULT NULL,
PRIMARY KEY (id)
);
insert into user(id,username,password) values(1,'xiongxina','123456');
insert into user(id,username,password) values(2,'xiongxinb','123456');
insert into user(id,username,password) values(3,'xiongxinc','123456');
mapper定义
package com.dbutil.mapper;
import com.dbutil.entity.UserEntity;
import com.dbutil.session.SqlSession;
import java.util.List;
public interface UserMapper {
@SqlSession.QueryList("select * from user")
List queryUser();
}
使用:
package com.dbutil;
import com.dbutil.entity.UserEntity;
import com.dbutil.mapper.UserMapper;
import com.dbutil.session.SqlSession;
import java.util.List;
public class UserService {
public static void main(String[] args) throws Exception {
UserMapper userMapper = SqlSession.getMapper(UserMapper.class);
List userEntities = userMapper.queryUser();
for (UserEntity userEntity : userEntities) {
System.out.println(userEntity);
}
}
}