今天写一下Mybatis
直接上代码,框架完成后放解释的图
public class MySqlsession {
private Excutor excutor = new MyExcutor();
private MyConfiguration myConfiguration = new MyConfiguration();
public <T> T selectOne(String statement , Object parameter) {
return excutor.query(statement , parameter);
}
public <T> T getMapper(Class<T> clazz) {
//动态代理调用
return (T) Proxy.newProxyInstance(clazz.getClassLoader() , new Class[]{clazz} ,
new MyMapperProxy(myConfiguration , this));
}
}
public class MyMapperProxy implements InvocationHandler {
private MySqlsession mySqlsession;
private MyConfiguration myConfiguration;
public MyMapperProxy(MyConfiguration myConfiguration ,MySqlsession mySqlsession) {
this.mySqlsession = mySqlsession;
this.myConfiguration = myConfiguration;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
MapperBean readMapper = myConfiguration.readMapper("userMapper.xml");
//是否是xml文件对应的接口
if(!method.getDeclaringClass().getName().equals(readMapper.getInterfaceName())) {
return null;
}
List<Function> list = readMapper.getList();
if(null != list || 0 != list.size()) {
for(Function function : list) {
if(method.getName().equals(function.getFuncName())) {
return mySqlsession.selectOne(function.getSql() , String.valueOf(args[0]));
}
}
}
return null;
}
}
public class MyConfiguration {
private static ClassLoader loader = ClassLoader.getSystemClassLoader();
/**
* 读取xml信息并处理
* @param resource
* @return
*/
public Connection bulid(String resource) {
try {
InputStream stream = loader.getResourceAsStream(resource);
SAXReader reader = new SAXReader();
Document document = reader.read(stream);
Element root = document.getRootElement();
return evalDataSource(root);
} catch (Exception e) {
throw new RuntimeException("error occured while evaling xml" + resource);
}
}
private Connection evalDataSource(Element node) throws ClassNotFoundException {
if(!node.getName().equals("database")) {
throw new RuntimeException("root shoule be <database>");
}
String driverClassName = null;
String url = null;
String username = null;
String password = null;
//获取属性节点
for(Object item : node.elements("property")) {
Element i = (Element)item;
String value = getValue(i);
String name = i.attributeValue("name");
if(name == null || value == null) {
throw new RuntimeException("[database]:<property> should contain name and value");
}
//赋值
switch (name) {
case "url" : url = value; break;
case "username" : username = value; break;
case "password" : password = value; break;
case "driverClassName" : driverClassName = value; break;
}
}
Class.forName(driverClassName);
Connection connection = null;
try {
//建立数据库链接
connection = DriverManager.getConnection(url , username , password);
} catch (SQLException e) {
System.out.println("凉凉:数据库链接错误");
}
return connection;
}
//获取property属性的值,如果有value值,则读取;否则读取内容
private String getValue(Element node) {
return node.hasContent() ? node.getText() : node.attributeValue("value");
}
public MapperBean readMapper(String path) {
MapperBean mapper = new MapperBean();
try {
InputStream stream = loader.getResourceAsStream(path);
SAXReader reader = new SAXReader();
Document document = reader.read(stream);
Element root = document.getRootElement();
//把mapper节点的namespace值存为接口名
mapper.setInterfaceName(root.attributeValue("namespace".trim()));
//用来存储方法的List
List<Function> list = new ArrayList<Function>();
//遍历根节点下所有子节点
for(Iterator rootIter = root.elementIterator() ; rootIter.hasNext();) {
Element e = (Element)rootIter.next();
//以resources/UserMapper.xml为例
//select
String sqlType = e.getName().trim();
//getUserById
String funcName = e.attributeValue("id").trim();
//select * from user where id = ?
String sql = e.getText().trim();
//org.chielong.bean.User
String resultType = e.attributeValue("resultType").trim();
Object newInstance = Class.forName(resultType).newInstance();
//用来存储一条方法的信息
Function fun = new Function();
fun.setSqlType(sqlType);
fun.setFuncName(funcName);
fun.setSql(sql);
fun.setResultType(newInstance);
list.add(fun);
}
mapper.setList(list);
} catch (DocumentException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
return mapper;
}
}
public class MapperBean {
//接口名
private String interfaceName;
//接口下所有方法
private List<Function> list;
//getter & setter
}
public class Function {
private String sqlType;
private String funcName;
private String sql;
private Object resultType;
private String parameterType;
//getter & setter
}
public interface Excutor {
public <T> T query(String statement , Object parameter);
}
public class MyExcutor implements Excutor{
private MyConfiguration xmlConfiguration = new MyConfiguration();
@Override
public <T> T query(String sql, Object parameter) {
Connection connection = getConnection();
ResultSet set = null;
PreparedStatement pre = null;
try {
pre = connection.prepareStatement(sql);
//设置参数
pre.setString(1 , parameter.toString());
set = pre.executeQuery();
User u = new User();
while(set.next()) {
u.setId(set.getString(1));
u.setUsername(set.getString(2));
u.setPassword(set.getString(3));
}
return (T) u;
} catch (SQLException e) {
e.printStackTrace();
} finally {
try {
if(set != null) {
set.close();
}
if(pre != null) {
pre.close();
}
if(connection != null) {
connection.close();
}
} catch (Exception e) {
e.printStackTrace();
}
}
return null;
}
private Connection getConnection() {
try {
return xmlConfiguration.bulid("config.xml");
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
}
(本来想写字的...想了想还是画图更直观)
(自从用了processon画图...真香)
public interface UserMapper {
public User getUserById(String id);
}
public class User {
private String id;
private String username;
private String password;
//getter & setter & toString
}
<?xml version="1.0" encoding="UTF-8"?>
<mapper nameSpace="org.chielong.mapper.UserMapper">
<select id="getUserById" resultType="org.chielong.bean.User">
select * from user where id = ?
</select>
</mapper>