目录
一、常用标签
1、< if>
<if test="problemId !=null and problemId !=''">
AND PROBLEM_ID =#{problemId,jdbcType=VARCHAR}
</if>
2、< choose>...< when>...< otherwise>
相当于if…else
<choose>
<when test="orderType =='asc'">
order by ead.OPR_DATE asc
</when>
<otherwise>
order by ead.OPR_DATE desc
</otherwise>
</choose>
3、< foreach>
遍历集合。
collection
:集合变量名称
item
:遍历时每个元素的名称
separator
:分隔符
open
:start字符串
close
:end字符串
index
:当前序号,标识是第几个元素
当使用可迭代对象或者数组时,index 是当前迭代的序号,item 的值是本次迭代获取到的元素。
当使用 Map 对象(或者 Map.Entry 对象的集合)时,index 是键,item 是值。
<if test="list != null">
<foreach collection="list" item="item" separator=" or " open="(" close=")" index="item_index">
(
r.activity_id = #{item.activityId, jdbcType=VARCHAR}
and r.rule_id = #{item.ruleId, jdbcType=VARCHAR}
)
</foreach>
</if>
4、< trim prefix="SET" suffixOverrides=",">
自适应添加前缀(prefix)和后缀(suffix),常用语更新语句。
prefix | 给sql语句拼接的前缀 |
---|---|
suffix | 给sql语句拼接的后缀 |
prefixOverrides | 去除sql语句前面的关键字或者字符,该关键字或者字符由prefixOverrides属性指定,假设该属性指定为"AND",当sql语句的开头为"AND",trim标签将会去除该"AND" |
suffixOverrides | 去除sql语句后面的关键字或者字符,该关键字或者字符由suffixOverrides属性指定 |
<update id="updateUserRank" parameterType="com.sinolife.efs.grown.domain.rank.RankDomain">
update efs_rank
<trim prefix="set" suffixOverrides=",">
<if test="value!=null and value!=''">
value1 = value1 + #{value,jdbcType=DECIMAL},
</if>
<if test="desc!=null and desc!=''">
desc1 = #{desc,jdbcType=VARCHAR},
</if>
</trim>
where is_valid ='Y'
and activity_id = #{activityId,jdbcType=VARCHAR}
and rule_id = #{ruleId,jdbcType=VARCHAR}
<if test="userId!=null and userId!=''">
and user_id = #{userId,jdbcType=VARCHAR}
</if>
</update>
5、< bind>
bind 元素可以从 OGNL 表达式中创建一个变量并将其绑定到上下文。比如:
<select id="selectBlogsLike" resultType="Blog">
<bind name="pattern" value="'%' + _parameter.getTitle() + '%'" />
SELECT * FROM BLOG
WHERE title LIKE #{pattern}
</select>
6、< typeAlias> 类型别名
<!-- mybatis-config.xml 中 -->
<typeAlias type="com.someapp.model.User" alias="User"/>
<!-- SQL 映射 XML 中 -->
<select id="selectUsers" resultType="User">
select id, username, hashedPassword
from some_table
where id = #{id}
</select>
二、增、删、改、查
select、insert的标签id 需要和mapper接口类中的方法名一致
1、< select>
- 直接映射返回到Map
<select id="selectPerson" parameterType="int" resultType="map">
SELECT * FROM table_name WHERE ID = #{id,jdbcType=VARCHAR}
</select>
- 直接映射返回到自定义resultMap
<select id="selectPerson" parameterType="int" resultMap="baseDataMap">
SELECT * FROM table_name WHERE ID = #{id,jdbcType=VARCHAR}
</select>
2、< insert>
insert 方法默认会返回一个int值
<insert id="insertActor" parameterType="canger.study.chapter04.bean.Actor">
insert into table_name
(first_name,last_name)
values
(#{firstName,jdbcType=VARCHAR},#{lastName,jdbcType=VARCHAR})
</insert>
3、< delete>
<delete id="deleteByExample" parameterType="string" >
delete from table_name
where id = #{id,jdbcType=VARCHAR}
</delete>
4、< update>
<update id="updateUserRank" parameterType="com.sinolife.efs.grown.domain.rank.RankDomain">
update efs_rank
<trim prefix="set" suffixOverrides=",">
<if test="value!=null and value!=''">
value1 = value1 + #{value,jdbcType=DECIMAL},
</if>
<if test="desc!=null and desc!=''">
desc1 = #{desc,jdbcType=VARCHAR},
</if>
</trim>
where is_valid ='Y'
and activity_id = #{activityId,jdbcType=VARCHAR}
and rule_id = #{ruleId,jdbcType=VARCHAR}
<if test="userId!=null and userId!=''">
and user_id = #{userId,jdbcType=VARCHAR}
</if>
</update>
三、sql片段
sql片段是一个可被其它语句引用的可重用语句块。
1、定义sql片段:
<sql id="userinfo_sql" >
id,name,age
</sql>
2、使用sql片段:
<select id="selectPerson" parameterType="int" resultMap="baseDataMap">
SELECT
<include refid="userinfo_sql" />
FROM table_name
WHERE ID = #{id,jdbcType=VARCHAR}
</select>
四、resultMap结果集
resultMap标签的结构
-
constructor
- 用于在实例化类时,注入结果到构造方法中
idArg
- ID 参数;标记出作为 ID 的结果可以帮助提高整体性能
arg
- 将被注入到构造方法的一个普通结果 -
id
– 一个 ID 结果;标记出作为 ID 的结果可以帮助提高整体性能 -
result
– 注入到字段或 JavaBean 属性的普通结果 -
association
– 一个复杂类型的关联;许多结果将包装成这种类型
嵌套结果映射 – 关联可以是 resultMap 元素,或是对其它结果映射的引用 -
collection
– 一个复杂类型的集合
嵌套结果映射 – 集合可以是 resultMap 元素,或是对其它结果映射的引用 -
discriminator
– 使用结果值来决定使用哪个 resultMap
case
– 基于某些值的结果映射
嵌套结果映射 – case 也是一个结果映射,因此具有相同的结构和元素;或者引用其它的结果映射
下面是一个简单的resultMap
<resultMap id="UserBelongToGroupMap" type="com.sinolife.efs.grown.domain.UserBelongToGroupInfo">
<id column="ID" jdbcType="VARCHAR" property="id" />
<result column="USER_ID" jdbcType="VARCHAR" property="userId" />
<result column="MOBILE" jdbcType="VARCHAR" property="mobile" />
<result column="EMAIL" jdbcType="VARCHAR" property="email" />
<result column="NICKNAME" jdbcType="VARCHAR" property="nickname" />
<result column="HEAD_IMG_URL" jdbcType="VARCHAR" property="headImgUrl" />
<result column="CREATED_USER" jdbcType="VARCHAR" property="createdUser" />
<result column="CREATED_DATE" jdbcType="TIMESTAMP" property="createdDate" />
</resultMap>
association:嵌套结果集映射(一对一)
property
:映射到列结果的字段或属性
javaType
:一个 Java 类的完全限定名,或一个类型别名
- 单步查询:
<resultMap id="cityPlusResultMap" type="canger.study.CityPlus">
<id column="city_id" jdbcType="VARCHAR" property="id"/>
<result column="city" jdbcType="VARCHAR" property="name"/>
<result column="country_id" jdbcType="VARCHAR" property="countryId"/>
<result column="last_update" jdbcType="VARCHAR" property="lastUpdate"/>
<association property="country" javaType="canger.study.Country">
<id column="country_country_id" jdbcType="VARCHAR" property="id"/>
<result column="country" jdbcType="VARCHAR" property="name"/>
<result column="country_last_update" jdbcType="VARCHAR" property="lastUpdate"/>
</association>
</resultMap>
使用级联属性实现一对一查询:
需要countryPlus对象中有一个country成员变量,该成员变量是一个country对象
<resultMap id="cityPlusResultMap" type="canger.study.CountryPlus">
<id column="city_id" jdbcType="VARCHAR" property="id"/>
<result column="city" jdbcType="VARCHAR" property="name"/>
<result column="country_id" jdbcType="VARCHAR" property="countryId"/>
<result column="last_update" jdbcType="VARCHAR" property="lastUpdate"/>
<result column="country_country_id" jdbcType="VARCHAR" property="country.id"/>
<result column="country" jdbcType="VARCHAR" property="country.name"/>
<result column="country_last_update" jdbcType="VARCHAR" property="country.lastUpdate"/>
</resultMap>
- 分步查询:
property
:映射到列结果的字段或属性
select
:子查询的SQL ID。需要加上命名空间namespace
column
:传递多参数方式:column="{id=country_id,name=countryName}"
<resultMap id="cityPlusResultMapStep" type="canger.study.chapter04.bean.CityPlus">
<id column="city_id" jdbcType="VARCHAR" property="id"/>
<result column="city" jdbcType="VARCHAR" property="name"/>
<result column="country_id" jdbcType="VARCHAR" property="countryId"/>
<result column="last_update" jdbcType="VARCHAR" property="lastUpdate"/>
<association property="country"
select="canger.study.selectCountryById"
column="country_id">
</association>
</resultMap>
collection:嵌套结果集映射(一对多)
- 单步查询:
property
:映射到列结果的字段或属性
ofType
:一个 Java 类的完全限定名,或一个类型别名
<select id="selectCountryPlusById" resultMap="countryPlusResultMap">
select
country.country_id as country_id,
country,
country.last_update as last_update,
city_id,
city,
city.country_id as city_country_id,
city.last_update as city_last_update
from country left join city on country.country_id = city.country_id
where country.country_id=#{id}
</select>
<resultMap id="countryPlusResultMap" type="canger.study.CountryPlus">
<id column="country_id" jdbcType="VARCHAR" property="id"/>
<result column="country" jdbcType="VARCHAR" property="name"/>
<result column="last_update" jdbcType="VARCHAR" property="lastUpdate"/>
<collection property="cityList" ofType="canger.study.City">
<id column="city_id" jdbcType="VARCHAR" property="id"/>
<result column="city" jdbcType="VARCHAR" property="name"/>
<result column="city_country_id" jdbcType="VARCHAR" property="countryId"/>
<result column="city_last_update" jdbcType="VARCHAR" property="lastUpdate"/>
</collection>
</resultMap>
- 分步查询:
property
:映射到列结果的字段或属性
select
:子查询的SQL ID。需要加上命名空间namespace
column
:传递多参数方式:column="{id=country_id,name=countryName}"
<select id="selectCountryPlusByIdStep" resultMap="countryPlusResultMapStep">
select *
from country
where country_id=#{id}
</select>
<select id="selectCountryPlusById" resultMap="countryPlusResultMap">
select
city_id,
city,
city.country_id as city_country_id,
city.last_update as city_last_update
from country left join city on country.country_id = city.country_id
where country.country_id=#{id}
</select>
<resultMap id="countryPlusResultMapStep" type="canger.study.CountryPlus">
<id column="country_id" jdbcType="VARCHAR" property="id"/>
<result column="country" jdbcType="VARCHAR" property="name"/>
<result column="last_update" jdbcType="VARCHAR" property="lastUpdate"/>
<collection property="cityList"
select="canger.study.selectCityByCountryId"
column="country_id">
</collection>
</resultMap>
<resultMap id="countryPlusResultMap" type="canger.study.City">
<id column="city_id" jdbcType="VARCHAR" property="id"/>
<result column="city" jdbcType="VARCHAR" property="name"/>
<result column="city_country_id" jdbcType="VARCHAR" property="countryId"/>
<result column="city_last_update" jdbcType="VARCHAR" property="lastUpdate"/>
</resultMap>
discriminator :鉴别器(根据字段的值,决定使用哪个结果集映射)
<resultMap id="vehicleResult" type="Vehicle">
<id property="id" column="id" />
<result property="vin" column="vin"/>
<result property="year" column="year"/>
<result property="make" column="make"/>
<result property="model" column="model"/>
<result property="color" column="color"/>
<discriminator javaType="int" column="vehicle_type">
<case value="1" resultMap="carResult"/>
<case value="2" resultMap="truckResult"/>
<case value="3" resultMap="vanResult"/>
<case value="4" resultMap="suvResult"/>
</discriminator>
</resultMap>
五、插入时获取自增或序列作为主键id
- 使用bind和java.util.UUID函数:
<insert id="insertUser" parameterType="com.study.mybatis.po.User">
<bind name="id"
value='@java.util.UUID@randomUUID().toString().replace("-", "")' />
INSERT INTO USER
(id,username,birthday,sex,address)
VALUES(#{id},#{username},#{birthday},#{sex},#{address})
</insert>
- Oracle 获取序列:
<insert id="insertUser" parameterType="com.study.mybatis.po.User">
<selectKey keyProperty="id" resultType="int" order="BEFORE">
SELECT seq.nextval FROM dual
</selectKey>
INSERT INTO USER
(id,username,birthday,sex,address)
VALUES(#{id},#{username},#{birthday},#{sex},#{address})
</insert>
- mysql获取自增主键的值:
它是在插入数据后查,通过LAST_INSERT_ID()查最后一条数据的id。
<insert id="insertUser" parameterType="com.study.mybatis.po.User">
<selectKey keyProperty="id" resultType="int" order="AFTER">
SELECT
LAST_INSERT_ID()
</selectKey>
INSERT INTO USER
(username,birthday,sex,address)
VALUES(#{username},#{birthday},#{sex},#{address})
</insert>
- mysql使用UUID()函数:
<insert id="insertUser2" parameterType="com.study.mybatis.po.User">
<selectKey keyProperty="id" resultType="string" order="BEFORE">
SELECT UUID()
</selectKey>
INSERT INTO USER
(id,username,birthday,sex,address)
VALUES(#{id},#{username},#{birthday},#{sex},#{address})
</insert>
六、常见的 Java 类型内建的类型别名
别名 | 映射的类型 |
---|---|
_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 |
object | Object |
map | Map |
hashmap | HashMap |
list | List |
arraylist | ArrayList |
collection | Collection |
iterator | Iterator |
七、数据库类型和java类型转换关系
类型处理器 | Java 类型 | JDBC 类型 |
---|---|---|
BooleanTypeHandler | java.lang.Boolean , boolean | 数据库兼容的 BOOLEAN |
ByteTypeHandler | java.lang.Byte , byte | 数据库兼容的 NUMERIC 或 BYTE |
ShortTypeHandler | java.lang.Short , short | 数据库兼容的 NUMERIC 或 SMALLINT |
IntegerTypeHandler | java.lang.Integer , int | 数据库兼容的 NUMERIC 或 INTEGER |
LongTypeHandler | java.lang.Long , long | 数据库兼容的 NUMERIC 或 BIGINT |
FloatTypeHandler | java.lang.Float , float | 数据库兼容的 NUMERIC 或 FLOAT |
DoubleTypeHandler | java.lang.Double , double | 数据库兼容的 NUMERIC 或 DOUBLE |
BigDecimalTypeHandler | java.math.BigDecimal | 数据库兼容的 NUMERIC 或 DECIMAL |
StringTypeHandler | java.lang.String | CHAR , VARCHAR |
ClobReaderTypeHandler | java.io.Reader | - |
ClobTypeHandler | java.lang.String | CLOB , LONGVARCHAR |
NStringTypeHandler | java.lang.String | NVARCHAR , NCHAR |
NClobTypeHandler | java.lang.String | NCLOB |
BlobInputStreamTypeHandler | java.io.InputStream | - |
ByteArrayTypeHandler | byte[] | 数据库兼容的字节流类型 |
BlobTypeHandler | byte[] | BLOB , LONGVARBINARY |
DateTypeHandler | java.util.Date | TIMESTAMP |
DateOnlyTypeHandler | java.util.Date | DATE |
TimeOnlyTypeHandler | java.util.Date | TIME |
SqlTimestampTypeHandler | java.sql.Timestamp | TIMESTAMP |
SqlDateTypeHandler | java.sql.Date | DATE |
SqlTimeTypeHandler | java.sql.Time | TIME |
ObjectTypeHandler | Any | OTHER 或未指定类型 |
EnumTypeHandler | Enumeration Type | VARCHAR 或任何兼容的字符串类型,用来存储枚举的名称(而不是索引序数值) |
EnumOrdinalTypeHandler | Enumeration Type | 任何兼容的 NUMERIC 或 DOUBLE 类型,用来存储枚举的序数值(而不是名称)。 |
SqlxmlTypeHandler | java.lang.String | SQLXML |
InstantTypeHandler | java.time.Instant | TIMESTAMP |
LocalDateTimeTypeHandler | java.time.LocalDateTime | TIMESTAMP |
LocalDateTypeHandler | java.time.LocalDate | DATE |
LocalTimeTypeHandler | java.time.LocalTime | TIME |
OffsetDateTimeTypeHandler | java.time.OffsetDateTime | TIMESTAMP |
OffsetTimeTypeHandler | java.time.OffsetTime | TIME |
ZonedDateTimeTypeHandler | java.time.ZonedDateTime | TIMESTAMP |
YearTypeHandler | java.time.Year | INTEGER |
MonthTypeHandler | java.time.Month | INTEGER |
YearMonthTypeHandler | java.time.YearMonth | VARCHAR 或 LONGVARCHAR |
JapaneseDateTypeHandler | java.time.chrono.JapaneseDate | DATE |
八、mappers配置的几种方式
如果mapper.java 和mapper.xml文件的路径和名称一致,那么就不需要配置:
<mappers> <mapper resource="mybatis/sqlmap/User.xml" /> </mappers>
<mappers>
<mapper resource="org/mybatis/builder/AuthorMapper.xml"/>
<mapper resource="org/mybatis/builder/BlogMapper.xml"/>
<mapper resource="org/mybatis/builder/PostMapper.xml"/>
</mappers>
<!-- Using url fully qualified paths -->
<mappers>
<mapper url="file:///var/mappers/AuthorMapper.xml"/>
<mapper url="file:///var/mappers/BlogMapper.xml"/>
<mapper url="file:///var/mappers/PostMapper.xml"/>
</mappers>
<!-- Using mapper interface classes -->
<mappers>
<mapper class="org.mybatis.builder.AuthorMapper"/>
<mapper class="org.mybatis.builder.BlogMapper"/>
<mapper class="org.mybatis.builder.PostMapper"/>
</mappers>
<!-- Register all interfaces in a package as mappers -->
<mappers>
<package name="org.mybatis.builder"/>
</mappers>
九、mybatis缓存
一级缓存
一级缓存是基于PerpetualCache 的 HashMap本地缓存;
一级缓存的作用域是SqlSession,即不同的SqlSession使用不同的缓存空间;
一级缓存的开启和关闭
- 一级缓存是默认开启的;
- 关闭一级缓存只需要在settings中设置localCacheScope为STATEMENT
清空一级缓存的操作
- SqlSession调用commit方法;
- SqlSession调用clearCache方法;
- select标签的flushCache属性为true;
- SqlSession执行了insert、update或delete操作,此时无论三种标签的 flushCache 属性是否为 false;
二级缓存
二级缓存默认也是采用 PerpetualCache,HashMap存储;
二级缓存的存储作用域为 Mapper(确切说是Namespace),即一个Mapper执行了insert、update或delete操作,不影响另外一个Mapper(不同namespace);
二级缓存可自定义存储实现,如 Ehcache、redis;
二级缓存开启后,需要对应的java Bean实现
<cache
eviction="FIFO"
flushInterval="60000"
size="512"
readOnly="true"/>
二级缓存的开启和关闭
settings
中可设置 cachaEnable为true或false,该属性是二级缓存的总开关,如果关闭,则所有mapper的二级缓存均不生效;- 在cachaEnable为true的情况下,在mapper文件中添加
<cache/>
标签即可开启二级缓存,如果没有该标签,则二级缓存不生效;
cache标签属性
- **eviction:缓存回收策略:**flushInterval:缓存多长时间清空一次,默认不清空,单位毫秒 ms
- LRU——最少使用的,移除最长时间不适用的对象;
- FIFO——先进先出
- WEAK——弱引用,更积极的移除基于垃圾回收器状态和弱引用规则的对象
- SOFT——软引用,更积极的移除基于垃圾回收器状态和弱引用规则的对象
- flushInterval:缓存多久清空一次,默认不清空,时间毫秒 ms
- readOnly:缓存是否只读
- size:缓存觉存放元素个数,默认1024
- type:自定义缓存的全类名
在多个命名空间中共享相同的缓存配置和实例
<cache-ref namespace="com.someone.application.data.SomeMapper"/>