日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > java >内容正文

java

Java软件开发:自定义MyBatis持久层框架

發布時間:2024/10/8 java 25 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Java软件开发:自定义MyBatis持久层框架 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

自定義MyBatis持久層框架

  • 1 框架概述
    • 1.1 什么是框架
    • 1.2 框架要解決的問題
    • 1.3 軟件開發的分層的重要性
  • 2 MyBatis框架
  • 3 JDBC編程
    • 3.1 JDBC程序的回顧
    • 3.2 JDBC存在的問題
  • 4 搭建MyBatis開發環境
    • 4.1 創建Maven工程
    • 4.2 編寫實體類
    • 4.3 編寫持久層接口
    • 4.4 編寫持久層接口的映射文件
    • 4.5 編寫 SqlMapConfig 配置文件
    • 4.6 編寫測試類
  • 5 三種常用設計模式
    • 5.1 工廠模式
    • 5.2 代理模式
    • 5.3 建造者模式
  • 6 自定義MyBatis框架
    • 6.1 創建Maven工程
    • 6.2 引入工具類
    • 6.3 編寫讀取配置文件類
    • 6.4 編寫Mapper類
    • 6.5 編寫 Configuration 配置類
    • 6.6 編寫構建者類
    • 6.7 編寫 SqlSessionFactory 接口和實現類
    • 6.8 編寫 SqlSession 接口和實現類
    • 6.9 編寫用于創建 Dao 接口代理對象的類

1 框架概述

1.1 什么是框架

框架(Framework)是整個或部分系統的可重用設計,表現為一組抽象構件及構件實例間交互的方法;另一種定義認為,框架是可被應用開發者定制的應用骨架。前者是從應用方面,而后者是從目的方面給出的定義。

簡而言之,框架其實就是某種應用的半成品,就是一組組件,供你選用完成你自己的系統。簡單說就是使用別人搭好的舞臺,你來做表演。而且,框架一般是成熟的,不斷升級的軟件。

1.2 框架要解決的問題

框架要解決的最重要的一個問題是技術整合的問題,在 J2EE 的框架中,有著各種各樣的技術,不同的軟件企業需要從 J2EE 中選擇不同的技術,這就使得軟件企業最終的應用依賴于這些技術,技術自身的復雜性和技術的風險性將會直接對應用造成沖擊。

而應用是軟件企業的核心,是競爭力的關鍵所在,因此應該將應用自身的設計和具體的實現技術解耦。這樣,軟件企業的研發將集中在應用的設計上,而不是具體的技術實現,技術實現是應用的底層支撐,它不應該直接對應用產生影響。

框架一般處在低層應用平臺(如 J2EE)和高層業務邏輯之間的中間層。

1.3 軟件開發的分層的重要性

框架的重要性在于它實現了部分功能,并且能夠很好的將低層應用平臺和高層業務邏輯進行了緩和。為了實現軟件工程中的“高內聚、低耦合”。把問題劃分開來各個解決,易于控制,易于延展,易于分配資源。我們常見的MVC 軟件設計思想就是很好的分層思想。


通過分層更好的實現了各個部分的職責,在每一層將再細化出不同的框架,分別解決各層關注的問題。

2 MyBatis框架

mybatis 是一個優秀的基于 java 的持久層框架,它內部封裝了 jdbc,使開發者只需要關注 sql 語句本身,而不需要花費精力去處理加載驅動、創建連接、創建 statement 等繁雜的過程。

mybatis 通過 xml 或注解的方式將要執行的各種 statement 配置起來,并通過 java 對象和 statement 中sql 的動態參數進行映射生成最終執行的 sql 語句,最后由 mybatis 框架執行 sql 并將結果映射為 java 對象并返回。

采用 ORM 思想解決了實體和數據庫映射的問題,對 jdbc 進行了封裝,屏蔽了 jdbc api 底層訪問細節,使我們不用與 jdbc api 打交道,就可以完成對數據庫的持久化操作。

3 JDBC編程

3.1 JDBC程序的回顧

