一、MyBatis 介紹
MyBatis 是支持普通 SQL查詢,
存儲過程和高級映射的優秀
持久層框架。MyBatis 消除了幾乎所有的
JDBC代碼和參數的手工設置以及
結果集的檢索。MyBatis 使用簡單的 XML或注解用於配置和原始映射,將接口和 Java 的POJOs(Plain Old Java Objects,普通的 Java對象)映射成數據庫中的記錄。
二、Spring MVC中集成MyBatis
1、准備依賴的jar包,添加到工程
2、MyBatis 與數據庫連接配置
先添加如下配置文件到工程:
applicationContext-mybatis.xml為mybatis配置文件,內容如下:
1 <?xml version="1.0" encoding="UTF-8"?> 2 <beans xmlns="http://www.springframework.org/schema/beans" xmlns:p="http://www.springframework.org/schema/p" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 3 xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx" xmlns:jdbc="http://www.springframework.org/schema/jdbc" 4 xmlns:context="http://www.springframework.org/schema/context" xmlns:cache="http://www.springframework.org/schema/cache" 5 xsi:schemaLocation=" 6 http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.2.xsd 7 http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd 8 http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc-3.2.xsd 9 http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.2.xsd 10 http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.2.xsd 11 http://www.springframework.org/schema/cache http://www.springframework.org/schema/cache/spring-cache-3.2.xsd" 12 default-autowire="byName" default-lazy-init="false"> 13 14 <!-- Mybatis's sqlSessionFactory config --> 15 <bean id="mysqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean"> 16 <property name="dataSource" ref="dataSource"></property> 17 <property name="configLocation" value="classpath:mybatis/mybatis-config-mysql.xml" /> 18 </bean> 19 <bean id="mapperScannerConfigurer" class="org.mybatis.spring.mapper.MapperScannerConfigurer"> 20 <property name="sqlSessionFactoryBeanName" value="mysqlSessionFactory" /> 21 <property name="basePackage" value="com.ruijie.crazy.dao.persistence" /> 22 </bean> 23 24 <!-- Spring JtaTransactionManager --> 25 <bean name="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> 26 <property name="dataSource" ref="dataSource"></property> 27 </bean> 28 29 <!-- enable the configuration of transactional behavior based on annotations --> 30 <tx:annotation-driven transaction-manager="transactionManager" order="1" /> 31 32 <!-- 啟用事務 --> 33 <tx:advice id="txAdvice" transaction-manager="transactionManager"> 34 <tx:attributes> 35 <tx:method name="select*" read-only="true" propagation="SUPPORTS" /> 36 <tx:method name="list*" read-only="true" propagation="SUPPORTS" /> 37 <tx:method name="query*" read-only="true" propagation="SUPPORTS" /> 38 <tx:method name="get*" read-only="true" propagation="SUPPORTS" /> 39 <tx:method name="find*" read-only="true" propagation="SUPPORTS" /> 40 <tx:method name="count*" read-only="true" propagation="SUPPORTS" /> 41 42 <tx:method name="add*" read-only="false" propagation="REQUIRED" rollback-for="Throwable" /> 43 <tx:method name="del*" read-only="false" propagation="REQUIRED" rollback-for="Throwable" /> 44 <tx:method name="insert*" read-only="false" propagation="REQUIRED" rollback-for="Throwable" /> 45 <tx:method name="update*" read-only="false" propagation="REQUIRED" rollback-for="Throwable" /> 46 <tx:method name="delete*" read-only="false" propagation="REQUIRED" rollback-for="Throwable" /> 47 <tx:method name="save*" read-only="false" propagation="REQUIRED" rollback-for="Throwable" /> 48 49 <tx:method name="newTran*" read-only="false" propagation="REQUIRES_NEW" rollback-for="Throwable" /> 50 <tx:method name="xaTran*" read-only="false" propagation="REQUIRED" isolation="SERIALIZABLE" rollback-for="Throwable" /> 51 52 <tx:method name="*" propagation="REQUIRED" rollback-for="Throwable" /> 53 </tx:attributes> 54 </tx:advice> 55 56 </beans>
applicationContext-database.xml為數據庫連接配置文件,內容如下:
1 <?xml version="1.0" encoding="UTF-8"?> 2 <beans xmlns="http://www.springframework.org/schema/beans" xmlns:p="http://www.springframework.org/schema/p" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 3 xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx" xmlns:jdbc="http://www.springframework.org/schema/jdbc" 4 xmlns:context="http://www.springframework.org/schema/context" xmlns:cache="http://www.springframework.org/schema/cache" 5 xsi:schemaLocation=" 6 http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.2.xsd 7 http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd 8 http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc-3.2.xsd 9 http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.2.xsd 10 http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.2.xsd 11 http://www.springframework.org/schema/cache http://www.springframework.org/schema/cache/spring-cache-3.2.xsd" 12 default-autowire="byName" default-lazy-init="false"> 13 <!-- 加載配置屬性文件 --> 14 <context:property-placeholder ignore-unresolvable="true" location="classpath:jdbc-dbcp.properties" /> 15 16 <!-- 數據庫連接池 --> 17 <bean id="parentDataSource" class="org.apache.commons.dbcp2.BasicDataSource" destroy-method="close" abstract="true"> 18 <property name="username" value="${dbcp.db.username}" /> 19 <property name="password" value="${dbcp.db.password}" /> 20 <property name="driverClassName" value="${dbcp.db.driverClassName}" /> 21 <property name="connectionProperties" value="${dbcp.db.connectionProperties}" /> 22 23 24 <!-- Connection Pooling Info --> 25 <!-- 連接池啟動時創建的初始化連接數量 --> 26 <property name="initialSize" value="${dbcp.db.initialSize}" /> 27 <!-- 連接池中可同時連接的最大的連接數(默認值為8,調整為20,高峰單機器在20並發左右,自己根據應用場景定) --> 28 <property name="maxTotal" value="${dbcp.db.maxTotal}" /> 29 <!-- 連接池中最大的空閑的連接數,超過的空閑連接將被釋放,如果設置為負數表示不限制(默認為8個,maxIdle不能設置 太小,因為假如在高負載的情況下,連接的打開時間比關閉的時間快,會引起連接池中idle的個數 上升超過maxIdle,而造成頻繁的連接銷毀>和創建,類似於jvm參數中的Xmx設置) --> 30 <property name="maxIdle" value="${dbcp.db.maxIdle}" /> 31 <!-- 連接池中最小的空閑的連接數,低於這個數量會被創建新的連接(默認為0,調整為5,該參數越接近maxIdle,性能越>好,因為連接的創建和銷毀,都是需要消耗資源的;但是不能太大,因為在機器很空閑的時候,也會創建低於minidle個數的連接,類似於jvm>參數中的Xmn設置) --> 32 <property name="minIdle" value="${dbcp.db.minIdle}" /> 33 <!--最大等待時間,當沒有可用連接時,連接池等待連接釋放的最大時間,超過該時間限制會拋出異常,如果設置-1表示無>限等待(默認為無限,調整為60000ms,避免因線程池不夠用,而導致請求被無限制掛起) --> 34 <property name="maxWaitMillis" value="${dbcp.db.maxWaitMillis}" /> 35 36 37 <!-- Validate配置代碼 --> 38 <property name="testOnCreate" value="${dbcp.db.testOnCreate}" /> 39 <!-- GenericObjectPool中針對pool管理,起了一個Evict的TimerTask定時線程進行控制(可通過設置參數timeBetweenEvictionRunsMillis>0),定時對線程池中的鏈接進行validateObject校驗,對無效的鏈接進行關閉后,會調用ensureMinIdle,適當建立鏈接保證最小的minIdle連接數。 --> 40 <property name="testWhileIdle" value="${dbcp.db.testWhileIdle}" /> 41 <!-- 對拿到的connection進行validateObject校驗 --> 42 <property name="testOnBorrow" value="${dbcp.db.testOnBorrow}" /> 43 <property name="testOnReturn" value="${dbcp.db.testOnReturn}" /> 44 45 <!-- 設置的Evict線程的時間,單位ms,大於0才會開啟evict檢查線程 --> 46 <property name="timeBetweenEvictionRunsMillis" value="${dbcp.db.timeBetweenEvictionRunsMillis}" /> 47 <!-- 代表每次檢查鏈接的數量,建議設置和maxActive一樣大,這樣每次可以有效檢查所有的鏈接. --> 48 <property name="numTestsPerEvictionRun" value="${dbcp.db.numTestsPerEvictionRun}" /> 49 <property name="minEvictableIdleTimeMillis" value="${dbcp.db.minEvictableIdleTimeMillis}" /> 50 <!-- 驗證連接是否可用sql --> 51 <property name="validationQuery" value="${dbcp.db.validationQuery}" /> 52 53 <!--超過removeAbandonedTimeout時間后,是否進 行沒用連接(廢棄)的回收(默認為false,調整為true) --> 54 <property name="removeAbandonedOnMaintenance" value="${dbcp.db.removeAbandonedOnMaintenance}" /> 55 <property name="removeAbandonedOnBorrow" value="${dbcp.db.removeAbandonedOnBorrow}" /> 56 <!--超過時間限制,回收沒有用(廢棄)的連接(默認為 300秒,調整為180) --> 57 <property name="removeAbandonedTimeout" value="${dbcp.db.removeAbandonedTimeout}" /> 58 <!-- 是否在自動回收超時連接的時候打印連接的超時錯誤 --> 59 <property name="logAbandoned" value="${dbcp.db.logAbandoned}" /> 60 61 </bean> 62 63 <!-- 數據庫連接池 --> 64 <bean id="defaultDataSource" parent="parentDataSource"> 65 <property name="url" value="${dbcp.db.url}" /> 66 </bean> 67 68 <bean id="dataSource" class="com.ruijie.crazy.core.db.DynamicDataSource"> 69 <property name="targetDataSources"> 70 <map key-type="java.lang.String"> 71 </map> 72 </property> 73 <property name="defaultTargetDataSource" ref="defaultDataSource" /> 74 </bean> 75 76 </beans>
jdbc-dbcp.properties為數據庫連接配置:
1 dbcp.db.driverClassName=com.mysql.jdbc.Driver 2 dbcp.db.url=jdbc:mysql://127.0.0.1:3306/test 3 dbcp.db.username=root 4 dbcp.db.password=admin 5 6 dbcp.db.connectionProperties=useUnicode=true;characterEncoding=utf8; 7 #Connection Pooling Info 8 dbcp.db.initialSize=20 9 dbcp.db.maxTotal=50 10 dbcp.db.maxIdle=50 11 dbcp.db.minIdle=20 12 dbcp.db.maxWaitMillis=90000 13 14 dbcp.db.validationQuery=SELECT 1 FROM DUAL 15 16 dbcp.db.testOnCreate=false 17 dbcp.db.testWhileIdle=true 18 dbcp.db.testOnBorrow=true 19 dbcp.db.testOnReturn=false 20 21 dbcp.db.timeBetweenEvictionRunsMillis=60000 22 dbcp.db.numTestsPerEvictionRun=50 23 #The minimum amount of time an object may sit idle in the pool before it is eligable for eviction by the idle object evictor (if any). 24 dbcp.db.minEvictableIdleTimeMillis=300000 25 26 dbcp.db.removeAbandonedOnBorrow=true 27 dbcp.db.removeAbandonedOnMaintenance=true 28 dbcp.db.removeAbandonedTimeout=180 29 dbcp.db.logAbandoned=false
mybatis-config-mysql.xml為sql映射配置文件:
1 <?xml version="1.0" encoding="UTF-8"?> 2 <!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd"> 3 <configuration> 4 <!-- 基礎設置 --> 5 <settings> 6 <!-- 全局映射器啟用緩存,設置為false,由應用去管理緩存,mybatis專注於sql --> 7 <setting name="cacheEnabled" value="false" /> 8 <!-- 查詢時,關閉關聯對象即時加載以提高性能 --> 9 <setting name="lazyLoadingEnabled" value="true" /> 10 <!-- 設置關聯對象加載的形態,此處為按需加載字段(加載字段由SQL指 定),不會加載關聯表的所有字段,以提高性能 --> 11 <setting name="aggressiveLazyLoading" value="false" /> 12 <!-- 對於未知的SQL查詢,允許返回不同的結果集以達到通用的效果 --> 13 <setting name="multipleResultSetsEnabled" value="true" /> 14 <!-- 允許使用列標簽代替列名 --> 15 <setting name="useColumnLabel" value="true" /> 16 <!-- 允許使用自定義的主鍵值(比如由程序生成的UUID 32位編碼作為鍵值),數據表的PK生成策略將被覆蓋 --> 17 <setting name="useGeneratedKeys" value="false" /> 18 <!-- 給予被嵌套的resultMap以字段-屬性的映射支持 --> 19 <setting name="autoMappingBehavior" value="FULL" /> 20 <!-- 對於批量更新操作緩存SQL以提高性能,如果返回行數有問題,可以修改該值為SIMPLE --> 21 <setting name="defaultExecutorType" value="REUSE" /> 22 <!-- 數據庫超過120秒仍未響應則超時 --> 23 <setting name="defaultStatementTimeout" value="120" /> 24 </settings> 25 26 <!-- SQL映射文件 --> 27 <mappers> 28 <!-- 通用SQL語句片段 --> 29 <mapper resource="mybatis/mapper/common_SqlMap.xml" /> 30 <mapper resource="mybatis/mapper/TProvinceMapper.xml" /> 31 </mappers> 32 </configuration>
common_SqlMap.xml是為了封裝sql查詢語句使用的配置文件,非必須配置:
1 <?xml version="1.0" encoding="UTF-8" ?> 2 <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" > 3 <mapper namespace="common" > 4 <sql id="If_Example_Conditon_Valid" > 5 <if test="condition.valid" > 6 <trim prefix="(" suffix=")" prefixOverrides="and" > 7 <foreach collection="condition.criterions" item="criterion" > 8 <choose > 9 <when test="criterion.noValue" > 10 and ${criterion.condition} 11 </when> 12 <when test="criterion.singleValue" > 13 and ${criterion.condition} #{criterion.value} 14 </when> 15 <when test="criterion.betweenValue" > 16 and ${criterion.condition} #{criterion.value} and #{criterion.secondValue} 17 </when> 18 <when test="criterion.listValue" > 19 and ${criterion.condition} 20 <foreach collection="criterion.value" item="listItem" open="(" close=")" separator="," > 21 #{listItem} 22 </foreach> 23 </when> 24 <when test="criterion.dateValue" > 25 and ${criterion.condition} #{criterion.value,jdbcType=TIMESTAMP} 26 </when> 27 </choose> 28 </foreach> 29 </trim> 30 </if> 31 </sql> 32 <sql id="Example_Where_Clause" > 33 <where > 34 <foreach collection="oredCriteria" item="condition" separator="or" > 35 <include refid="common.If_Example_Conditon_Valid" /> 36 </foreach> 37 </where> 38 </sql> 39 <sql id="Update_By_Example_Where_Clause" > 40 <where > 41 <foreach collection="example.oredCriteria" item="condition" separator="or" > 42 <include refid="common.If_Example_Conditon_Valid" /> 43 </foreach> 44 </where> 45 </sql> 46 </mapper>
TProvinceMapper.xml為與數據庫中具體的表匹配的映射文件:
1 <?xml version="1.0" encoding="UTF-8" ?> 2 <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" > 3 <mapper namespace="com.ruijie.crazy.dao.persistence.TProvinceMapper" > 4 <resultMap id="BaseResultMap" type="com.ruijie.crazy.entity.beans.TProvince" > 5 <id column="id" property="id" jdbcType="INTEGER" /> 6 <result column="province" property="province" jdbcType="VARCHAR" /> 7 </resultMap> 8 <sql id="Base_Column_List" > 9 id, province 10 </sql> 11 <select id="selectByExample" resultMap="BaseResultMap" parameterType="com.ruijie.crazy.core.mybatis.Criteria" > 12 select 13 <if test="distinct" > 14 distinct 15 </if> 16 <include refid="Base_Column_List" /> 17 from t_province 18 <if test="_parameter != null" > 19 <include refid="common.Example_Where_Clause" /> 20 </if> 21 </select> 22 <select id="selectByPrimaryKey" resultMap="BaseResultMap" parameterType="java.lang.Integer" > 23 select 24 <include refid="Base_Column_List" /> 25 from t_province 26 where id = #{id,jdbcType=INTEGER} 27 </select> 28 <delete id="deleteByPrimaryKey" parameterType="java.lang.Integer" > 29 delete from t_province 30 where id = #{id,jdbcType=INTEGER} 31 </delete> 32 <delete id="deleteByExample" parameterType="com.ruijie.crazy.core.mybatis.Criteria" > 33 delete from t_province 34 <if test="_parameter != null" > 35 <include refid="common.Example_Where_Clause" /> 36 </if> 37 </delete> 38 <insert id="insert" parameterType="com.ruijie.crazy.entity.beans.TProvince" > 39 <selectKey resultType="java.lang.Integer" keyProperty="id" order="BEFORE" > 40 SELECT LAST_INSERT_ID() 41 </selectKey> 42 insert into t_province (id, province) 43 values (#{id,jdbcType=INTEGER}, #{province,jdbcType=VARCHAR}) 44 </insert> 45 <insert id="insertSelective" parameterType="com.ruijie.crazy.entity.beans.TProvince" > 46 <selectKey resultType="java.lang.Integer" keyProperty="id" order="BEFORE" > 47 SELECT LAST_INSERT_ID() 48 </selectKey> 49 insert into t_province 50 <trim prefix="(" suffix=")" suffixOverrides="," > 51 id, 52 <if test="province != null" > 53 province, 54 </if> 55 </trim> 56 <trim prefix="values (" suffix=")" suffixOverrides="," > 57 #{id,jdbcType=INTEGER}, 58 <if test="province != null" > 59 #{province,jdbcType=VARCHAR}, 60 </if> 61 </trim> 62 </insert> 63 <select id="countByExample" parameterType="com.ruijie.crazy.core.mybatis.Criteria" resultType="java.lang.Integer" > 64 select count(*) from t_province 65 <if test="_parameter != null" > 66 <include refid="common.Example_Where_Clause" /> 67 </if> 68 </select> 69 <update id="updateByExampleSelective" parameterType="map" > 70 update t_province 71 <set > 72 <if test="record.id != null" > 73 id = #{record.id,jdbcType=INTEGER}, 74 </if> 75 <if test="record.province != null" > 76 province = #{record.province,jdbcType=VARCHAR}, 77 </if> 78 </set> 79 <if test="_parameter != null" > 80 <include refid="common.Update_By_Example_Where_Clause" /> 81 </if> 82 </update> 83 <update id="updateByExample" parameterType="map" > 84 update t_province 85 set id = #{record.id,jdbcType=INTEGER}, 86 province = #{record.province,jdbcType=VARCHAR} 87 <if test="_parameter != null" > 88 <include refid="common.Update_By_Example_Where_Clause" /> 89 </if> 90 </update> 91 <update id="updateByPrimaryKeySelective" parameterType="com.ruijie.crazy.entity.beans.TProvince" > 92 update t_province 93 <set > 94 <if test="province != null" > 95 province = #{province,jdbcType=VARCHAR}, 96 </if> 97 </set> 98 where id = #{id,jdbcType=INTEGER} 99 </update> 100 <update id="updateByPrimaryKey" parameterType="com.ruijie.crazy.entity.beans.TProvince" > 101 update t_province 102 set province = #{province,jdbcType=VARCHAR} 103 where id = #{id,jdbcType=INTEGER} 104 </update> 105 106 </mapper>
3、java中代碼

