MyBatis
是一個基於 Java
的持久層框架,它內部封裝了 JDBC
,使開發者只需關注 SQL
語句自己,而不用再花費精力去處理諸如註冊驅動、建立 Connection
、配置 Statement
等繁雜過程。java
Mybatis
經過 xml
或註解的方式將要執行的各類 Statement
、PreparedStatement
等配置起來,並經過 Java
對象和 Statement
中 SQL
的動態參數進行映射生成最終執行的 SQL
語句,最後由 MyBatis
框架執行 SQL
並將結果映射成 Java
對象並返回。程序員
Hibernate 框架是提供了全面的數據庫封裝機制的 全自動 ORM,即實現了 POJO 和數據庫表之間的映射,以及 SQL 的自動生成和執行。spring
相對於此,MyBatis 只能算做是 半自動 ORM。其着力點,是在 POJO 類與 SQL 語句之間的映射關係。也就是說,MyBatis 並不會爲程序員自動生成 SQL 語句。具體的 SQL 須要程序員本身編寫,而後經過 SQL 語句映射文件,將 SQL 所需的參數,以及返回的結果字段映射到指定 POJO。sql
XML
文件中配置 SQL
語句,實現了 SQL
語句與代碼的分離,給程序的維護帶來了很大便利。SQL
語句,所以可以實現比 Hibernate
等全自動 ORM
框架更高的查詢效率,可以完成複雜查詢。在 pom.xml
引入 Mybatis 相關依賴。數據庫
<dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis</artifactId> <version>3.2.8</version> </dependency> <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis-spring</artifactId> <version>1.3.1</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-jdbc</artifactId> <version>4.3.17.RELEASE</version> </dependency>
在 resource
目錄下建立 mybatis-config
配置文件。數組
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd"> <configuration> <!-- 全局參數 --> <settings> <!-- 打印 SQL 語句 --> <setting name="logImpl" value="STDOUT_LOGGING" /> <!-- 使全局的映射器啓用或禁用緩存。 --> <setting name="cacheEnabled" value="false"/> <!-- 全局啓用或禁用延遲加載。當禁用時,全部關聯對象都會即時加載。 --> <setting name="lazyLoadingEnabled" value="true"/> <!-- 當啓用時,有延遲加載屬性的對象在被調用時將會徹底加載任意屬性。不然,每種屬性將會按須要加載。 --> <setting name="aggressiveLazyLoading" value="true"/> <!-- 是否容許單條 SQL 返回多個數據集 (取決於驅動的兼容性) default:true --> <setting name="multipleResultSetsEnabled" value="true"/> <!-- 是否能夠使用列的別名 (取決於驅動的兼容性) default:true --> <setting name="useColumnLabel" value="true"/> <!-- 容許 JDBC 生成主鍵。須要驅動器支持。若是設爲了 true,這個設置將強制使用被生成的主鍵,有一些驅動器不兼容不過仍然能夠執行。 default:false --> <setting name="useGeneratedKeys" value="false"/> <!-- 指定 MyBatis 如何自動映射 數據基表的列 NONE:不映射 PARTIAL:部分 FULL:所有 --> <setting name="autoMappingBehavior" value="PARTIAL"/> <!-- 這是默認的執行類型 (SIMPLE: 簡單; REUSE: 執行器可能重複使用prepared statements語句;BATCH: 執行器能夠重複執行語句和批量更新) --> <setting name="defaultExecutorType" value="SIMPLE"/> <!-- 使用駝峯命名法轉換字段。 --> <setting name="mapUnderscoreToCamelCase" value="true"/> <!-- 設置本地緩存範圍 session:就會有數據的共享 statement:語句範圍 (這樣就不會有數據的共享 ) defalut:session --> <setting name="localCacheScope" value="SESSION"/> <!-- 設置 JDBC 類型爲空時,某些驅動程序 要指定值, default:OTHER,插入空值時不須要指定類型 --> <setting name="jdbcTypeForNull" value="NULL"/> </settings> </configuration>
在 resource
目錄下建立一個 spring-context-mybatis.xml
的集成配置文件。緩存
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd"> <!-- 配置 SqlSession --> <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean"> <property name="dataSource" ref="dataSource"/> <!-- 用於配置對應實體類所在的包,多個 package 之間能夠用 ',' 號分割 --> <property name="typeAliasesPackage" value="com.antoniopeng.ssm.domain"/> <!-- 用於配置對象關係映射--> <property name="mapperLocations" value="classpath:/mapper/**/*.xml"/> <!-- -用於配置文件所在目錄-> <property name="configLocation" value="classpath:/mybatis-config.xml"></property> </bean> <!-- 掃描 Mapper --> <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer"> <property name="basePackage" value="com.antoniopeng.ssm.dao" /> </bean> </beans>
<insert id="insert"> INSERT INTO tb_user ( id, username, password, phone, email, created, updated ) VALUES ( #{id}, #{username}, #{password}, #{phone}, #{email}, #{created}, #{update} ) </insert>
<delete id="delete"> DELETE FROM tb_user WHERE id = #{id} </delete>
<select id="getById" resultType="TbUser"> SELECT a.id, a.username, a.password, a.phone, a.email, a.created, a.updated AS "update" FROM tb_user AS a WHERE a.id = #{id} </select>
<update id="update"> UPDATE tb_user SET username = #{username}, password = #{password}, phone = #{phone}, email = #{email}, created = #{created}, updated = #{update} WHERE id = #{id} </update>
動態 SQL 主要用於解決查詢條件不肯定的狀況:在程序運行期間,根據用戶提交的查詢條件進行查詢。提交的查詢條件不一樣,執行的 SQL 語句不一樣。若將每種可能的狀況均逐一列出,對全部條件進行排列組合,將會出現大量的 SQL 語句。此時,可以使用動態 SQL 來解決這樣的問題。這裏的條件判斷使用的表達式爲 OGNL
表達式。經常使用的動態 SQL 標籤有 <if>
、<where>
、<choose>
、<foreach>
等。session
注意:在 mapper 的動態 SQL 中若出現 >
、<
、>=
,<=
等符號,最好將其轉換爲實體符號。不然,XML 可能會出現解析出錯問題,特別是 <
在 XML 中是絕對不能出現的。mybatis
對於該標籤的執行,當 test 的值爲 true 時,會將其包含的 SQL 片段拼接到其所在的 SQL 語句中。
案例
爲了解決兩個條件均未作設定的狀況,在 where 後添加了一個「1=1」的條件。這樣就不至於兩個條件均未設定而出現只剩下一個 where,而沒有任何可拼接的條件的不完整 SQL 語句。app
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="com.antoniopeng.ssm.dao.StudentDao"> <!-- if --> <select id="selectByIf" resultType="com.antoniopeng.ssm.entity.Student"> SELECT * FROM student WHERE 1 = 1 <if test="name != null and name != ''"> AND name LIKE concat('%', #{name}, '%') </if> <if test="age != null and age > 0"> AND age > #{age} </if> </select> </mapper>
案例
<select id="selectByWhere" resultType="com.antoniopeng.ssm.entity.Student"> SELECT * FROM student <where> <if test="name != null and name != ''"> AND name LIKE concat('%', #{name}, '%') </if> <if test="age != null and age > 0"> AND age > #{age} </if> </where> </select>
該標籤中只能夠包含 <when/>
、<otherwise/>
,能夠包含多個 <when/>
與一個 <otherwise/>
。它們聯合使用,完成 Java 中的開關語句 switch case 功能。
案例
本例要完成的需求是,若姓名不空,則按照姓名查詢;若姓名爲空,則按照年齡查詢;若沒有查詢條件,則沒有查詢結果。
<!-- choose --> <select id="selectByChoose" resultType="com.antoniopeng.ssm.entity.Student"> SELECT * FROM student <where> <choose> <when test="name != null and name != ''"> AND name LIKE concat('%', #{name}, '%') </when> <when test="age != null and age > 0"> AND age > #{age} </when> <otherwise> AND 1 != 1 </otherwise> </choose> </where> </select>
該標籤用於實現對於數組與集合的遍歷。對其使用,須要注意:collection
表示要遍歷的集合類型,這裏是數組,即 array。open
、close
、separator
爲對遍歷內容的 SQL 拼接。
遍歷數組案例
<!-- foreach --> <select id="selectByForeach" resultType="com.antoniopeng.ssm.entity.Student"> SELECT * FROM student <if test="array != null and array.length > 0"> WHERE id IN <foreach collection="array" open="(" close=")" item="id" separator=","> #{id} </foreach> </if> </select>
遍歷泛型爲基本類型的集合案例
/** * 使用 foreach 標籤以 list 基本類型的形式查詢 * @param ids * @return */ public List<Student> selectByForeachWithListBase(List<Long> ids);
<!-- foreach --> <select id="selectByForeachWithListBase" resultType="com.antoniopeng.ssm.entity.Student"> SELECT * FROM student <if test="list != null and list.size > 0"> WHERE id IN <foreach collection="list" open="(" close=")" item="id" separator=","> #{id} </foreach> </if> </select>
遍歷泛型爲自定義類型的集合案例
/** * 使用 foreach 標籤以 list 自定義類型的形式查詢 * @param students * @return */ public List<Student> selectByForeachWithListCustom(List<Student> students);
<!-- foreach --> <select id="selectByForeachWithListCustom" resultType="com.antoniopeng.ssm.entity.Student"> SELECT * FROM student <if test="list != null and list.size > 0"> WHERE id IN <foreach collection="list" open="(" close=")" item="student" separator=","> #{student.id} </foreach> </if> </select>
該標籤用於定義 SQL 片段,以便其它 SQL 標籤複用。而其它標籤使用該 SQL 片段, 須要使用 <include/>
子標籤。該標籤能夠定義 SQL 語句中的任何部分,因此 <include/>
子標籤能夠放在動態 SQL 的任何位置。
案例
<sql id="select"> SELECT id, name, age, score FROM student </sql>
使用 sql 標籤
<!-- foreach --> <select id="selectByForeachWithListCustom" resultType="com.antoniopeng.ssm.entity.Student"> <include refid="select" /> </select>