对于Mybatis2.0框架,主要是对代码进行优化,重构,实现了专人做专事的职责功能,在里面我们主要使用了设计模式中装饰器模式,代理模式,工厂模式。
对于Mybatis代理模式有些特殊的
对于专人做做事加入了
整体布局:
MConfiguration 代码:
/**
*
*/
package com.matao.mybatis.config;
import com.matao.mybatis.mapper.MapperRegistory;
/**
* @author MT
*
*/
public class MConfiguration {
private String scanPath;
private MapperRegistory mapperRegistory = new MapperRegistory();
public MConfiguration scanPath(String scanPath){
this.scanPath = scanPath;
return this;
}
public void build(){
if (scanPath == null || scanPath.length() <1) {
throw new RuntimeException("this scanPath is required");
}
}
public String getScanPath() {
return scanPath;
}
public void setScanPath(String scanPath) {
this.scanPath = scanPath;
}
public MapperRegistory getMapperRegistory() {
return mapperRegistory;
}
public void setMapperRegistory(MapperRegistory mapperRegistory) {
this.mapperRegistory = mapperRegistory;
}
}
MSqlSession代码:
/**
*
*/
package com.matao.mybatis.sqlsession;
import java.lang.reflect.Proxy;
import com.matao.mybatis.config.MConfiguration;
import com.matao.mybatis.excuter.Executer;
import com.matao.mybatis.excuter.SimpleExecuter;
import com.matao.mybatis.mapper.MapperProxy;
import com.matao.mybatis.mapper.MapperRegistory;
public class MSqlSession {
private MConfiguration configuration;
private Executer<?> executer;
public MConfiguration getConfiguration() {
return configuration;
}
//构造方法
public MSqlSession(MConfiguration configuration, Executer executer) {
super();
this.configuration = configuration;
this.executer = executer;
}
//得到mapper对象
public MSqlSession() {
super();
// TODO Auto-generated constructor stub
}
public <T> T getMapper(Class<T> clazz){
return (T) Proxy.newProxyInstance(clazz.getClassLoader(),
new Class[]{clazz}, new MapperProxy<T>(this,clazz));
}
//实现查询方法
public <T> T selectOne(MapperRegistory.MapperData<T> statement,Object parameter){
return (T) executer.query(statement, parameter);
}
}
MapperProxy代码:
/**
*
*/
package com.matao.mybatis.mapper;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import com.matao.mybatis.sqlsession.MSqlSession;
/**
* @author MT
* @param <T>
*
*/
public class MapperProxy<T> implements InvocationHandler{
private final MSqlSession mSqlSession;
private final Class<T> mapperInterface;
/**
* @param <T>
* @param mSqlSession
* @param clazz
*/
public MapperProxy(MSqlSession mSqlSession, Class<T> clazz) {
this.mSqlSession = mSqlSession;
this.mapperInterface = clazz;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println(method.getDeclaringClass().getName() + "." + method.getName());
MapperRegistory.MapperData mapperData =
mSqlSession
.getConfiguration()
.getMapperRegistory()
.get(method.getDeclaringClass().getName() + "." + method.getName());
if (mapperData != null) {
return mSqlSession.selectOne(mapperData, String.valueOf(args[0]));
}
return method.invoke(proxy, args);
}
}
MapperRegistory 代码:
/**
*
*/
package com.matao.mybatis.mapper;
import java.util.HashMap;
import java.util.Map;
import com.matao.mybatis.Test;
/**
* @author MT
*
*/
public class MapperRegistory {
private static Map<String, MapperData> methodSqlMapping = new HashMap<String, MapperData>();
public MapperRegistory(){
methodSqlMapping.put("com.matao.mybatis.mapper.TestMapper.selectByPrimaryKey",
new MapperData("select * from test where id = %d", Test.class));
}
public class MapperData<T>{
private String sql;
private Class<T> type;
public MapperData(String sql, Class<T> type) {
super();
this.sql = sql;
this.type = type;
}
/**
* @return the sql
*/
public String getSql() {
return sql;
}
/**
* @param sql the sql to set
*/
public void setSql(String sql) {
this.sql = sql;
}
/**
* @return the type
*/
public Class<T> getType() {
return type;
}
/**
* @param type the type to set
*/
public void setType(Class<T> type) {
this.type = type;
}
}
public Map<String, MapperData> getMethodSqlMapping() {
return methodSqlMapping;
}
public void setMethodSqlMapping(Map<String, MapperData> methodSqlMapping) {
MapperRegistory.methodSqlMapping = methodSqlMapping;
}
/**
* @param string
* @return
*/
public MapperData get(String key) {
return methodSqlMapping.get(key);
}
}
Executer代码:
/**
*
*/
package com.matao.mybatis.excuter;
import com.matao.mybatis.mapper.MapperRegistory;
/**
* @author MT
* @param <T>
*
*/
public interface Executer<T> {
/**
* @param statement
* @param parameter
* @return
*/
T query(MapperRegistory.MapperData statement, Object parameter);
}
ExecuterFactory 代码:
/**
*
*/
package com.matao.mybatis.factory;
import java.io.ObjectInputStream.GetField;
import com.matao.mybatis.config.MConfiguration;
import com.matao.mybatis.excuter.CacheingExecuter;
import com.matao.mybatis.excuter.Executer;
import com.matao.mybatis.excuter.SimpleExecuter;
/**
* @author MT
*
*/
public class ExecuterFactory {
private static final String SIMPLE="simple";
private static final String CACHE="cache";
public static Executer DEFAULT(MConfiguration configuration){
return get(SIMPLE,configuration);
}
/**
* @param simple2
* @param configuration
* @return
*/
public static Executer get(String key, MConfiguration configuration) {
if (SIMPLE.equalsIgnoreCase(key)) {
return new SimpleExecuter(configuration);
}
if (CACHE.equalsIgnoreCase(key)) {
return new CacheingExecuter(new SimpleExecuter(configuration));
}
throw new RuntimeException("executer is not found");
}
public enum ExecuterType{
SIMPLE,
CACHE
}
}
SimpleExecuter 代码:
/**
*
*/
package com.matao.mybatis.excuter;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import com.matao.mybatis.Test;
import com.matao.mybatis.config.MConfiguration;
import com.matao.mybatis.handler.StatementHandler;
import com.matao.mybatis.mapper.MapperRegistory;
/**
* @author MT
* @param <E>
*
*/
public class SimpleExecuter implements Executer{
private MConfiguration configuration;
public SimpleExecuter() {
super();
// TODO Auto-generated constructor stub
}
public SimpleExecuter(MConfiguration configuration) {
super();
this.configuration = configuration;
}
public MConfiguration getConfiguration() {
return configuration;
}
public void setConfiguration(MConfiguration configuration) {
this.configuration = configuration;
}
/* (non-Javadoc)
* @see com.matao.mybatis.excuter.Executer#query(java.lang.String, java.lang.Object)
*/
@Override
public Object query(MapperRegistory.MapperData mapperdata, Object parameter) {
try {
StatementHandler handler = new StatementHandler(configuration);
return handler.query(mapperdata,parameter);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
}
}
StatementHandler代码:
/**
*
*/
package com.matao.mybatis.handler;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import com.matao.mybatis.config.MConfiguration;
import com.matao.mybatis.mapper.MapperRegistory;
/**
* @author MT
* @param <E>
*
*/
public class StatementHandler<E> {
private final MConfiguration configuration;
private final Resulthandler resulthandler;
String driver = "com.mysql.jdbc.Driver";
String username = "root";
String password = "123456";
String url = "jdbc:mysql://localhost:3310/test";
public StatementHandler(MConfiguration configuration) {
super();
this.configuration = configuration;
this.resulthandler = new Resulthandler(configuration);
}
/**
* @param mapperdata
* @param parameter
* @return
* @throws Exception
*/
public <E> E query(MapperRegistory.MapperData mapperdata, Object parameter) throws Exception {
try {
Connection conn = getConnection();
PreparedStatement psStatement;
psStatement = conn.prepareCall(String.format(mapperdata.getSql(), Integer.parseInt(String.valueOf(parameter))));
psStatement.execute();
return (E) Resulthandler.handle(psStatement,mapperdata);
} catch (NumberFormatException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
}
/**
* @return
*/
private Connection getConnection() {
Connection conn =null;
try {
Class.forName(driver);
conn = DriverManager.getConnection(url, username, password);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return conn;
}
/**
* @return the configuration
*/
public MConfiguration getConfiguration() {
return configuration;
}
/**
* @return the resulthandler
*/
public Resulthandler getResulthandler() {
return resulthandler;
}
}
Resulthandler 代码:
/**
*
*/
package com.matao.mybatis.handler;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import com.matao.mybatis.config.MConfiguration;
import com.matao.mybatis.mapper.MapperRegistory;
/**
* @author MT
*
*/
public class Resulthandler {
private final MConfiguration configuration;
public Resulthandler(MConfiguration configuration) {
super();
this.configuration = configuration;
}
/**
* @param <E>
* @param <T>
* @param psStatement
* @param mapperdata
* @return
* @throws Exception
*/
public static <E, T> E handle(PreparedStatement psStatement, MapperRegistory.MapperData<T> mapperdata) throws Exception {
Object resultObj = mapperdata.getType().newInstance();
ResultSet rs = psStatement.getResultSet();
if(rs.next()) {
int i = 0;
for(Field field : resultObj.getClass().getDeclaredFields()){
System.out.println(field);
setValue(resultObj,field,rs,i);
}
}
return (E) resultObj;
}
/**
* @param <T>
* @param resultObj
* @param field
* @param rs
* @param i
* @throws Exception
*/
private static <T> void setValue(Object resultObj, Field field, ResultSet rs, int i) throws Exception {
Method setMethod = resultObj.getClass().getMethod("set" + upperCapital(field.getName()), field.getType());
System.out.println(setMethod.getName());
setMethod.invoke(resultObj, getResult(field,rs));
}
/**
* @param name
* @return
*/
private static String upperCapital(String name) {
String first = name.substring(0, 1);
String tail = name.substring(1);
return first.toUpperCase() + tail;
}
/**
* @param field
* @param rs
* @return
* @throws SQLException
*/
private static Object getResult(Field field, ResultSet rs) throws SQLException {
Class<?> type = field.getType();
if (Integer.class == type) {
return rs.getInt(field.getName());
}
if (String.class == type) {
return rs.getString(field.getName());
}
return rs.getString(field.getName());
}
/**
* @return the configuration
*/
public MConfiguration getConfiguration() {
return configuration;
}
}
CacheingExecuter代码:
/**
*
*/
package com.matao.mybatis.excuter;
import java.util.HashMap;
import java.util.Map;
import com.matao.mybatis.config.MConfiguration;
import com.matao.mybatis.handler.StatementHandler;
import com.matao.mybatis.mapper.MapperRegistory.MapperData;
/**
* @author MT
* @param <T>
* @param <T>
*
*/
public class CacheingExecuter<T> implements Executer<T>{
private MConfiguration configguration;
private SimpleExecuter delegate;
private Map<String, Object> localCache = new HashMap<String, Object>();
public CacheingExecuter() {
super();
// TODO Auto-generated constructor stub
}
public MConfiguration getConfigguration() {
return configguration;
}
public void setConfigguration(MConfiguration configguration) {
this.configguration = configguration;
}
public CacheingExecuter(MConfiguration configguration) {
super();
this.configguration = configguration;
}
public CacheingExecuter(SimpleExecuter delegate) {
super();
this.delegate = delegate;
}
@Override
public T query(MapperData mapperdata, Object parameter) {
// TODO Auto-generated method stub
StatementHandler handler = new StatementHandler<>(configguration);
Object result = localCache.get(mapperdata.getSql());
if (result != null) {
return (T) result;
}
result = (T) delegate.query(mapperdata, parameter);
localCache.put(mapperdata.getSql(), result);
return (T) delegate.query(mapperdata, parameter);
}
}
测试:
TestMapper 代码:
/**
*
*/
package com.matao.mybatis.mapper;
import com.matao.mybatis.Test;
/**
* @author MT
*
*/
public interface TestMapper {
Test selectByPrimaryKey(Integer userid);
}
/**
*
*/
package com.matao.mybatis;
import com.matao.mybatis.config.MConfiguration;
import com.matao.mybatis.excuter.SimpleExecuter;
import com.matao.mybatis.factory.ExecuterFactory;
import com.matao.mybatis.factory.ExecuterFactory.ExecuterType;
import com.matao.mybatis.mapper.TestMapper;
import com.matao.mybatis.sqlsession.MSqlSession;
/**
* @author MT
*
*/
public class BootStrap {
public static void main(String[] args) {
MConfiguration config = new MConfiguration();
config.setScanPath("com.matao.mybatis.mapper");
config.build();
MSqlSession sqlSession = new MSqlSession(config,ExecuterFactory.get(ExecuterType.CACHE.name(),config));
TestMapper mapper = sqlSession.getMapper(TestMapper.class);
Test test = mapper.selectByPrimaryKey(1);
System.out.println(test);
}
}
测试结果
总结:虽然只是简单的手写Mybatis代码:但是基本功能还是可以实现的,也没感觉Mybatis那么高高在上了,至少对他更感兴趣了,而不是说这是一个很难的业务需求了。