import java.sql.*;public class Main {public static void main(String[] args) {Connection connection = null;PreparedStatement preparedStatement = null;ResultSet resultSet = null;String url = "jdbc:mysql://localhost:3306/mybatisdb?characterEncoding=utf-8";String driver = "com.mysql.jdbc.Driver";String username = "root";String password = "Root@2020";try {//加載數據庫驅動Class.forName(driver);//通過驅動管理類獲取數據庫連接connection = DriverManager.getConnection(url, username, password);//定義Sql語句,?標識占位符String sql = "select * from user where username = ?";//獲取預處理statementpreparedStatement = connection.prepareStatement(sql);//設置參數,第一個參數是sql語句中參數的序號(從1開始),第二個參數設置的是參數值preparedStatement.setString(1, "老王");//數據庫執行查詢,返回查詢結果集resultSet = preparedStatement.executeQuery();//遍歷查詢結果集while (resultSet.next()) {System.out.println(resultSet.getString("id") + "," + resultSet.getString("username"));}} catch (Exception e) {e.printStackTrace();} finally {if (resultSet != null) {try {resultSet.close();} catch (SQLException throwables) {throwables.printStackTrace();}}if (preparedStatement != null) {try {preparedStatement.close();} catch (SQLException throwables) {throwables.printStackTrace();}}if (connection != null) {try {connection.close();} catch (SQLException throwables) {throwables.printStackTrace();}}}} }

3.2 JDBC存在的問題

1、數據庫鏈接創建、釋放頻繁造成系統資源浪費從而影響系統性能,如果使用數據庫連接池可解決此問題。

2、Sql 語句在代碼中硬編碼,造成代碼不易維護,實際應用 sql 變化的可能較大,sql 變動需要改變 java代碼。

3、使用 preparedStatement 向占有位符號傳參數存在硬編碼,因為 sql 語句的 where 條件不一定,可能多也可能少,修改 sql 還要修改代碼,系統不易維護。

4、對結果集解析存在硬編碼(查詢列名),sql 變化導致解析代碼變化,系統不易維護,如果能將數據庫記錄封裝成 pojo 對象解析比較方便。

4 搭建MyBatis開發環境

4.1 創建Maven工程

<dependencies><dependency><groupId>org.mybatis</groupId><artifactId>mybatis</artifactId><version>3.4.5</version></dependency><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>5.1.6</version></dependency><dependency><groupId>log4j</groupId><artifactId>log4j</artifactId><version>1.2.12</version></dependency><dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>4.10</version><scope>test</scope></dependency></dependencies>

4.2 編寫實體類

public class User implements Serializable {private Integer id;private String username;private Date birthday;private String sex;private String address;@Overridepublic String toString() {return "User{" +"id=" + id +", username='" + username + '\'' +", birthday=" + birthday +", sex='" + sex + '\'' +", address='" + address + '\'' +'}';}public Integer getId() {return id;}public void setId(Integer id) {this.id = id;}public String getUsername() {return username;}public void setUsername(String username) {this.username = username;}public Date getBirthday() {return birthday;}public void setBirthday(Date birthday) {this.birthday = birthday;}public String getSex() {return sex;}public void setSex(String sex) {this.sex = sex;}public String getAddress() {return address;}public void setAddress(String address) {this.address = address;} }

4.3 編寫持久層接口

public interface IUserDao {/*** 查詢所有* @return*/List<User> findAll(); }

4.4 編寫持久層接口的映射文件

創建位置:必須和持久層接口在相同的包中。
名稱:必須以持久層接口名稱命名文件名,擴展名是.xml

<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="com.baidu.dao.IUserDao"> <!-- 配置查詢所有--><select id="findAll" resultType="com.company.domain.User">select * from user</select> </mapper>

4.5 編寫 SqlMapConfig 配置文件

<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE configurationPUBLIC "-//mybatis.org//DTD Config 3.0//EN""http://mybatis.org/dtd/mybatis-3-config.dtd"> <configuration><!--配置環境--><environments default="mysql"><!--配置mysql環境--><environment id="mysql"><!--配置事務類型--><transactionManager type="JDBC"></transactionManager><!--配置數據源(連接池)--><dataSource type="POOLED"><!--配置連接數據庫的四個基本信息--><property name="driver" value="com.mysql.jdbc.Driver"/><property name="url" value="jdbc:mysql://localhost:3306/mybatisdb"/><property name="username" value="root"/><property name="password" value="Root@2020"/></dataSource></environment></environments><!--指定映射配置文件的位置--><mappers><mapper resource="com/company/dao/IUserDao.xml"/></mappers> </configuration>

4.6 編寫測試類

public class MybatisTest {public static void main(String[] args) throws Exception {//1.讀取配置文件InputStream in = Resources.getResourceAsStream("SqlMapConfig.xml");//2.創建SqlSessionFactory工廠SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();SqlSessionFactory factory = builder.build(in);//3.使用工廠生產SqlSession對象SqlSession session = factory.openSession();//4.使用SqlSession創建DAO的代理對象IUserDao userDao = session.getMapper(IUserDao.class);//5.使用代理對象執行方法List<User> users = userDao.findAll();for (User user : users) {System.out.println(user);}//6.釋放資源session.close();in.close();} }

5 三種常用設計模式

5.1 工廠模式

工廠模式(Factory Pattern)是 Java 中最常用的設計模式之一。這種類型的設計模式屬于創建型模式,它提供了一種創建對象的最佳方式。

在工廠模式中,我們在創建對象時不會對客戶端暴露創建邏輯,并且是通過使用一個共同的接口來指向新創建的對象。

意圖:定義一個創建對象的接口,讓其子類自己決定實例化哪一個工廠類,工廠模式使其創建過程延遲到子類進行。

主要解決:主要解決接口選擇的問題。

何時使用:我們明確地計劃不同條件下創建不同實例時。

如何解決:讓其子類實現工廠接口,返回的也是一個抽象的產品。

關鍵代碼:創建過程在其子類執行。

5.2 代理模式

在代理模式(Proxy Pattern)中,一個類代表另一個類的功能。這種類型的設計模式屬于結構型模式。

在代理模式中,我們創建具有現有對象的對象,以便向外界提供功能接口。

意圖:為其他對象提供一種代理以控制對這個對象的訪問。

主要解決:在直接訪問對象時帶來的問題,比如說:要訪問的對象在遠程的機器上。在面向對象系統中,有些對象由于某些原因(比如對象創建開銷很大,或者某些操作需要安全控制,或者需要進程外的訪問),直接訪問會給使用者或者系統結構帶來很多麻煩,我們可以在訪問此對象時加上一個對此對象的訪問層。

何時使用:想在訪問一個類時做一些控制。

如何解決:增加中間層。

關鍵代碼:實現與被代理類組合。

5.3 建造者模式

建造者模式(Builder Pattern)使用多個簡單的對象一步一步構建成一個復雜的對象。這種類型的設計模式屬于創建型模式,它提供了一種創建對象的最佳方式。

一個 Builder 類會一步一步構造最終的對象。該 Builder 類是獨立于其他對象的。

意圖:將一個復雜的構建與其表示相分離,使得同樣的構建過程可以創建不同的表示。

主要解決:主要解決在軟件系統中,有時候面臨著"一個復雜對象"的創建工作,其通常由各個部分的子對象用一定的算法構成;由于需求的變化,這個復雜對象的各個部分經常面臨著劇烈的變化,但是將它們組合在一起的算法卻相對穩定。

何時使用:一些基本部件不會變,而其組合經常變化的時候。

如何解決:將變與不變分離開。

關鍵代碼:建造者:創建和提供實例,導演:管理建造出來的實例的依賴關系。

6 自定義MyBatis框架

6.1 創建Maven工程

<dependencies> <!-- <dependency>--> <!-- <groupId>org.mybatis</groupId>--> <!-- <artifactId>mybatis</artifactId>--> <!-- <version>3.4.5</version>--> <!-- </dependency>--><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>5.1.6</version></dependency><dependency><groupId>log4j</groupId><artifactId>log4j</artifactId><version>1.2.12</version></dependency><dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>4.10</version><scope>test</scope></dependency><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>

6.2 引入工具類

public class XMLConfigBuilder {/*** 解析主配置文件,把里面的內容填充到DefaultSqlSession所需要的地方* 使用的技術:* dom4j+xpath*/public static Configuration loadConfiguration(InputStream config) {try {//定義封裝連接信息的配置對象(mybatis的配置對象)Configuration cfg = new Configuration();//1.獲取SAXReader對象SAXReader reader = new SAXReader();//2.根據字節輸入流獲取Document對象Document document = reader.read(config);//3.獲取根節點Element root = document.getRootElement();//4.使用xpath中選擇指定節點的方式,獲取所有property節點List<Element> propertyElements = root.selectNodes("//property");//5.遍歷節點for (Element propertyElement : propertyElements) {//判斷節點是連接數據庫的哪部分信息//取出name屬性的值String name = propertyElement.attributeValue("name");if ("driver".equals(name)) {//表示驅動//獲取property標簽value屬性的值String driver = propertyElement.attributeValue("value");cfg.setDriver(driver);}if ("url".equals(name)) {//表示連接字符串//獲取property標簽value屬性的值String url = propertyElement.attributeValue("value");cfg.setUrl(url);}if ("username".equals(name)) {//表示用戶名//獲取property標簽value屬性的值String username = propertyElement.attributeValue("value");cfg.setUsername(username);}if ("password".equals(name)) {//表示密碼//獲取property標簽value屬性的值String password = propertyElement.attributeValue("value");cfg.setPassword(password);}}//取出mappers中的所有mapper標簽,判斷他們使用了resource還是class屬性List<Element> mapperElements = root.selectNodes("//mappers/mapper");//遍歷集合for (Element mapperElement : mapperElements) {//判斷mapperElement使用的是哪個屬性Attribute attribute = mapperElement.attribute("resource");if (attribute != null) {System.out.println("使用的是XML");//表示有resource屬性,用的是XML//取出屬性的值String mapperPath = attribute.getValue();//獲取屬性的值"com/itheima/dao/IUserDao.xml"//把映射配置文件的內容獲取出來,封裝成一個mapMap<String, Mapper> mappers = loadMapperConfiguration(mapperPath);//給configuration中的mappers賦值cfg.setMappers(mappers);} else {System.out.println("使用的是注解");//表示沒有resource屬性,用的是注解//獲取class屬性的值String daoClassPath = mapperElement.attributeValue("class");//根據daoClassPath獲取封裝的必要信息Map<String, Mapper> mappers = loadMapperAnnotation(daoClassPath);//給configuration中的mappers賦值cfg.setMappers(mappers);}}//返回Configurationreturn cfg;} catch (Exception e) {throw new RuntimeException(e);} finally {try {config.close();} catch (Exception e) {e.printStackTrace();}}}/*** 根據傳入的參數,解析XML,并且封裝到Map中** @param mapperPath 映射配置文件的位置* @return map中包含了獲取的唯一標識(key是由dao的全限定類名和方法名組成)* 以及執行所需的必要信息(value是一個Mapper對象,里面存放的是執行的SQL語句和要封裝的實體類全限定類名)*/private static Map<String, Mapper> loadMapperConfiguration(String mapperPath) throws IOException {InputStream in = null;try {//定義返回值對象Map<String, Mapper> mappers = new HashMap<String, Mapper>();//1.根據路徑獲取字節輸入流in = Resources.getResourceAsStream(mapperPath);//2.根據字節輸入流獲取Document對象SAXReader reader = new SAXReader();Document document = reader.read(in);//3.獲取根節點Element root = document.getRootElement();//4.獲取根節點的namespace屬性取值String namespace = root.attributeValue("namespace");//是組成map中key的部分//5.獲取所有的select節點List<Element> selectElements = root.selectNodes("//select");//6.遍歷select節點集合for (Element selectElement : selectElements) {//取出id屬性的值 組成map中key的部分String id = selectElement.attributeValue("id");//取出resultType屬性的值 組成map中value的部分String resultType = selectElement.attributeValue("resultType");//取出文本內容 組成map中value的部分String queryString = selectElement.getText();//創建KeyString key = namespace + "." + id;//創建ValueMapper mapper = new Mapper();mapper.setQueryString(queryString);mapper.setResultType(resultType);//把key和value存入mappers中mappers.put(key, mapper);}return mappers;} catch (Exception e) {throw new RuntimeException(e);} finally {in.close();}}/*** 根據傳入的參數,得到dao中所有被select注解標注的方法。* 根據方法名稱和類名,以及方法上注解value屬性的值,組成Mapper的必要信息** @param daoClassPath* @return*/private static Map<String, Mapper> loadMapperAnnotation(String daoClassPath) throws Exception {//定義返回值對象Map<String, Mapper> mappers = new HashMap<String, Mapper>();//1.得到dao接口的字節碼對象Class daoClass = Class.forName(daoClassPath);//2.得到dao接口中的方法數組Method[] methods = daoClass.getMethods();//3.遍歷Method數組for (Method method : methods) {//取出每一個方法,判斷是否有select注解boolean isAnnotated = method.isAnnotationPresent(Select.class);if (isAnnotated) {//創建Mapper對象Mapper mapper = new Mapper();//取出注解的value屬性值Select selectAnno = method.getAnnotation(Select.class);String queryString = selectAnno.value();mapper.setQueryString(queryString);//獲取當前方法的返回值,還要求必須帶有泛型信息Type type = method.getGenericReturnType();//List<User>//判斷type是不是參數化的類型if (type instanceof ParameterizedType) {//強轉ParameterizedType ptype = (ParameterizedType) type;//得到參數化類型中的實際類型參數Type[] types = ptype.getActualTypeArguments();//取出第一個Class domainClass = (Class) types[0];//獲取domainClass的類名String resultType = domainClass.getName();//給Mapper賦值mapper.setResultType(resultType);}//組裝key的信息//獲取方法的名稱String methodName = method.getName();String className = method.getDeclaringClass().getName();String key = className + "." + methodName;//給map賦值mappers.put(key, mapper);}}return mappers;} } public class Executor {public <E> List<E> selectList(Mapper mapper, Connection conn) {PreparedStatement pstm = null;ResultSet rs = null;try {//1.取出mapper中的數據String queryString = mapper.getQueryString();//select * from userString resultType = mapper.getResultType();//com.itheima.domain.UserClass domainClass = Class.forName(resultType);//2.獲取PreparedStatement對象pstm = conn.prepareStatement(queryString);//3.執行SQL語句,獲取結果集rs = pstm.executeQuery();//4.封裝結果集List<E> list = new ArrayList<E>();//定義返回值while(rs.next()) {//實例化要封裝的實體類對象E obj = (E)domainClass.newInstance();//取出結果集的元信息:ResultSetMetaDataResultSetMetaData rsmd = rs.getMetaData();//取出總列數int columnCount = rsmd.getColumnCount();//遍歷總列數for (int i = 1; i <= columnCount; i++) {//獲取每列的名稱,列名的序號是從1開始的String columnName = rsmd.getColumnName(i);//根據得到列名,獲取每列的值Object columnValue = rs.getObject(columnName);//給obj賦值:使用Java內省機制(借助PropertyDescriptor實現屬性的封裝)PropertyDescriptor pd = new PropertyDescriptor(columnName,domainClass);//要求:實體類的屬性和數據庫表的列名保持一種//獲取它的寫入方法Method writeMethod = pd.getWriteMethod();//把獲取的列的值,給對象賦值writeMethod.invoke(obj,columnValue);}//把賦好值的對象加入到集合中list.add(obj);}return list;} catch (Exception e) {throw new RuntimeException(e);} finally {release(pstm,rs);}}private void release(PreparedStatement pstm,ResultSet rs){if(rs != null){try {rs.close();}catch(Exception e){e.printStackTrace();}}if(pstm != null){try {pstm.close();}catch(Exception e){e.printStackTrace();}}} } public class DataSourceUtil {public static Connection getConnection(Configuration cfg) {try {Class.forName(cfg.getDriver());return DriverManager.getConnection(cfg.getUrl(), cfg.getUsername(), cfg.getPassword());} catch (Exception e) {throw new RuntimeException(e);}} }

6.3 編寫讀取配置文件類

/*** 使用類加載器讀取配置文件*/ public class Resources {/*** 根據傳入的參數,獲取一個字節輸入流** @param filepath* @return*/public static InputStream getResourceAsStream(String filepath) {return Resources.class.getClassLoader().getResourceAsStream(filepath);} }

6.4 編寫Mapper類

/*** 用于封裝執行的SQL語句和結果類型的全限定類名*/ public class Mapper {private String queryString;//SQLprivate String resultType;//實體類的全限定類名public String getQueryString() {return queryString;}public void setQueryString(String queryString) {this.queryString = queryString;}public String getResultType() {return resultType;}public void setResultType(String resultType) {this.resultType = resultType;} }

6.5 編寫 Configuration 配置類

public class Configuration {private String driver;//驅動private String url;//地址private String username;//用戶名private String password;//密碼//Map<唯一標識,Mapper>用于保存映射文件中的sql標識及sql語句private Map<String, Mapper> mappers;public Map<String, Mapper> getMappers() {return mappers;}public void setMappers(Map<String, Mapper> mappers) {//此處需要使用追加的方式this.mappers = mappers;}public String getDriver() {return driver;}public void setDriver(String driver) {this.driver = driver;}public String getUrl() {return url;}public void setUrl(String url) {this.url = url;}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;} }

6.6 編寫構建者類

/*** 用于創建一個SqlSessionFactory對象*/ public class SqlSessionFactoryBuilder {public SqlSessionFactory build(InputStream in) {DefaultSqlSessionFactory factory = new DefaultSqlSessionFactory();factory.setConfig(in);return factory;} }

6.7 編寫 SqlSessionFactory 接口和實現類

public interface SqlSessionFactory {SqlSession openSession(); } /*** SqlSessionFactory接口的實現類*/ public class DefaultSqlSessionFactory implements SqlSessionFactory {private InputStream config = null;public void setConfig(InputStream config) {this.config = config;}/*** 用于創建一個新的操作數據庫對象** @return*/@Overridepublic SqlSession openSession() {Configuration cfg = XMLConfigBuilder.loadConfiguration(config);return new DefaultSqlSession(cfg);} }

6.8 編寫 SqlSession 接口和實現類

/*** 自定義Mybatis中和數據庫交互的核心類* 里面可以創建dao接口的代理對象*/ public interface SqlSession {/*** 根據參數創建一個代理對象* @param daoInterfaceClass dao的接口字節碼* @param <T>* @return*/<T> T getMapper(Class<T> daoInterfaceClass);/*** 釋放資源*/void close(); } /*** SqlSession實現類*/ public class DefaultSqlSession implements SqlSession {private Configuration cfg;private Connection conn;public DefaultSqlSession(Configuration cfg) {this.cfg = cfg;this.conn = DataSourceUtil.getConnection(cfg);}/*** 用于創建代理對象** @param daoInterfaceClass dao的接口字節碼* @param <T>* @return*/@Overridepublic <T> T getMapper(Class<T> daoInterfaceClass) {return (T) Proxy.newProxyInstance(daoInterfaceClass.getClassLoader(),new Class[]{daoInterfaceClass},new MapperProxy(cfg.getMappers(), conn));}/*** 用于釋放資源*/@Overridepublic void close() {if (conn != null) {try {conn.close();} catch (SQLException throwables) {throwables.printStackTrace();}}}//查詢所有的方法public <E> List<E> selectList(String statement) {Mapper mapper = cfg.getMappers().get(statement);return new Executor().selectList(mapper, conn);} }

6.9 編寫用于創建 Dao 接口代理對象的類

public class MapperProxy implements InvocationHandler {//Map的key是全限定類名+方法名private Map<String, Mapper> mappers;private Connection conn;public MapperProxy(Map<String, Mapper> mappers, Connection conn) {this.mappers = mappers;this.conn = conn;}/*** 用于對方法進行增強,就是調用SelectList方法** @param proxy* @param method* @param args* @return* @throws Throwable*/@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {//1.獲取方法名String methodName = method.getName();//2.獲取方法所在類的名稱String className = method.getDeclaringClass().getName();//3.組合keyString key = className + "." + methodName;//4.獲取Mappers中的mapper對象Mapper mapper = mappers.get(key);//5.判斷是否有mapperif (mapper == null) {throw new IllegalArgumentException("傳入的參數有誤");}Executor executor = new Executor();//6.調用工具類查詢所有return executor.selectList(mapper,conn);} }

總結

以上是生活随笔為你收集整理的Java软件开发:自定义MyBatis持久层框架的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。