4、測試
Controller中寫入如下測試代碼:
1 package com.ruijie.crazy.controller; 2 3 import java.util.HashMap; 4 import java.util.List; 5 import java.util.Map; 6 7 import javax.annotation.Resource; 8 9 import org.springframework.stereotype.Controller; 10 import org.springframework.web.bind.annotation.RequestMapping; 11 import org.springframework.web.bind.annotation.RequestMethod; 12 import org.springframework.web.bind.annotation.ResponseBody; 13 import org.springframework.web.servlet.ModelAndView; 14 15 import com.ruijie.crazy.dao.service.TProvinceDao; 16 import com.ruijie.crazy.entity.beans.TProvince; 17 18 @Controller 19 @RequestMapping("/myweb") 20 public class MyFirstController { 21 @Resource 22 TProvinceDao tProvinceDao; 23 24 @RequestMapping(value = "/test", method = RequestMethod.GET) 25 public ModelAndView getUserInfoByCode() { 26 System.out.println("/myweb/test"); 27 Map<String, Object> map = new HashMap<String, Object>(); 28 29 List<TProvince> plist= tProvinceDao.getAll(); 30 map.put("userName", "ypf: " + plist.get(0).getProvince()); 31 return new ModelAndView("hello",map); 32 } 33 34 }
運行工程,瀏覽器輸入http://127.0.0.1/crazypf/myweb/test.html,顯示結果如下:
