package com.zjy.mybatis.test;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javassist.ClassPool;
import javassist.CtClass;
import javassist.CtMethod;
import javassist.CtNewMethod;
import com.zjy.jdbc.util.DBUtil;
public class MyBatisReflectUtil {
private static MyBatisConfig config;
static {
try {
String configXml = "/mybatisConfig.xml";
config = MyBatisParseUtil.parse(configXml);
} catch (Exception e) {
e.printStackTrace();
}
}
public static Map<String, Object> convert(Object obj) throws Exception {
List<Class> list = new ArrayList<Class>();
list.add(Integer.class);
list.add(Double.class);
list.add(Float.class);
list.add(String.class);
list.add(int.class);
list.add(float.class);
list.add(double.class);
Class clazz = obj.getClass();
Map<String, Object> result = new HashMap<String, Object>();
if (list.contains(obj.getClass())) {
result.put("$1", obj);
} else {
Field[] fields = clazz.getDeclaredFields();
for (Field field : fields) {
String name = field.getName();
field.setAccessible(true);
Object value = field.get(obj);
result.put(name, value);
}
}
return result;
}
public static Object getMapper(String type) throws Exception {
ClassPool pool = ClassPool.getDefault();
// String type="com.zjy.mybatis.model.Customer";
String proxyPuffix = "$Proxy_";
String proxyType = type + proxyPuffix;
CtClass interfaceClazz = pool.get(type);
CtClass implClazz = pool.makeClass(proxyType);
implClazz.addInterface(interfaceClazz);
Class mapperInterface = Class.forName(type);
Method methods[] = mapperInterface.getDeclaredMethods();
String mapperClazzName = mapperInterface.getName();
for (Method method : methods) {
String methodName = method.getName();
if ( methodName.equals("query")) {
continue;
}
CtMethod cm = interfaceClazz.getDeclaredMethod(method.getName());
CtMethod methodImpl = CtNewMethod.copy(cm, implClazz, null);
StringBuilder body =new StringBuilder("{");
Map<String, MapperConfig> mapperConfigs = config.getMapperConfig();
MapperConfig cfg = mapperConfigs.get(type);
Map<String, Sql> map = cfg.getSqls();
Sql sql=map.get(methodName);
if(sql.getSqlType().equals("select")){
String resultType=sql.getResultType();
body.append("return ("+resultType+")");
}
body.append(MyBatisReflectUtil.class.getName()+ ".executeById(\"" + mapperClazzName + "\",\""+ methodName + "\",$1);");;
body.append("}");
System.out.println(body.toString());
methodImpl.setBody(body.toString());
implClazz.addMethod(methodImpl);
}
Class clazz = implClazz.toClass();
return clazz.newInstance();
}
public static Object executeById(String nameSpace, String id, int param) {
return executeById(nameSpace, id, Integer.valueOf(param));
}
public static Object executeById(String nameSpace, String id, Object param) {
try {
Map<String, MapperConfig> mapperConfigs = config.getMapperConfig();
MapperConfig cfg = mapperConfigs.get(nameSpace);
Map<String, Sql> map = cfg.getSqls();
Sql sql=map.get(id);
String executeSql = sql.getSql();
Map<String, Object> properties = MyBatisReflectUtil.convert(param);
if(sql.getSqlType().equals("select")){
String resultMapName=sql.getResultMap();
ResultMap resultMap=cfg.getResultMap().get(resultMapName);
return executeQuery(sql, resultMap, properties);
}else{
return execute(executeSql, properties);
}
} catch (Exception e) {
throw new IllegalArgumentException(e);
}
}
public static Object executeQuery(Sql sql, ResultMap map,Map<String, Object> properties)
throws Exception {
String reg = "\\#\\{([^\\}]*)\\}";
Pattern pattern = Pattern.compile(reg);
String querySql=sql.getSql();
Matcher matcher = pattern.matcher(querySql);
int i = 0;
List<ParameterPosition> list = new ArrayList<ParameterPosition>();
while (matcher.find()) {
String text = matcher.group(1);
ParameterPosition position = new ParameterPosition();
position.setIndex(i);
position.setName(text);
i = i + 1;
list.add(position);
}
querySql = querySql.replaceAll("\\#\\{([^\\}]*)\\}", "?");
Object paramterValues[] = new Object[list.size()];
for (int t = 0; t < list.size(); t++) {
ParameterPosition position = list.get(t);
int index = position.getIndex();
String name = position.getName();
if (properties.containsKey("$1")) {
paramterValues[index] = properties.get("$1");
} else {
paramterValues[index] = properties.get(name);
}
}
List<Map<String,Object>> resultSet=DBUtil.preExecuteQuery(querySql, paramterValues);
if(resultSet.size()==1){
String resultType=sql.getResultType();
Class resultClass=Class.forName(resultType);
Object result=resultClass.newInstance();
Map<String,Object> values=resultSet.get(0);
for(Entry<String,String> entry:map.getResultMap().entrySet()){
String property=entry.getKey();
String column=entry.getValue();
Field field=resultClass.getDeclaredField(property);
field.setAccessible(true);
field.set(result, values.get(column));
}
return result;
}
throw new IllegalArgumentException("返回多个值,暂时不支持!!");
}
public static boolean execute(String sql, Map<String, Object> properties)
throws Exception {
String reg = "\\#\\{([^\\}]*)\\}";
Pattern pattern = Pattern.compile(reg);
Matcher matcher = pattern.matcher(sql);
int i = 0;
List<ParameterPosition> list = new ArrayList<ParameterPosition>();
while (matcher.find()) {
String text = matcher.group(1);
ParameterPosition position = new ParameterPosition();
position.setIndex(i);
position.setName(text);
i = i + 1;
list.add(position);
}
sql = sql.replaceAll("\\#\\{([^\\}]*)\\}", "?");
Object paramterValues[] = new Object[list.size()];
for (int t = 0; t < list.size(); t++) {
ParameterPosition position = list.get(t);
int index = position.getIndex();
String name = position.getName();
if (properties.containsKey("$1")) {
paramterValues[index] = properties.get("$1");
} else {
paramterValues[index] = properties.get(name);
}
}
return DBUtil.preExecute(sql, paramterValues);
}
}
package com.zjy.mybatis.test;
import java.util.Map;
public class MapperConfig {
private String nameSpace;
private Map<String, Sql> upddateSqls;
private Map<String,ResultMap> resultMap;
public String getNameSpace() {
return nameSpace;
}
public void setNameSpace(String nameSpace) {
this.nameSpace = nameSpace;
}
public Map<String, Sql> getSqls() {
return upddateSqls;
}
public void setSqls(Map<String, Sql> updateSqls) {
this.upddateSqls = updateSqls;
}
public Map<String, ResultMap> getResultMap() {
return resultMap;
}
public void setResultMap(Map<String, ResultMap> resultMap) {
this.resultMap = resultMap;
}
}
package com.zjy.mybatis.test;
import java.util.Map;
public class MyBatisConfig {
private Map<String, String> dataSourceConfig;
private Map<String, MapperConfig> mapperConfig;
public Map<String, String> getDataSourceConfig() {
return dataSourceConfig;
}
public void setDataSourceConfig(Map<String, String> dataSourceConfig) {
this.dataSourceConfig = dataSourceConfig;
}
public Map<String, MapperConfig> getMapperConfig() {
return mapperConfig;
}
public void setMapperConfig(Map<String, MapperConfig> mapperConfig) {
this.mapperConfig = mapperConfig;
}
}
package com.zjy.mybatis.test;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.dom4j.Document;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
public class MyBatisParseUtil {
public static Map<String, String> getDataSourceConfig(String configXml)
throws Exception {
// String configXml = "/mybatisConfig.xml";
SAXReader reader = new SAXReader();
if (!configXml.startsWith("/")) {
configXml = "/" + configXml;
}
Document document = reader.read(MyBatisMaker.class
.getResource(configXml));
List<Element> list = document
.selectNodes("/configuration/environments/environment/dataSource/property");
Map<String, String> config = new HashMap<String, String>();
for (Element node : list) {
String name = node.attributeValue("name");
String value = node.attributeValue("value");
config.put(name, value);
}
return config;
}
public static List<String> getMapperResources(String configXml)
throws Exception {
SAXReader reader = new SAXReader();
Document document = reader.read(MyBatisMaker.class
.getResource(configXml));
List<Element> list = document
.selectNodes("/configuration/mappers/mapper");
List<String> result = new ArrayList<String>();
for (Element node : list) {
String resource = node.attributeValue("resource");
result.add(resource);
}
return result;
}
public static MapperConfig parseMapper(String configXml) throws Exception {
SAXReader reader = new SAXReader();
if (!configXml.startsWith("/")) {
configXml = "/" + configXml;
}
InputStream inputStream = System.class.getResourceAsStream(configXml);
Document document = reader.read(inputStream);
Element root = document.getRootElement();
String mapperType = root.attributeValue("namespace");
List<String> expresses = new ArrayList<String>();
expresses.add("/mapper/insert");
expresses.add("/mapper/update");
expresses.add("/mapper/delete");
expresses.add("/mapper/select");
Map<String, Sql> sqls = new HashMap<String, Sql>();
for (String str : expresses) {
List<Element> elements = root.selectNodes(str);
for (Element ele : elements) {
String id = ele.attributeValue("id");
String parameterType = ele.attributeValue("parameterType");
String resultType = ele.attributeValue("resultType");
String resultMap = ele.attributeValue("resultMap");
String sqlText = ele.getText();
Sql sql = new Sql();
sql.setId(id);
sql.setParameterType(parameterType);
sql.setResultMap(resultMap);
sql.setResultType(resultType);
sql.setSql(sqlText);
String tagName=ele.getName();
sql.setSqlType(tagName);
sqls.put(sql.getId(), sql);
}
}
Map<String,ResultMap> resultMapList=parseResultMap(configXml);
MapperConfig result = new MapperConfig();
result.setNameSpace(mapperType);
result.setSqls(sqls);
result.setResultMap(resultMapList);
return result;
}
public static Map<String,ResultMap> parseResultMap(String configXml)throws Exception{
InputStream inputStream = System.class.getResourceAsStream(configXml);
SAXReader reader=new SAXReader();
Document document = reader.read(inputStream);
List<String> mapExpress=new ArrayList<String>();
mapExpress.add("id");
mapExpress.add("result");
List<Element> resultMapList=document.selectNodes("mapper/resultMap");
Map<String,ResultMap> result=new HashMap<String, ResultMap>();
for(Element resultEle:resultMapList){
String id=resultEle.attributeValue("id");
String type=resultEle.attributeValue("type");
ResultMap resultMap=new ResultMap();
resultMap.setId(id);
resultMap.setType(type);
Map<String,String> propertyMap=new HashMap<String, String>();
for(String express:mapExpress){
List<Element> elements=resultEle.selectNodes(express);
for(Element ele:elements){
String property=ele.attributeValue("property");
String column=ele.attributeValue("column");
propertyMap.put(property, column);
}
resultMap.setPropertyMap(propertyMap);
}
result.put(resultMap.getId(), resultMap);
}
return result;
}
public static MyBatisConfig parse(String configXml) throws Exception {
// String configXml = "/mybatisConfig.xml";
Map<String, String> dataSourceConfig = getDataSourceConfig(configXml);
List<String> resource = getMapperResources(configXml);
Map<String, MapperConfig> mappers = new HashMap<String, MapperConfig>();
for (String str : resource) {
MapperConfig config = parseMapper(str);
mappers.put(config.getNameSpace(), config);
}
MyBatisConfig myBatis = new MyBatisConfig();
myBatis.setDataSourceConfig(dataSourceConfig);
myBatis.setMapperConfig(mappers);
return myBatis;
}
}