myBatis的mapper映射文件之批量處理方式
#mybatis常見批量處理
在開發當中,可能經常會遇到批量處理這種情況,一般都再在java層面進行,
其本質是節省數據庫連接打開關閉的的次數,占用更少的運行內存。
mybatis批量插入
<insert id="saveFeeRuleList" useGeneratedKeys="true" parameterType="java.util.List"> <selectKey resultType="java.lang.String" keyProperty="id" order="AFTER"> SELECT LAST_INSERT_ID() </selectKey> INSERT INTO t_product_fee_rule( <include refid="Base_Column_List"/> ) VALUES <foreach collection="list" item="item" index="index" separator=","> ( #{item.id},#{item.productId}, #{item.feeCode},#{item.feeValue}, #{item.remarks} ) </foreach> </insert>
mybatis批量刪除
<delete id="removeProductAgent" parameterType="java.util.HashMap"> <foreach collection="maps.agentIds" item="item" index="index" open="" close="" separator=";"> DELETE FROM t_product_agent WHERE 1 = 1 AND product_id = #{maps.productId} AND agent_id = #{item} </foreach> </delete>
此處的maps接口中的@Param值對應,屬於自定義變量。
void removeProductAgent(@Param("maps")Map<String, Object> map);
mybatis批量修改
<update id="saveUpdateFeeRuleList" parameterType="java.util.List"> <foreach collection="list" item="item" index="index" open="" close="" separator=";"> UPDATE t_product_fee_rule SET fee_value = #{item.feeValue}, remarks = #{item.remarks} WHERE id = #{item.id} </foreach> </update>
myBatis mapper文件詳解
本文的寫作目的主要是帶大傢瞭解mapper的寫法
表結構:
CREATE TABLE customer ( id int(11) NOT NULL COMMENT ‘企業用戶ID', name varchar(45) DEFAULT NULL COMMENT ‘名稱', logo varchar(80) DEFAULT ‘' COMMENT ‘企業標識', describe varchar(500) DEFAULT ‘' COMMENT ‘企業班車說明', is_enable tinyint(1) DEFAULT ‘0' COMMENT ‘是否啟用 1=啟用 0=不啟用', phone varchar(20) DEFAULT NULL COMMENT ‘客服電話', admin varchar(50) DEFAULT NULL COMMENT ‘管理員賬號', password varchar(80) DEFAULT NULL COMMENT ‘管理員密碼', uuid varchar(80) DEFAULT NULL COMMENT ‘企業唯一ID', PRIMARY KEY (id) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 ;
Mapper映射文件是在實際開發過程中使用最多的。
Mapper文件中包含的元素有
cache
– 配置給定命名空間的緩存。cache-ref
– 從其他命名空間引用緩存配置。resultMap
– 映射復雜的結果對象。sql
– 可以重用的 SQL 塊,也可以被其他語句引用。insert
– 映射插入語句update
– 映射更新語句delete
– 映射刪除語句select
– 映射查詢語句
本文的代碼都是用mybatis-generator生成的註釋部分是博主自己加的:
<?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"> <!-- namespace綁定瞭與之對應的接口,值是該接口的全限定名;這個參數有且隻有一個 --> <mapper namespace="cn.rainbowbus.dao.CustomerMapper"> <!-- 用來描述select語句返回字段與java屬性的映射關系。 可以有多個resultMap標簽,用不同id區分不同標簽。 可以實現一對多,多對多關系 --> <resultMap id="BaseResultMap" type="cn.rainbowbus.entity.Customer"> <!-- column是表中的字段名。 property是對應的java屬性。 jdbcTyep: 數據庫中字段類型,它與Java中屬性類型有對應關系,詳情看下表。 id:數據庫主鍵字段。 result:普通字段。 一對多標簽 : collection> property:對應的java屬性名 ofType:對應的java屬類型 <id property="java屬性" column="author_third_id" jdbcType="BIGINT"/> <result property="java屬性" column="account_id" jdbcType="VARCHAR"/> --> <id column="id" jdbcType="INTEGER" property="id" /> <result column="name" jdbcType="VARCHAR" javaType="string" property="name" /> <result column="logo" jdbcType="VARCHAR" property="logo" /> <result column="describe" jdbcType="VARCHAR" property="describe" /> <result column="is_enable" jdbcType="BIT" property="isEnable" /> <result column="phone" jdbcType="VARCHAR" property="phone" /> <result column="admin" jdbcType="VARCHAR" property="admin" /> <result column="password" jdbcType="VARCHAR" property="password" /> <result column="uuid" jdbcType="VARCHAR" property="uuid" /> </resultMap> <!-- 可以重用的 SQL 塊,也可以被其他語句引用。 --> <sql id="Example_Where_Clause"> <where>/* where 可以自動去除sql語句where關鍵字後的and關鍵字*/ /* 向sql傳遞數組或List, mybatis使用foreach解析,可以做批量處理。 collection:傳入的集合的變量名稱(要遍歷的值)。 item:每次循環將循環出的數據放入這個變量中。 open:循環開始拼接的字符串。 close:循環結束拼接的字符串。 separator:循環中拼接的分隔符。 */ <foreach collection="oredCriteria" item="criteria" separator="or"> /* 判斷語句,test值等於true執行等於false跳過 test可以是一個值為Boolean型的計算語句 */ <if test="criteria.valid"> /* 前綴'and' 被'(' 替換 prefix:前綴覆蓋並增加其內容 不寫的話默認替換為空 suffix:後綴覆蓋並增加其內容 不寫的話默認替換為空 prefixOverrides:前綴判斷的條件 suffixOverrides:後綴判斷的條件 */ <trim prefix="(" prefixOverrides="and" suffix=")"> <foreach collection="criteria.criteria" item="criterion"> /* choose 是或(or)的關系。 choose標簽是按順序判斷其內部when標簽中的test條件出否成立,如果有一個成立,則 choose 結束。 當 choose 中所有 when 的條件都不滿則時,則執行 otherwise 中的sql。 類似於Java 的 switch 語句,choose 為 switch,when 為 case,otherwise 則為 default。 */ <choose> <when test="criterion.noValue"> and ${criterion.condition} </when> <when test="criterion.singleValue"> and ${criterion.condition} #{criterion.value} </when> <when test="criterion.betweenValue"> and ${criterion.condition} #{criterion.value} and #{criterion.secondValue} </when> <when test="criterion.listValue"> and ${criterion.condition} <foreach close=")" collection="criterion.value" item="listItem" open="(" separator=","> #{listItem} </foreach> </when> </choose> </foreach> </trim> </if> </foreach> </where> </sql> <sql id="Update_By_Example_Where_Clause"> <where> <foreach collection="example.oredCriteria" item="criteria" separator="or"> <if test="criteria.valid"> <trim prefix="(" prefixOverrides="and" suffix=")"> <foreach collection="criteria.criteria" item="criterion"> <choose> <when test="criterion.noValue"> and ${criterion.condition} </when> <when test="criterion.singleValue"> and ${criterion.condition} #{criterion.value} </when> <when test="criterion.betweenValue"> and ${criterion.condition} #{criterion.value} and #{criterion.secondValue} </when> <when test="criterion.listValue"> and ${criterion.condition} <foreach close=")" collection="criterion.value" item="listItem" open="(" separator=","> #{listItem} </foreach> </when> </choose> </foreach> </trim> </if> </foreach> </where> </sql> <sql id="Base_Column_List"> <if test="fields == null"> id, name, logo, describe, is_enable, phone, admin, password, uuid </if> <if test="fields != null"> ${fields} </if> </sql> <!-- select查詢語句標簽 id: 與namespace接口中的方法名對應 parameterType: 參數類型 resultMap : 返回值類型 自增IDset到對象中: useGeneratedKeys="true" keyProperty="id" keyColumn="id" 支持類型簡寫,詳情看下表 --> <select id="selectByExample" useGeneratedKeys="true" keyProperty="id" keyColumn="id" parameterType="cn.rainbowbus.entity.CustomerExample" resultMap="BaseResultMap"> select <if test="distinct"> distinct </if> <include refid="Base_Column_List" />/*引入一個SQL模塊*/ from customer <if test="_parameter != null"> <include refid="Example_Where_Clause" /> </if> <if test="orderByClause != null"> order by ${orderByClause} </if> <if test="startRow != null"> limit #{startRow} , #{pageSize} </if> </select> <select id="selectByPrimaryKey" parameterType="java.lang.Integer" resultMap="BaseResultMap"> select id,name,logo,describe,is_enable,phone,admin,password,uuid from customer where id = #{id,jdbcType=INTEGER} </select> <!-- delete刪除語句標簽 id: 與namespace接口中的方法名對應 parameterType: 參數類型 --> <delete id="deleteByPrimaryKey" parameterType="java.lang.Integer"> delete from customer where id = #{id,jdbcType=INTEGER} </delete> <delete id="deleteByExample" parameterType="cn.rainbowbus.entity.CustomerExample"> delete from customer <if test="_parameter != null"> <include refid="Example_Where_Clause" /> </if> </delete> <!--插入語句--> <insert id="insert" parameterType="cn.rainbowbus.entity.Customer"> insert into customer (id, name, logo, describe, is_enable, phone, admin, password, uuid ) values (#{id,jdbcType=INTEGER}, #{name,jdbcType=VARCHAR}, #{logo,jdbcType=VARCHAR}, #{describe,jdbcType=VARCHAR}, #{isEnable,jdbcType=BIT}, #{phone,jdbcType=VARCHAR}, #{admin,jdbcType=VARCHAR}, #{password,jdbcType=VARCHAR}, #{uuid,jdbcType=VARCHAR} ) </insert> <insert id="insertSelective" parameterType="cn.rainbowbus.entity.Customer"> insert into customer <trim prefix="(" suffix=")" suffixOverrides=","> <if test="id != null"> id, </if> <if test="name != null"> name, </if> <if test="logo != null"> logo, </if> <if test="describe != null"> describe, </if> <if test="isEnable != null"> is_enable, </if> <if test="phone != null"> phone, </if> <if test="admin != null"> admin, </if> <if test="password != null"> password, </if> <if test="uuid != null"> uuid, </if> </trim> <trim prefix="values (" suffix=")" suffixOverrides=","> <if test="id != null"> #{id,jdbcType=INTEGER}, </if> <if test="name != null"> #{name,jdbcType=VARCHAR}, </if> <if test="logo != null"> #{logo,jdbcType=VARCHAR}, </if> <if test="describe != null"> #{describe,jdbcType=VARCHAR}, </if> <if test="isEnable != null"> #{isEnable,jdbcType=BIT}, </if> <if test="phone != null"> #{phone,jdbcType=VARCHAR}, </if> <if test="admin != null"> #{admin,jdbcType=VARCHAR}, </if> <if test="password != null"> #{password,jdbcType=VARCHAR}, </if> <if test="uuid != null"> #{uuid,jdbcType=VARCHAR}, </if> </trim> </insert> <select id="countByExample" parameterType="cn.rainbowbus.entity.CustomerExample" resultType="java.lang.Long"> select count(*) from customer <if test="_parameter != null"> <include refid="Example_Where_Clause" /> </if> </select> <update id="updateByExampleSelective" parameterType="map"> update customer <set> <if test="record.id != null"> id = #{record.id,jdbcType=INTEGER}, </if> <if test="record.name != null"> name = #{record.name,jdbcType=VARCHAR}, </if> <if test="record.logo != null"> logo = #{record.logo,jdbcType=VARCHAR}, </if> <if test="record.describe != null"> describe = #{record.describe,jdbcType=VARCHAR}, </if> <if test="record.isEnable != null"> is_enable = #{record.isEnable,jdbcType=BIT}, </if> <if test="record.phone != null"> phone = #{record.phone,jdbcType=VARCHAR}, </if> <if test="record.admin != null"> admin = #{record.admin,jdbcType=VARCHAR}, </if> <if test="record.password != null"> password = #{record.password,jdbcType=VARCHAR}, </if> <if test="record.uuid != null"> uuid = #{record.uuid,jdbcType=VARCHAR}, </if> </set> <if test="_parameter != null"> <include refid="Update_By_Example_Where_Clause" /> </if> </update> <update id="updateByExample" parameterType="map"> update customer set id = #{record.id,jdbcType=INTEGER}, name = #{record.name,jdbcType=VARCHAR}, logo = #{record.logo,jdbcType=VARCHAR}, describe = #{record.describe,jdbcType=VARCHAR}, is_enable = #{record.isEnable,jdbcType=BIT}, phone = #{record.phone,jdbcType=VARCHAR}, admin = #{record.admin,jdbcType=VARCHAR}, password = #{record.password,jdbcType=VARCHAR}, uuid = #{record.uuid,jdbcType=VARCHAR} <if test="_parameter != null"> <include refid="Update_By_Example_Where_Clause" /> </if> </update> <update id="updateByPrimaryKeySelective" parameterType="cn.rainbowbus.entity.Customer"> update customer <set> <if test="name != null"> name = #{name,jdbcType=VARCHAR}, </if> <if test="logo != null"> logo = #{logo,jdbcType=VARCHAR}, </if> <if test="describe != null"> describe = #{describe,jdbcType=VARCHAR}, </if> <if test="isEnable != null"> is_enable = #{isEnable,jdbcType=BIT}, </if> <if test="phone != null"> phone = #{phone,jdbcType=VARCHAR}, </if> <if test="admin != null"> admin = #{admin,jdbcType=VARCHAR}, </if> <if test="password != null"> password = #{password,jdbcType=VARCHAR}, </if> <if test="uuid != null"> uuid = #{uuid,jdbcType=VARCHAR}, </if> </set> where id = #{id,jdbcType=INTEGER} </update> <update id="updateByPrimaryKey" parameterType="cn.rainbowbus.entity.Customer"> update customer set name = #{name,jdbcType=VARCHAR}, logo = #{logo,jdbcType=VARCHAR}, describe = #{describe,jdbcType=VARCHAR}, is_enable = #{isEnable,jdbcType=BIT}, phone = #{phone,jdbcType=VARCHAR}, admin = #{admin,jdbcType=VARCHAR}, password = #{password,jdbcType=VARCHAR}, uuid = #{uuid,jdbcType=VARCHAR} where id = #{id,jdbcType=INTEGER} </update> <update id="batchUpdateByKeys" parameterType="java.util.List"> update customer <trim prefix="set" suffixOverrides=","> <trim prefix="id =case id" suffix="end,"> <foreach collection="recordList" index="index" item="item"> <if test="item.id !=null "> when #{item.id,jdbcType=INTEGER} then #{item.id,jdbcType=INTEGER} </if> <if test="item.id ==null "> when #{item.id,jdbcType=INTEGER} then customer.id </if> </foreach> </trim> <trim prefix="name =case id" suffix="end,"> <foreach collection="recordList" index="index" item="item"> <if test="item.name !=null "> when #{item.id,jdbcType=INTEGER} then #{item.name,jdbcType=VARCHAR} </if> <if test="item.name ==null "> when #{item.id,jdbcType=INTEGER} then customer.name </if> </foreach> </trim> <trim prefix="logo =case id" suffix="end,"> <foreach collection="recordList" index="index" item="item"> <if test="item.logo !=null "> when #{item.id,jdbcType=INTEGER} then #{item.logo,jdbcType=VARCHAR} </if> <if test="item.logo ==null "> when #{item.id,jdbcType=INTEGER} then customer.logo </if> </foreach> </trim> <trim prefix="describe =case id" suffix="end,"> <foreach collection="recordList" index="index" item="item"> <if test="item.describe !=null "> when #{item.id,jdbcType=INTEGER} then #{item.describe,jdbcType=VARCHAR} </if> <if test="item.describe ==null "> when #{item.id,jdbcType=INTEGER} then customer.describe </if> </foreach> </trim> <trim prefix="is_enable =case id" suffix="end,"> <foreach collection="recordList" index="index" item="item"> <if test="item.isEnable !=null "> when #{item.id,jdbcType=INTEGER} then #{item.isEnable,jdbcType=BIT} </if> <if test="item.isEnable ==null "> when #{item.id,jdbcType=INTEGER} then customer.is_enable </if> </foreach> </trim> <trim prefix="phone =case id" suffix="end,"> <foreach collection="recordList" index="index" item="item"> <if test="item.phone !=null "> when #{item.id,jdbcType=INTEGER} then #{item.phone,jdbcType=VARCHAR} </if> <if test="item.phone ==null "> when #{item.id,jdbcType=INTEGER} then customer.phone </if> </foreach> </trim> <trim prefix="admin =case id" suffix="end,"> <foreach collection="recordList" index="index" item="item"> <if test="item.admin !=null "> when #{item.id,jdbcType=INTEGER} then #{item.admin,jdbcType=VARCHAR} </if> <if test="item.admin ==null "> when #{item.id,jdbcType=INTEGER} then customer.admin </if> </foreach> </trim> <trim prefix="password =case id" suffix="end,"> <foreach collection="recordList" index="index" item="item"> <if test="item.password !=null "> when #{item.id,jdbcType=INTEGER} then #{item.password,jdbcType=VARCHAR} </if> <if test="item.password ==null "> when #{item.id,jdbcType=INTEGER} then customer.password </if> </foreach> </trim> <trim prefix="uuid =case id" suffix="end,"> <foreach collection="recordList" index="index" item="item"> <if test="item.uuid !=null "> when #{item.id,jdbcType=INTEGER} then #{item.uuid,jdbcType=VARCHAR} </if> <if test="item.uuid ==null "> when #{item.id,jdbcType=INTEGER} then customer.uuid </if> </foreach> </trim> </trim> where id in( <foreach collection="recordList" index="index" item="item" separator=","> #{item.id,jdbcType=INTEGER} </foreach> ) </update> <insert id="batchInsert" parameterType="cn.rainbowbus.entity.Customer"> insert into customer (id, name, logo, describe, is_enable, phone, admin, password, uuid) values <foreach collection="list" item="item" index="index" separator="," > (#{item.id,jdbcType=INTEGER}, #{item.name,jdbcType=VARCHAR}, #{item.logo,jdbcType=VARCHAR}, #{item.describe,jdbcType=VARCHAR}, #{item.isEnable,jdbcType=BIT}, #{item.phone,jdbcType=VARCHAR}, #{item.admin,jdbcType=VARCHAR}, #{item.password,jdbcType=VARCHAR}, #{item.uuid,jdbcType=VARCHAR})</foreach> </insert> <delete id="batchDeleteByKeys" parameterType="java.lang.Integer"> delete from customer where id in ( <foreach collection="ids" index="index" item="id" separator=","> #{id} </foreach> ) </delete> </mapper>
註意
#{}占位符: 占位
如果傳入的是基本類型,那麼#{}中的變量名稱可以隨意寫
如果傳入的參數是pojo類型,那麼#{}中的變量名稱必須是pojo中的屬性.屬性名(user.username)
$ {}拼接符: 字符串原樣拼接(有sql註入的風險)
如果傳入的是基本類型,那麼中 的 變 量 名 必 須 是 v a l u e 如 果 傳 入 的 參 數 是 p o j o 類 型 , 那 麼 {}中的變量名必須是value 如果傳入的參數是pojo類型,那麼中的變量名必須是value如果傳入的參數是pojo類型,那麼{}中的變量名稱必須是pojo中的屬性.屬性名(user.username)
註意:使用拼接符有可能造成sql註入,在頁面輸入的時候可以加入校驗,不可輸入sql關鍵字,不可輸入空格
註意:如果是取簡單數量類型的參數,括號中的值必須為value
例: select * from user where username like ‘%${value}%’
可以這樣寫來解決sql註入:select * from user where username like ‘%’ #{name}’%'(開發經常使用)
動態SQL
Mybatis提供瞭9種動態sql標簽:trim | where | set | foreach | if | choose | when | otherwise | bind。
1.判斷語句if
判斷語句,test值等於true執行等於false跳過,test可以是一個值為Boolean型的計算語句
<if test="true"> </if>
2.修剪語句:trim
- 前綴’and’ 被'(‘ 替換
prefix
:前綴覆蓋並增加其內容 不寫的話默認替換為空suffix
:後綴覆蓋並增加其內容 不寫的話默認替換為空prefixOverrides
:前綴判斷的條件suffixOverrides
:後綴判斷的條件
<trim prefix="(" suffix=")" prefixOverrides="and" ></trim>
3.循環語句:foreach
- 向sql傳遞數組或List, mybatis使用foreach解析,可以做批量處理。
collection
:傳入的集合的變量名稱(要遍歷的值)。item
:每次循環將循環出的數據放入這個變量中。open
:循環開始拼接的字符串。close
:循環結束拼接的字符串。separator
:循環中拼接的分隔符。
<foreach collection="oredCriteria" item="criteria" separator="or"></foreach>
4.選擇語句:choose
類似於Java 的 switch 語句,choose 為 switch,when 為 case,otherwise 則為 default。
choose 是或(or)的關系。choose標簽是按順序判斷其內部when標簽中的test條件出否成立,如果有一個成立,則 choose 結束。當 choose 中所有 when 的條件都不滿則時,則執行 otherwise 中的sql。
<choose> <when test="false"> ... </when> <when test="true"> ... </when> <otherwise> ...同樣這不是必須的 </otherwise> </choose>
mapper對應的Java接口文件:
package cn.rainbowbus.dao; import cn.rainbowbus.entity.Customer; import cn.rainbowbus.entity.CustomerExample; import java.util.List; import org.apache.ibatis.annotations.Param; public interface CustomerMapper { long countByExample(CustomerExample example); int deleteByExample(CustomerExample example); int deleteByPrimaryKey(Integer id); int insert(Customer record); int insertSelective(Customer record); List<Customer> selectByExample(CustomerExample example); Customer selectByPrimaryKey(Integer id); int updateByExampleSelective(@Param("record") Customer record, @Param("example") CustomerExample example); int updateByExample(@Param("record") Customer record, @Param("example") CustomerExample example); int updateByPrimaryKeySelective(Customer record); int updateByPrimaryKey(Customer record); int batchUpdateByKeys(@Param("recordList") List<Customer> recordList); void batchInsert(List<Customer> recordLst); int batchDeleteByKeys(@Param("ids") Integer[] ids); }
mybatis支持別名:
別名 | 映射類型 |
---|---|
_byte | byte |
_long | long |
_short | short |
_int | int |
_integer | int |
_double | double |
_float | float |
_boolean | boolean |
string | String |
byte | Byte |
long | Long |
short | Short |
int | Integer |
integer | Integer |
double | Double |
float | Float |
boolean | Boolean |
date | Date |
decimal | BigDecimal |
bigdecimal | BigDecimal |
map | Map |
jdbcType與JavaType的映射關系
jdbcType | Java Type |
---|---|
CHAR | String |
ARCHAR | String |
ONGVARCHAR | String |
UMERIC | java.math.BigDecimal |
ECIMAL | java.math.BigDecimal |
IT | boolean |
OOLEAN | boolean |
INYINT | byte |
SMALLINT | short |
INTEGER | int |
BIGINT | long |
REAL | float |
FLOAT | double |
DOUBLE | double |
BINARY | byte[] |
VARBINARY | byte[] |
LONGVARBINARY | byte[] |
DATE | java.sql.Date |
TIME | java.sql.Time |
TIMESTAMP | java.sql.Timestamp |
CLOB | Clob |
BLOB | Blob |
ARRAY | Array |
DISTINCT | mapping of underlying type |
STRUCT | Struct |
REF | Ref |
DATALINK | java.net.URL[color=red][/color] |
以上為個人經驗,希望能給大傢一個參考,也希望大傢多多支持WalkonNet。
推薦閱讀:
- Mybatis 批量更新實體對象方式
- mybatis update更新字段的使用操作
- 詳解Mybatis Generator的具體使用教程
- 基於mybatis 動態SQL查詢總結
- mybatis實現批量插入並返回主鍵(xml和註解兩種方法)