Spring Boot 整合 MyBatis(四)
阿新 • • 發佈:2018-11-09
Spring Boot 整合 MyBatis
A、ORM框架是什麼? 物件關係對映(Object Relational Mapping,簡稱 ORM)模式是一種為了解決面向物件與關係資料庫存在的 互不匹配的現象技術。簡單的說,ORM 是通過使用描述物件和資料庫之間對映的元資料,將程式中的物件自 動持久化到關係資料庫中。 B、為什麼需要ORM框架 當開發一個應用程式的時候(不使用 O/R Mapping),可能會寫不少資料訪問層的程式碼,用來從資料庫儲存、 刪除、讀取物件資訊等。在 DAL 中寫了很多的方法來讀取物件資料、改變狀態物件等任務,而這些程式碼寫 起來總是重複的。針對這些問題 ORM 提供瞭解決方案,簡化了將程式中的物件持久化到關係資料庫中的操作。 ORM 框架的本質是簡化程式設計中操作資料庫的編碼,一個是宣稱可以不用寫一句 SQL 的 Hibernate, 一個是以動態 SQL 見長的 MyBatis,兩者各有特點。在企業級系統開發中可以根據需求靈活使用, 有趣的現象:傳統企業大都喜歡使用 Hibernate,而網際網路行業通常使用MyBatis。 C、MyBatis 介紹 MyBatis 支援普通 SQL 查詢,儲存過程和高階對映的優秀持久層框架。MyBatis 消除了幾乎所有的 JDBC 代 碼和引數的手工設定以及對結果集的檢索封裝。MaBatis 可以使用簡單的 XML 或註解用於配置和原始對映。 將介面和 Java 的 POJO(Plain Old Java Objects,普通的 Java 物件)對映成資料庫中的記錄。 優點: SQL 被統一提取出來,便於統一管理和優化 SQL 和程式碼解耦,將業務邏輯和資料訪問邏輯分離,使系統的設計更清晰,更易維護,更易單元測試 提供對映標籤,支援物件與資料庫的 ORM 欄位關係對映 提供物件關係對映標籤,支援物件關係元件維護 靈活書寫動態 SQL,支援各種條件來動態生成不同的 SQL 缺點: 編寫 SQL 語句時工作量很大,尤其是欄位多、關聯表多時,更是如此 SQL 語句依賴於資料庫,導致資料庫移植性差 E、MyBatis 重要的概念 Mapper 配置: Mapper 配置可以使用基於 XML 的 Mapper 配置⽂檔案來實現,也可以使用基於 Java 註解的 MyBatis 註解來實現,甚至可以直接使用 MyBatis 提供的 API 來實現。 Mapper 介面: Mapper 介面是指自行定義的一個數據操做介面,類似於通常所說的 DAO 接⼝口。早期的Mapper 介面需要自定義去實現,現在 MyBatis 會自動為 Mapper 介面建立動態代理物件。Mapper 接 口的方法通常與 Mapper 配置⽂檔案中的 select、insert、update、delete 等 XML 結點存在 一一對應關係。 Executor: MyBatis 中所有的 Mapper 語句的執行都是通過 Executor 進行的,Executor 是 MyBatis 的一個 核⼼心介面。 SqlSession: SqlSession 是 MyBatis 的關鍵物件,是執行持久化操作的獨享,類似於 JDBC 中的Connection, SqlSession 物件完全包含以資料庫為背景的所有執行 SQL 操作的方法,它的底層封裝了JDBC連 接,可以用 SqlSession 例項來直接執行被對映的 SQL 語句。 SqlSessionFactory: SqlSessionFactory 是 MyBatis 的關鍵物件,它是單個數據庫對映關係經過編譯後的內 存映象。SqlSessionFactory 物件的例項可以通過 SqlSessionFactoryBuilder 物件類獲 得,而SqlSessionFactoryBuilder 則可以從 XML 配置檔案或一個預先定製的 Configuration 的例項構建出。 F、MyBatis 的工作流程如下: a、首先載入 Mapper 配置的 SQL 對映檔案,或者是註解的相關 SQL 內容。 b、建立會話工廠,MyBatis 通過讀取配置檔案的資訊來構造出會話工廠(SqlSessionFactory)。 c、建立會話。根據會話工廠,MyBatis 就可以通過它來建立會話物件(SqlSession)。會話物件是一個接 口,該介面中包含了對資料庫操作的增刪改查⽅方法。 d、建立執行器。因為會話物件本身不能直接操作資料庫,所以它使用了一個叫做資料庫執行器(Executor) 的介面來幫它執行操作。 e、封裝 SQL 物件。在這一步,執行器將待處理的 SQL 資訊封裝到一個物件中(MappedStatement),該對 象包括 SQL 語句、輸⼊入引數對映資訊(Java 簡單型別、HashMap 或 POJO)和輸出結果對映資訊(Java 簡單型別、HashMap 或 POJO)。 f、操作資料庫。擁有了執行器和 SQL 資訊封裝物件就使用它們訪問資料庫了,最後再返回操作結果,結束流程。 在具體的使用過程中,按照上述的流程來執行。
1、mybatis-spring-boot-starter 主要提供了兩種解決方式,①XML配置,②使用註解。
A、XML版本
XML 版本保持對映檔案的老傳統,優化主要體現在不需要實現 Dao 的實現層,系統會自動根據方法名在對映檔案中找到對應的 SQL。 POM.XML檔案 <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.mybatis.spring.boot</groupId> <artifactId>mybatis-spring-boot-starter</artifactId> <version>RELEASE</version> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> </dependency> <dependency> <groupId>org.apache.commons</groupId> <artifactId>commons-lang3</artifactId> <version>3.4</version> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-devtools</artifactId> <optional>true</optional> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> <configuration> <fork>true</fork> </configuration> </plugin> </plugins> </build> 我還會引入另外一個元件,Apache 的 commons-lang 3 ,此包有非常多的工具類可以使用, 比如常用的判斷字串是否為空,快速複寫實體類的 toString() 方法等。 實體類檔案:UserEntity public class UserEntity implements Serializable { private static final long serialVersionUID = 1L; private Long id; private String userName; private String passWord; private UserSexEnum userSex; private String nickName; //getter/setter省略 } 列舉類: public enum UserSexEnum { MAN, WOMAN } application.properties檔案 mybatis.config-location=classpath:mybatis/mybatis-config.xml mybatis.mapper-locations=classpath:mybatis/mapper/*.xml mybatis.type-aliases-package=com.kid.entity spring.datasource.driverClassName = com.mysql.jdbc.Driver spring.datasource.url = jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=utf-8 spring.datasource.username = root spring.datasource.password = root # mybatis.config-locations :配置 mybatis-config.xml 路徑,mybatis-config.xml 中配置MyBatis 基礎屬性。 # mybatis.mapper-locations :配置 Mapper 對應的 XML 檔案路徑 # mybatis.type-aliases-package :配置專案中實體類包路徑 # spring.datasource.* :資料來源配置 # Spring Boot 啟動時資料來源會自動注入到 SqlSessionFactory 中,使用 SqlSessionFactory 構建 # SqlSessionFactory,再自動注入到 Mapper 中,最後我們直接使用 Mapper 即可 啟動類:在啟動類中新增對 Mapper 包掃描 @MapperScan ,Spring Boot 啟動的時候會自動載入包路徑下的Mapper。 @SpringBootApplication @MapperScan("com.kid.mapper") public class SpringbootMybatisApplication { public static void main(String[] args) { SpringApplication.run(SpringbootMybatisApplication.class, args); } } 開發SQL: MyBatis公共屬性 <!--配置別名--> <typeAliases> <typeAlias alias="Integer" type="java.lang.Integer" /> <typeAlias alias="Long" type="java.lang.Long" /> <typeAlias alias="HashMap" type="java.util.HashMap" /> <typeAlias alias="LinkedHashMap" type="java.util.LinkedHashMap" /> <typeAlias alias="ArrayList" type="java.util.ArrayList" /> <typeAlias alias="LinkedList" type="java.util.LinkedList" /> </typeAliases> mybatis-config.xml ,主要配置常用的 typeAliases,設定類型別名為 Java 型別設定一個短的名字。只和 XML 配置有關,存在的意義僅在於用來減少類完全限定名的冗餘。 UserMapper介面 public interface UserMapper { List<UserEntity> getAll(); UserEntity getOne(Long id); void insert(UserEntity user); void update(UserEntity user); int delete(Long id); List<UserEntity> getList(UserParam userParam); Long getCount(UserParam userParam); } 注意:這裡的方法名需要和 XML 配置中的 id 屬性一致,不然會找不到方法去對應執行的 SQL。 新增UserMapper對映檔案 <!--指明對應檔案的 Mapper 類地址--> <mapper namespace="com.kid.mapper.UserMapper" > <!-- 配置表結構和類的對應關係: 這裡故意將類的兩個欄位和資料庫欄位設定為不一致,並且有一個使用列舉。 使⽤用列舉有一個非常⼤大的優點,插⼊入此屬性的資料會自動進⾏行校驗, 如果不是列舉的內容會報錯。 --> <resultMap id="BaseResultMap" type="com.kid.entity.UserEntity" > <id column="id" property="id" jdbcType="BIGINT" /> <result column="userName" property="userName" jdbcType="VARCHAR" /> <result column="passWord" property="passWord" jdbcType="VARCHAR" /> <result column="user_sex" property="userSex" javaType="com.kid.enums.UserSexEnum"/> <result column="nick_name" property="nickName" jdbcType="VARCHAR" /> </resultMap> <sql id="Base_Column_List" > id, userName, passWord, user_sex, nick_name </sql> <sql id="Base_Where_List"> <if test="userName != null and userName != ''"> and userName = #{userName} </if> <if test="userSex != null and userSex != ''"> and user_sex = #{userSex} </if> </sql> <select id="getAll" resultMap="BaseResultMap" > SELECT <include refid="Base_Column_List" /> FROM users </select> <select id="getList" resultMap="BaseResultMap" parameterType="com.kid.param.UserParam"> select <include refid="Base_Column_List" /> from users where 1=1 <include refid="Base_Where_List" /> order by id desc limit #{beginLine} , #{pageSize} </select> <select id="getCount" resultType="Integer" parameterType="com.kid.param.UserParam"> select count(1) from users where 1=1 <include refid="Base_Where_List" /> </select> <select id="getOne" parameterType="Long" resultMap="BaseResultMap" > SELECT <include refid="Base_Column_List" /> FROM users WHERE id = #{id} </select> <insert id="insert" parameterType="com.kid.entity.UserEntity" > INSERT INTO users (userName,passWord,user_sex) VALUES (#{userName}, #{passWord}, #{userSex}) </insert> <update id="update" parameterType="com.kid.entity.UserEntity" > UPDATE users SET <if test="userName != null">userName = #{userName},</if> <if test="passWord != null">passWord = #{passWord},</if> nick_name = #{nickName} WHERE id = #{id} </update> <delete id="delete" parameterType="Long" > DELETE FROM users WHERE id =#{id} </delete> </mapper>