一,定义实体
public class User {
private int id;
private String name;
private int age;
private String addr;
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 int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getAddr() {
return addr;
}
public void setAddr(String addr) {
this.addr = addr;
}
@Override
public String toString() {
return "User{" +
"id=" + id +
", name='" + name + '\'' +
", age=" + age +
", addr='" + addr + '\'' +
'}';
}
}
二,定义xml
<?xml version="1.0" encoding="UTF-8" ?>
<mapper namespace="test.dao.UserDao">
<select id="getUserInfo" resultType="test.entity.User">
select * from tb_user
where id = ?;
</select>
<update id="updateUserName">
update tb_user set name = ?
where id = ?
</update>
<insert id="insertUser">
insert into tb_user
values(?, ?, ?, ?);
</insert>
</mapper>
三,数据配置
public class Config {
public static final Config DEFAULT = new Config();
private Config() {
}
private String url = "jdbc:mysql://139.199.195.54:3306/weistudy";
private String user = "root";
private String pwd = "kurozakisql";
private String mapperPath = "mapper/";
public String getUrl() {
return url;
}
public String getUser() {
return user;
}
public String getPwd() {
return pwd;
}
public String getMapperPath() {
return mapperPath;
}
}
四,数据源连接
public class ConnectionManager {
public static Connection get() throws SQLException {
return DriverManager.getConnection(
Config.DEFAULT.getUrl(),
Config.DEFAULT.getUser(),
Config.DEFAULT.getPwd()
);
}
}
五,XMl 映射到实体文件
public class MapperInfo {
private QueryType queryType;
private String interfaceName;
private String methodName;
private String sql;
private String resultType;
public QueryType getQueryType() {
return queryType;
}
public void setQueryType(QueryType queryType) {
this.queryType = queryType;
}
public String getSql() {
return sql;
}
public void setSql(String sql) {
this.sql = sql;
}
public String getResultType() {
return resultType;
}
public void setResultType(String resultType) {
this.resultType = resultType;
}
public String getInterfaceName() {
return interfaceName;
}
public void setInterfaceName(String interfaceName) {
this.interfaceName = interfaceName;
}
public String getMethodName() {
return methodName;
}
public void setMethodName(String methodName) {
this.methodName = methodName;
}
@Override
public String toString() {
return "MapperInfo{" +
"queryType=" + queryType +
", interfaceName='" + interfaceName + '\'' +
", methodName='" + methodName + '\'' +
", sql='" + sql + '\'' +
", resultType='" + resultType + '\'' +
'}';
}
}
接口方法
public interface UserDao {
User getUserInfo(int id);
int updateUserName(String newName, int id);
int insertUser(int id, String name, int age, String addr);
}
六,定义枚举查询
public enum QueryType {
SELECT, UPDATE, INSERT, DELETE;
public static QueryType value(String v) {
return valueOf(v.toUpperCase());
}
}
七,SQL映射文件处理器
public enum SqlMappersHolder {
INSTANCE;
private Map<String, MapperInfo> mi = null;
SqlMappersHolder() {
if (mi != null)
return;
mi = new HashMap<>();
File dir = new File(SqlMappersHolder.class
.getClassLoader()
.getResource(Config.DEFAULT.getMapperPath())
.getFile());
SAXReader reader = new SAXReader();
try {
for (String file : dir.list()) {
Document doc = reader.read(new File(dir, file));
Element root = doc.getRootElement();
String className = root.attributeValue("namespace");
for (Object o : root.elements()) {
Element e = (Element) o;
MapperInfo info = new MapperInfo();
info.setQueryType(QueryType.value(e.getName()));
info.setInterfaceName(className);
info.setMethodName(e.attributeValue("id"));
info.setResultType(e.attributeValue("resultType"));
info.setSql(e.getText());
mi.put(idOf(className, e.attributeValue("id")), info);
}
}
} catch (DocumentException e) {
e.printStackTrace();
}
}
public MapperInfo getMapperInfo(String className, String methodName) {
return mi.get(idOf(className, methodName));
}
private String idOf(String className, String methodName) {
return className + "." + methodName;
}
}
八,SQL执行处理器
public class SqlExecuteHandler implements InvocationHandler {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
// get mapper info
MapperInfo info = getMapperInfo(method);
// execute sql
return executeSql(info, args);
}
private MapperInfo getMapperInfo(Method method) throws Exception {
MapperInfo info = SqlMappersHolder.INSTANCE.getMapperInfo(
method.getDeclaringClass().getName(),
method.getName());
if (info == null) {
throw new Exception("Mapper not found for method: " +
method.getDeclaringClass().getName() + "." + method.getName());
}
return info;
}
private Object executeSql(MapperInfo info, Object[] params)
throws SQLException, ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException {
Object result = null;
PreparedStatement pstat = ConnectionManager.get().prepareStatement(info.getSql());
for (int i = 0; i < params.length; i++) {
pstat.setObject(i + 1, params[i]);
}
if (info.getQueryType() == QueryType.SELECT) {
ResultSet rs = pstat.executeQuery();
rs.first();
// 将查询结果映射为Java类或基本数据类型)
// 目前简化版仅支持String和int两种类型
if (rs.getMetaData().getColumnCount() == 1) {
switch (info.getResultType()) {
case "int":
result = rs.getInt(1);
break;
default:
result = rs.getString(1);
}
} else {
Class<?> resTypeClass = Class.forName(info.getResultType());
Object inst = resTypeClass.newInstance();
for (Field field : resTypeClass.getDeclaredFields()) {
String setterName = "set" +
field.getName().substring(0, 1).toUpperCase() +
field.getName().substring(1);
Method md;
switch (field.getType().getSimpleName()) {
case "int":
md = resTypeClass.getMethod(setterName, new Class[]{int.class});
md.invoke(inst, rs.getInt(field.getName()));
break;
default:
md = resTypeClass.getMethod(setterName, new Class[]{String.class});
md.invoke(inst, rs.getString(field.getName()));
}
}
result = inst;
}
} else {
result = pstat.executeUpdate();
}
return result;
}
}
十,SqlSession
public class SqlSession {
@SuppressWarnings("unchecked")
public <T> T getMapper(Class<T> cls) {
return (T) Proxy.newProxyInstance(cls.getClassLoader(),
new Class[]{cls},
new SqlExecuteHandler());
}
}
十一,SqlSessionFactory.
public class SqlSessionFactory {
static {
SqlMappersHolder inst = SqlMappersHolder.INSTANCE;
try {
Class.forName("com.mysql.cj.jdbc.Driver");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
public SqlSession openSession() {
return new SqlSession();
}
}
十二,测试
public class TestClient {
public static void main(String[] args) {
SqlSessionFactory factory = new SqlSessionFactory();
SqlSession sqlSession = factory.openSession();
UserDao userDao = sqlSession.getMapper(UserDao.class);
System.out.println(userDao.getUserInfo(3));
}
}