自定义MyBatis
生活随笔
收集整理的這篇文章主要介紹了
自定义MyBatis
小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.
自定義MyBatis是為了深入了解MyBatis的原理
主要的調(diào)用是這樣的:
//1.讀取配置文件 InputStream in = Resources.getResourceAsStream("SqlMapConfig.xml"); //2.創(chuàng)建SqlSessionFactory工廠 SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder(); SqlSessionFactory factory = builder.build(in); //3.使用工廠生產(chǎn)SqlSession對象 SqlSession session = factory.openSession(); //4.使用SQLSession創(chuàng)建Dao接口的代理對象 UserDao userDao = session.getMapper(UserDao.class); //5.使用代理對象執(zhí)行方法 List<User> users = userDao.findAll(); for (User user : users) {System.out.println(user); } //6.釋放資源 session.close(); in.close();首先第一步:將配置文件SqlMapConfig.xml轉(zhuǎn)為流文件
<?xml version="1.0" encoding="utf-8" ?> <!DOCTYPE configuration><configuration><!--配置環(huán)境--><environments default="mysql"><!--配置mysql的環(huán)境--><environment id="mysql"><!--配置事務(wù)類型--><transactionManager type="JDBC"></transactionManager><!--配置數(shù)據(jù)源(連接池)--><dataSource type="POOLED"><!--配置連接數(shù)據(jù)庫的基本信息--><property name="driver" value="com.mysql.jdbc.Driver"/><property name="url"value="jdbc:mysql://localhost:3306/mybatis?useUnicode=true&characterEncoding=utf8"/><property name="username" value="root"/><property name="password" value="1234"/></dataSource></environment></environments><!--指定映射配置文件的位置,映射配置文件指的是每個dao獨立的配置文件--><!--<mappers><mapper resource="com/jinke/dao/UserDao.xml"/></mappers>--><!--如果是用注解來配置--><mappers><mapper class="com.jinke.dao.UserDao"/></mappers> </configuration> import java.io.InputStream;/*使用類加載器讀取配置文件的類*/ public class Resources {public static InputStream getResourceAsStream(String filePath) {return Resources.class.getClassLoader().getResourceAsStream(filePath);} }第二步:解析配置文件
import com.jinke.mybatis.cfg.Configuration; import com.jinke.mybatis.sqlsession.defaults.DefaultSqlSessionFactory; import com.jinke.mybatis.utils.XMLConfigBuilder;import java.io.InputStream;public class SqlSessionFactoryBuilder {public SqlSessionFactory build(InputStream config) {Configuration cfg = XMLConfigBuilder.loadConfiguration(config);return new DefaultSqlSessionFactory(cfg);} }主要是通過反射將屬性值保存到map中
import com.jinke.mybatis.annotations.Select; import com.jinke.mybatis.cfg.Configuration; import com.jinke.mybatis.cfg.Mapper; import com.jinke.mybatis.io.Resources; import org.dom4j.Attribute; import org.dom4j.Document; import org.dom4j.Element; import org.dom4j.io.SAXReader;import java.io.IOException; import java.io.InputStream; import java.lang.reflect.Method; import java.lang.reflect.ParameterizedType; import java.lang.reflect.Type; import java.util.HashMap; import java.util.List; import java.util.Map;public class XMLConfigBuilder {public static Configuration loadConfiguration(InputStream config) {Configuration cfg = new Configuration();try {SAXReader reader = new SAXReader();Document document = reader.read(config);Element root = document.getRootElement();List<Element> propertyElements = root.selectNodes("//property");for (Element propertyElement : propertyElements) {String name = propertyElement.attributeValue("name");if ("driver".equals(name)) {String driver = propertyElement.attributeValue("value");cfg.setDriver(driver);}if ("url".equals(name)) {String url = propertyElement.attributeValue("value");cfg.setUrl(url);}if ("username".equals(name)) {String username = propertyElement.attributeValue("value");cfg.setUsername(username);}if ("password".equals(name)) {String password = propertyElement.attributeValue("value");cfg.setPassword(password);}}List<Element> mapperElements = root.selectNodes("//mappers/mapper");for (Element mapperElement : mapperElements) {Attribute attribute = mapperElement.attribute("resource");if (attribute != null) {System.out.println("使用的是XML");String mapperPath = attribute.getValue();Map<String, Mapper> mappers = loadMapperConfiguration(mapperPath);cfg.setMappers(mappers);} else {System.out.println("使用的是注解");String daoClassPath = mapperElement.attributeValue("class");Map<String, Mapper> mappers = loadMapperAnnotation(daoClassPath);cfg.setMappers(mappers);}}return cfg;} catch (Exception e) {e.printStackTrace();} finally {try {config.close();} catch (IOException e) {e.printStackTrace();}}return cfg;}private static Map<String, Mapper> loadMapperConfiguration(String mapperPath) throws IOException {InputStream in = null;Map<String, Mapper> mappers = new HashMap<String, Mapper>();try {in = Resources.getResourceAsStream(mapperPath);SAXReader reader = new SAXReader();Document document = reader.read(in);Element root = document.getRootElement();String namespace = root.attributeValue("namespace");List<Element> selectElements = root.selectNodes("//select");for (Element selectElement : selectElements) {String id = selectElement.attributeValue("id");String resultType = selectElement.attributeValue("resultType");String queryString = selectElement.getText();String key = namespace + "." + id;Mapper mapper = new Mapper();mapper.setQueryString(queryString);mapper.setResultType(resultType);mappers.put(key, mapper);}return mappers;} catch (Exception e) {e.printStackTrace();}return mappers;}private static Map<String, Mapper> loadMapperAnnotation(String daoClassPath) throws Exception {Map<String, Mapper> mappers = new HashMap<String, Mapper>();Class daoClass = Class.forName(daoClassPath);Method[] methods = daoClass.getMethods();for (Method method : methods) {boolean isAnnotated = method.isAnnotationPresent(Select.class);if (isAnnotated) {Mapper mapper = new Mapper();Select selectAnno = method.getAnnotation(Select.class);String queryString = selectAnno.value();mapper.setQueryString(queryString);Type type = method.getGenericReturnType();if (type instanceof ParameterizedType) {ParameterizedType ptype = (ParameterizedType) type;Type[] types = ptype.getActualTypeArguments();Class domainClass = (Class) types[0];String resultType = domainClass.getName();mapper.setResultType(resultType);}String methodName = method.getName();String className = method.getDeclaringClass().getName();String key = className + "." + methodName;mappers.put(key, mapper);}}return mappers;} }第三步:DefaultSqlSessionFactory工廠生產(chǎn)出DefaultSqlSession對象
import com.jinke.mybatis.cfg.Configuration; import com.jinke.mybatis.sqlsession.SqlSession; import com.jinke.mybatis.sqlsession.SqlSessionFactory;public class DefaultSqlSessionFactory implements SqlSessionFactory {private Configuration cfg;public DefaultSqlSessionFactory(Configuration cfg) {this.cfg = cfg;}public SqlSession openSession() {return new DefaultSqlSession(cfg);} }第四步:DefaultSqlSession執(zhí)行動態(tài)代理
import com.jinke.mybatis.cfg.Configuration; import com.jinke.mybatis.sqlsession.SqlSession; import com.jinke.mybatis.sqlsession.proxy.MapperProxy; import com.jinke.mybatis.utils.DataSourceUtil;import java.lang.reflect.Proxy; import java.sql.Connection; import java.sql.SQLException;public class DefaultSqlSession implements SqlSession {private Configuration cfg;private Connection connection;public DefaultSqlSession(Configuration cfg) {this.cfg = cfg;this.connection = DataSourceUtil.getConnection(cfg);}public <T> T getMapper(Class<T> daoInterfaceClass) {return (T) Proxy.newProxyInstance(daoInterfaceClass.getClassLoader(), new Class[]{daoInterfaceClass}, new MapperProxy(cfg.getMappers(), connection));}public void close() {if (connection != null) {try {connection.close();} catch (SQLException e) {e.printStackTrace();}}} }執(zhí)行sql語句
import com.jinke.mybatis.cfg.Mapper; import com.jinke.mybatis.utils.Executor;import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.sql.Connection; import java.util.Map;public class MapperProxy implements InvocationHandler {private Map<String, Mapper> mappers;private Connection connection;public MapperProxy(Map<String, Mapper> mappers, Connection connection) {this.mappers = mappers;this.connection = connection;}public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {String methodName = method.getName();String className = method.getDeclaringClass().getName();String key = className + "." + methodName;Mapper mapper = mappers.get(key);if (mapper == null) {throw new IllegalArgumentException("傳入的參數(shù)有誤");}return new Executor().selectList(mapper, connection);} } import com.jinke.mybatis.cfg.Mapper;import java.beans.PropertyDescriptor; import java.lang.reflect.Method; import java.sql.*; import java.util.ArrayList; import java.util.List;public class Executor {public <E> List<E> selectList(Mapper mapper, Connection conn) {PreparedStatement pstm = null;ResultSet rs = null;try {String queryString = mapper.getQueryString();String resultType = mapper.getResultType();Class domainClass = Class.forName(resultType);pstm = conn.prepareStatement(queryString);rs = pstm.executeQuery();List<E> list = new ArrayList<E>();while (rs.next()) {E obj = (E) domainClass.newInstance();ResultSetMetaData rsmd = rs.getMetaData();int columnCount = rsmd.getColumnCount();for (int i = 1; i < columnCount; i++) {String columnName = rsmd.getColumnName(i);Object columnValue = rs.getObject(columnName);PropertyDescriptor pd = new PropertyDescriptor(columnName, domainClass);Method writeMethod = pd.getWriteMethod();writeMethod.invoke(obj, columnValue);}list.add(obj);}return list;} catch (Exception e) {e.printStackTrace();} finally {release(pstm, rs);}return null;}private void release(PreparedStatement pstm, ResultSet rs) {if (rs != null) {try {rs.close();} catch (SQLException e) {e.printStackTrace();}}if (pstm != null) {try {pstm.close();} catch (SQLException e) {e.printStackTrace();}}} }最后放一張文件結(jié)構(gòu)圖
代碼地址?https://github.com/king1039/MyBatis
歡迎關(guān)注我的微信公眾號:安卓圈
轉(zhuǎn)載于:https://www.cnblogs.com/anni-qianqian/p/11103040.html
總結(jié)
以上是生活随笔為你收集整理的自定义MyBatis的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Grid布局和Flex布局
- 下一篇: AcWing 164. 可达性统计