自定义Mybatis框架
生活随笔
收集整理的這篇文章主要介紹了
自定义Mybatis框架
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
一、開發環境的準備及統一
1、 Jdk環境:JDK 1.8 64bit
2、 Maven環境:MAVEN 3.3.9
二、創建Maven工程并引入坐標
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><groupId>com.william</groupId><artifactId>DIYMybatisFramework</artifactId><version>1.0-SNAPSHOT</version><properties><maven.compiler.source>1.8</maven.compiler.source><maven.compiler.target>1.8</maven.compiler.target></properties><dependencies><!--解析xml--><dependency><groupId>dom4j</groupId><artifactId>dom4j</artifactId><version>1.6.1</version></dependency><dependency><groupId>jaxen</groupId><artifactId>jaxen</artifactId><version>1.1.6</version></dependency></dependencies> </project>三、 自定義Mybatis框架配置文件結構約定
1.Sql文件約定
<?xml version="1.0" encoding="utf-8" ?> <mapper namespace="com.william.dao.UserDao"><select id="findAll" resultType="com.william.domain.User">select * from user</select> </mapper>2.框架核心配置文件約定
<?xml version="1.0" encoding="UTF-8" ?> <configuration><environments default="development"><environment id="development"><transactionManager type="JDBC" /><dataSource type="POOLED"><property name="driver" value="com.mysql.jdbc.Driver" /><property name="url" value="jdbc:mysql://127.0.0.1:3306/web02?characterEncoding=utf8" /><property name="username" value="root" /><property name="password" value="root" /></dataSource></environment></environments><mappers><mapper resource="com/william/mapper/UserMapper.xml"></mapper></mappers> </configuration>四、核心組件開發
1.Mapper開發
根據Jdbc存在問題的分析,我們已經知道了要將SQL語句放入配置文件中,這樣將來修改SQL語句會比較方便,但放在配置文件中的SQL語句還需要讀取出來,這樣我們就可以基于面向對象思維定義一個Mapper類,用于將配置文件中的SQL語句保存起來,使用時更方便。定義如下:
package Framework.domain; /*** @author :lijunxuan* @date :Created in 2019/7/9 12:14* @description :* @version: 1.0*/ public class Mapper {private String resultType;private String sql;public String getResultType() {return resultType;}public void setResultType(String resultType) {this.resultType = resultType;}public String getSql() {return sql;}public void setSql(String sql) {this.sql = sql;} }2.Configuration開發
我們以面向對象思維操作自定義框架的核心配置文件時,需要有一個實體類與之對應。Configuration 配置類主要用于保存SqlMapConfig.xml文件中讀取的xml結點的信息,以及映射的SQL語句的集合。定義如下:
package Framework.domain;import java.util.HashMap; import java.util.Map;/*** @author :lijunxuan* @date :Created in 2019/7/9 12:16* @description :* @version: 1.0*/ public class Configuration {private String driverClass;private String username;private String password;private String url;private Map<String,Mapper> xmlMap =new HashMap<>();@Overridepublic String toString() {return "Configuration{" +"driverClass='" + driverClass + '\'' +", username='" + username + '\'' +", password='" + password + '\'' +", url='" + url + '\'' +", xmlMap=" + xmlMap +'}';}public String getDriverClass() {return driverClass;}public void setDriverClass(String driverClass) {this.driverClass = driverClass;}public String getUsername() {return username;}public void setUsername(String username) {this.username = username;}public String getPassword() {return password;}public void setPassword(String password) {this.password = password;}public String getUrl() {return url;}public void setUrl(String url) {this.url = url;}public Map<String, Mapper> getXmlMap() {return xmlMap;}public void setXmlMap(Map<String, Mapper> xmlMap) {this.xmlMap = xmlMap;} }3.SqlSession接口開發
package Framework.dao;import java.util.List;public interface SqlSession {/**** @param mapperId 唯一的標識* @return*/public List selectList(String mapperId);/*** 釋放資源*/public void close(); }4.SqlSessionImpl實現類開發
package Framework.dao.Impl;import Framework.dao.SqlSession; import Framework.domain.Configuration; import Framework.domain.Mapper; import Framework.utils.Executer;import java.util.List;/*** @author :lijunxuan* @date :Created in 2019/7/9 12:27* @description :* @version: 1.0*/ public class SqlSessionImpl implements SqlSession {private Configuration cfg;private Executer ex;public SqlSessionImpl(Configuration cfg) {this.cfg = cfg;ex=new Executer(cfg);}@Overridepublic List selectList(String mapperId) {//獲取sql語句,結果類型Mapper mapper = cfg.getXmlMap().get(mapperId);String sql = mapper.getSql();String resultType = mapper.getResultType();//執行查詢操作return ex.executeQuery(sql,resultType);}@Overridepublic void close() {ex.close();} }5.Executor執行器開發
Executor類,用于實現SQL語句的執行,主要是調用JDBC來實現SQL語句的執行。
package Framework.utils; import Framework.domain.Configuration; import java.lang.reflect.Method; import java.sql.*; import java.util.ArrayList; import java.util.List; /*** sql操作的執行器(工具類)* @author :lijunxuan* @date :Created in 2019/7/9 12:33* @description :* @version: 1.0*/ public class Executer {private Configuration cfg;public Executer(Configuration cfg) {this.cfg = cfg;}private Connection connection;private PreparedStatement preparedStatement;private ResultSet resultSet;/*** 執行sql查詢操作,返回集合* @param sql* @param resultType* @return*/public List executeQuery(String sql, String resultType) {List list=new ArrayList();//1.注冊驅動try {Class.forName(cfg.getDriverClass());} catch (ClassNotFoundException e) {e.printStackTrace();}//2.獲取連接try {connection = DriverManager.getConnection(cfg.getUrl(), cfg.getUsername(), cfg.getPassword());//獲取preparedStatement對象preparedStatement = connection.prepareStatement(sql);//3.執行sql語句resultSet = preparedStatement.executeQuery();//獲取數據庫的元數據:修飾代碼的代碼(修飾數據的數據)ResultSetMetaData metaData = resultSet.getMetaData();//獲取列的個數int columnCount = metaData.getColumnCount();//創建一個列名的集合List<String> columnNames=new ArrayList<>();//獲取所有的列名//列的索引從1開始for (int i = 1; i <=columnCount; i++) {String columnName = metaData.getColumnName(i);columnNames.add(columnName);}//獲取實體類對象的字節碼文件Class clazz = Class.forName(resultType);//根據字節碼反射獲取實體類中的所有方法Method[] methods = clazz.getMethods();//setUsername set + username//封裝結果集(不體現具體的屬性和字段名)while (resultSet.next()){//如果resultSet.next()為true,就應該new一個對象//通過反射來獲取對象Object o = clazz.newInstance();for (String columnName : columnNames) {for (Method method : methods) {//比較 set +列名 與方法名if (("set"+columnName).equalsIgnoreCase(method.getName())){//如果相同,就找到列對應的set方法//獲取列對應的數據Object columnValue = resultSet.getObject(columnName);//反射調用set方法給屬性賦值//參數1:需要賦值的對象//參數2: 方法的參數method.invoke(o,columnValue);}}}list.add(o);}//4.處理結果集} catch (Exception e) {e.printStackTrace();}return list;}/*** 釋放資源*/public void close(){if (connection!=null){try {connection.close();} catch (SQLException e) {e.printStackTrace();}}if (preparedStatement!=null){try {preparedStatement.close();} catch (SQLException e) {e.printStackTrace();}}if (resultSet!=null){try {resultSet.close();} catch (SQLException e) {e.printStackTrace();}}} }6.SqlSessionFactory開發
SqlSessionFactory的開發基于工廠模式,工廠模式是我們最常用的用來實例化對象的設計模式,是用工廠方法代替new操作的一種模式。創建對象的時候使用工廠模式會帶來更大的可擴展性和盡量少的修改量。
package Framework.factory;import Framework.dao.Impl.SqlSessionImpl; import Framework.dao.SqlSession; import Framework.domain.Configuration;/*** 使用工廠模式創建sqlSession對象* @author :lijunxuan* @date :Created in 2019/7/9 15:38* @description :* @version: 1.0*/ public class SqlSessionFactory {private Configuration cgf;public SqlSessionFactory(Configuration cgf) {this.cgf = cgf;}public SqlSession openSession(){return new SqlSessionImpl(cgf);} }7.SqlSessionFactoryBuilder開發
package Framework.factory;import Framework.domain.Configuration; import Framework.domain.Mapper; import org.dom4j.Document; import org.dom4j.DocumentException; import org.dom4j.Element; import org.dom4j.io.SAXReader;import java.io.InputStream; import java.util.List;/*** 使用構建者模式創建SqlSessionFactory對象* 解析xml文件,數據存入Configuration對象中* @author :lijunxuan* @date :Created in 2019/7/9 15:41* @description :* @version: 1.0*/ public class SqlSessionFactoryBuilder {private InputStream inputStream;public SqlSessionFactory build(InputStream inputStream){this.inputStream=inputStream;Configuration cfg=new Configuration();loadCongiguration(cfg);return new SqlSessionFactory(cfg);}/*** 解析xml文件,把xml中的數據讀入到實體類中*/private void loadCongiguration(Configuration cfg) {//創建SAXReader對象SAXReader saxReader = new SAXReader();//讀取流對象,獲取文檔對象Document doc =null;try {doc = saxReader.read(inputStream);} catch (DocumentException e) {e.printStackTrace();}//解析文檔對象,獲取根節點Element rootElement = doc.getRootElement();//獲取文檔中的所有的propertyList<Element> propertyList = rootElement.selectNodes("//property");//遍歷集合對象for (Element propertyElement : propertyList) {//獲取節點的name屬性值和value屬性值String nameValue = propertyElement.attributeValue("name");String valueValue = propertyElement.attributeValue("value");if ("driver".equals(nameValue)){cfg.setDriverClass(valueValue);}if ("url".equals(nameValue)){cfg.setUrl(valueValue);}if ("username".equals(nameValue)){cfg.setUsername(valueValue);}if ("password".equals(nameValue)){cfg.setPassword(valueValue);}}//開始解析mappers標簽//獲取根節點Element root1 =doc.getRootElement();//獲取mappers節點Element mappers = root1.element("mappers");//獲取所有mapper節點List<Element> mapperList = mappers.elements("mapper");//循環集合for (Element element : mapperList) {String path = element.attributeValue("resource");loadXmlConfiguration(path,cfg);}}/*** 解析xml映射文件* @param path* @param cfg*/private void loadXmlConfiguration(String path, Configuration cfg) {SAXReader saxReader = new SAXReader();//根據路徑獲取流對象InputStream inputStream = SqlSessionFactoryBuilder.class.getClassLoader().getResourceAsStream(path);Document document = null;try {document = saxReader.read(inputStream);} catch (DocumentException e) {e.printStackTrace();}//獲取根節點Element rootElement = document.getRootElement();//獲取namespace的屬性值String namespace = rootElement.attributeValue("namespace");/*** element(name) 獲取第一個名稱為name的子節點* elements(name): 獲取所有名稱為name的子節點* elements(): 獲取的是所有的子節點*///獲取根節點下的所有子節點List<Element> elements = rootElement.elements();for (Element element : elements) {String idValue = element.attributeValue("id");String resultTypeValue = element.attributeValue("resultType");String sql=element.getTextTrim();/*** key:唯一的標識*/String key=namespace+"."+idValue;Mapper mapper = new Mapper();mapper.setSql(sql);mapper.setResultType(resultTypeValue);cfg.getXmlMap().put(key,mapper);}} }8.自定義Mybatis框架架構圖
五、安裝到Maven倉庫
1.使用Idea自帶的打包和安裝功能將當前工程打成Jar包安裝到本地Maven倉庫(雙擊install圖標即可):
2.查看本地Maven倉庫
總結
以上是生活随笔為你收集整理的自定义Mybatis框架的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 运行SpringBoot时:Type j
- 下一篇: 基因强大什么意思