参数传递方式
单个参数
可以接受基本类型,对象类型,集合类型的值。
public Employee getEmpById(Integer id);
多个参数
会被MyBatis重新包装成一个Map传入。Map的key是param1,param2,0,1…,值就是参数的值。
public Employee getEmpByIdAndLastName(Integer id,String lastName);
命名参数
参数使用@Param起一个名字,MyBatis就会将这些参数封装进map中,key指定的名字。
public Employee getEmpByIdAndLastName(@Param("id")Integer id,@Param("lastName")String lastName);
POJO
public boolean updateEmp(Employee employee);
Map
public Employee getEmpByMap(Map<String, Object> map);
映射文件中参数设置
#{id,javaType=int,jdbcType=INTEGER}
javaType指定java类型 jdbcType指定数据库类型 numericScale小数点后保留位数。
mode 属性允许指定IN,OUT 或INOUT 参数。如果参数为OUT 或INOUT,参数对象属性的真实值将会被改变,就像在获取输出参数时所期望的那样。
参数位置支持的属性
javaType、jdbcType、mode、numericScale、resultMap、typeHandler、jdbcTypeName、expression
Mybatis 中$与#的区别
https://www.cnblogs.com/hellokitty1/p/6007801.html
Insert、update、delete属性
id:命名空间唯一标志符,作为Mybatis查找sql
parameterType:可选,限定传入参数的类名或者别名。未指定情况下,Mybatis可以通过TypeHandler推断具体传入语句的参数类型,默认值unset。
flushCache:是否清空本地缓存和二级缓存,默认值true。
timeout:等待数据库返回请求结果的秒数。默认unset
statementType:STATEMENT、PREPARED或CALLABLE的一个,分别对应Statement、PreparedStatement或CallableStatement,默认PREPARED
useGeneratedKeys:令Mybatis使用JDBC的getGeneratedKeys方法来获取由数据库内部生成的主键,默认false。
keyProperty:Mybatis会通过getGeneratedKeys的返回值或者通过insert语句的selectKey子元素设置他的键值,默认unset
keyColumn:(仅对insert和update有用)通过生成的键值设置表中的列名,这个设置仅在某些数据库(如PostgreSQL)是必须的,当主键不是表中的第一列的时候需要设置。多个生成的列,可以用逗号分隔属性名层列表。
databaseId:如果配置databaseIdProvider,Mybatis会加载所有的不带databaseId或匹配当前databaseId的语句
Insert
Mysql:
mysql支持自增主键,自增主键值的获取,mybatis也是利用statement.getGenreatedKeys();
useGeneratedKeys="true";使用自增主键获取主键值策略,keyProperty;指定对应的主键属性。databaseId指定数据库是mysql。
<insert id="addEmp" parameterType="com.mybatis.bean.Employee"
useGeneratedKeys="true" keyProperty="id" databaseId="mysql">
insert into tbl_employee(last_name,email,gender)
values(#{lastName},#{email},#{gender})
</insert>
Oracle:
Oracle不支持自增,每次插入的数据的主键是从序列中拿到的值;
<insert id="addEmp" databaseId="oracle">
<selectKey keyProperty="id" order="BEFORE" resultType="Integer">
<!-- 编写查询主键的sql语句 -->
select EMPLOYEES_SEQ.nextval from dual
</selectKey>
<!-- 插入时的主键是从序列中拿到的 -->
<!-- BEFORE:-->
insert into employees(EMPLOYEE_ID,LAST_NAME,EMAIL)
values(#{id},#{lastName},#{email<!-- ,jdbcType=NULL -->})
</insert>
语句步骤:
1 查询序列MPLOYEES_SEQ下一个序列值。
2 将序列值赋值给id属性。
3 进行插入操作。
selectKey
keyProperty:查出的主键值封装给javaBean的哪个属性
order:BEFORE当前sql在插入sql之前运行
AFTER当前sql在插入sql之后运行
resultType:查出的数据的返回值类型
statementType:STATEMENT、PREPARED或CALLABLE
BEFORE运行顺序:
先运行selectKey查询id的sql;查出id值封装给javaBean的id属性
在运行插入的sql;就可以取出id属性对应的值
AFTER运行顺序:
先运行插入的sql(从序列中取出新值作为id);
再运行selectKey查询id的sql;
上面AFTER例子(不建议):
这种方式下,在高并发下,AFTER下获取的currval值不准确。
<insert id="addEmp" databaseId="oracle">
<selectKey keyProperty="id" order="AFTER" resultType="Integer">
<!-- 编写查询主键的sql语句 -->
select EMPLOYEES_SEQ.currval from dual
</selectKey>
<!-- 插入时的主键是从序列中拿到的 -->
<!-- BEFORE:-->
insert into employees(EMPLOYEE_ID,LAST_NAME,EMAIL)
values(EMPLOYEES_SEQ.nextval,#{lastName},#{email<!-- ,jdbcType=NULL -->})
</insert>
select
常用参数
Id:唯一标识符。
parameterType:参数类型。MyBatis可以根据TypeHandler自动推断
resultType:返回值类型(别名或者全类名,如果返回的是集合,定义集合中元素的类型。不能和resultMap同时使用)
resultMap:外部resultMap命名引用,和resultType不能同时使用。
<select id="getDeptById" resultType="com.mybatis.bean.Department">
select id,dept_name departmentName from tbl_dept where id=#{id}
</select>
update
<update id="updateEmp">
update tbl_employee
set last_name=#{lastName},email=#{email},gender=#{gender}
where id=#{id}
</update>
delete
<delete id="deleteEmpById">
delete from tbl_employee where id=#{id}
</delete>
resultMap
constructor:类在实例化时, 用来注入结果到构造方法中.
idArg ID参数
Arg 注入到构造方法的一个普通结果
id:id结果
result:普通结果
association:一个复杂的类型关联;
collection:复杂类型的集
discriminator:使用结果值来决定使用哪个结果映射
普通对象映射:
public class Employee {
private Integer id;
private String lastName;
private String email;
private String gender;
}
<resultMap type="bean.Employee" id="MySimpleEmp">
<!--指定主键列的封装规则: id定义主键会底层有优化;
column:指定哪一列 property:指定对应的javaBean属性 -->
<id column="id" property="id"/>
<!-- 定义普通列封装规则 -->
<result column="last_name" property="lastName"/>
<!-- 其他不指定的列会自动封装:我们只要写resultMap就把全部的映射规则都写上。 -->
<result column="email" property="email"/>
<result column="gender" property="gender"/>
</resultMap>
含级联属性对象映射:
public class Employee {
private Integer id;
private String lastName;
private String email;
private String gender;
private Department dept;
}
普通方式定义:
<resultMap type="bean.Employee" id="MyDifEmp">
<id column="id" property="id"/>
<result column="last_name" property="lastName"/>
<result column="gender" property="gender"/>
<result column="did" property="dept.id"/>
<result column="dept_name" property="dept.departmentName"/>
</resultMap>
association定义关联的单个对象的封装规则:
<resultMap type="bean.Employee" id="MyDifEmp2">
<id column="id" property="id"/>
<result column="last_name" property="lastName"/>
<result column="gender" property="gender"/>
<!-- association可以指定联合的javaBean对象
property="dept":指定哪个属性是联合的对象
javaType:指定这个属性对象的类型-->
<association property="dept" javaType="com.mybatis.bean.Department">
<id column="did" property="id"/>
<result column="dept_name" property="departmentName"/>
</association>
</resultMap>
collection嵌套结果集查询:
public class Department {
private Integer id;
private String departmentName;
private List<Employee> emps;
}
<!--嵌套结果集的方式,使用collection标签定义关联的集合类型的属性封装规则 -->
<resultMap type="bean.Department" id="MyDept">
<id column="did" property="id"/>
<result column="dept_name" property="departmentName"/>
<!--collection定义关联集合类型的属性的封装规则
ofType:指定集合里面元素的类型-->
<collection property="emps" ofType="bean.Employee">
<!-- 定义这个集合中元素的封装规则 -->
<id column="eid" property="id"/>
<result column="last_name" property="lastName"/>
<result column="email" property="email"/>
<result column="gender" property="gender"/>
</collection>
</resultMap>
<select id="getDeptByIdPlus" resultMap="MyDept">
SELECT d.id did,d.dept_name dept_name,
e.id eid,e.last_name last_name,e.email email,e.gender gender
FROM tbl_dept d
LEFT JOIN tbl_employee e
ON d.id=e.d_id
WHERE d.id=#{id}
</select>
分段查询嵌套结果集
<resultMap type="bean.Department" id="MyDeptStep">
<id column="id" property="id"/>
<id column="dept_name" property="departmentName"/>
<collection property="emps"
select="dao.EmployeeMapperPlus.getEmpsByDeptId"
column="{deptId=id}" fetchType="lazy"></collection>
</resultMap>
<select id="getDeptByIdStep" resultMap="MyDeptStep">
select id,dept_name from tbl_dept where id=#{id}
</select>
fetchType=eager/lazy 立即加载(eager)或者延迟加载(lazy) 可以覆盖全局setting设置
MyBatis-动态SQL
if:判断
<select id="findActiveBlogWithTitleLike"
resultType="Blog">
SELECT * FROM BLOG
WHERE
<if test="title != null">
title like #{title}
</if>
<if test="state != null">
AND state = #{state}
</if>
</select>
where
在多个if语句的时候可能会出现:
SELECT * FROM BLOG WHERE AND title like ‘someTitle’
SELECT * FROM BLOG WHERE
严谨的方法:
<select id="findActiveBlogWithTitleLike"
resultType="Blog">
SELECT * FROM BLOG
<where>
<if test="title != null">
title like #{title}
</if>
<if test="state != null">
AND state = #{state}
</if></where>
</select>
where 元素只会在至少有一个子元素的条件返回 SQL 子句的情况下才去插入“WHERE”子句。而且,若语句的开头为“AND”或“OR”,where 元素也会将它们去除。
choose (when, otherwise)
<select id="findActiveBlogLike" resultType="Blog">
SELECT * FROM BLOG
<where>
<choose>
<when test="title != null">
title like #{title}
</when>
<when test="state != null">
state = #{state}
</when>
<otherwise>
featured = 1
</otherwise>
</choose>
</where>
</select>
trim
字符串的截取规则
prefix:前缀
prefixOverrides:前缀覆盖
suffix:后缀
suffixOverrides:后缀覆盖
<select id="getEmpsByConditionTrim" resultType="bean.Employee">
select * from tbl_employee
<trim prefix="where" suffixOverrides="and">
<if test="id!=null">
id=#{id} and
</if>
<if test="lastName!=null && lastName!=""">
last_name like #{lastName} and
</if>
<if test="email!=null and email.trim()!=""">
email=#{email} and
</if>
<!-- ognl会进行字符串与数字的转换判断 "0"==0 -->
<if test="gender==0 or gender==1">
gender=#{gender}
</if>
</trim>
</select>
set
set 元素会动态前置 SET 关键字,同时也会删掉无关的逗号,因为用了条件语句之后很可能就会在生成的 SQL 语句的后面留下这些逗号。
<update id="updateAuthorIfNecessary">
update Author
<set>
<if test="username != null">username=#{username},</if>
<if test="password != null">password=#{password},</if>
<if test="email != null">email=#{email},</if>
<if test="bio != null">bio=#{bio}</if>
</set>
where id=#{id}
</update>
foreach
对一个collection集合进行遍历
<select id="selectPostIn" resultType="domain.blog.Post">
SELECT *
FROM POST P
WHERE ID in
<foreach item="item" index="index" collection="list"
open="(" separator="," close=")">
#{item}
</foreach>
</select>
声明可以在元素体内使用的集合项(item)和索引(index)变量。它也允许你指定开头open与结尾close的字符串以及在迭代结果之间放置分隔符。
bind
bind 元素可以从 OGNL 表达式中创建一个变量并将其绑定到上下文。
<select id="selectBlogsLike" resultType="Blog">
<bind name="pattern" value="'%' + _parameter.getTitle() + '%'" />
SELECT * FROM BLOG
WHERE title LIKE #{pattern}
</select>
多数据库支持
一个配置了“_databaseId”变量的 databaseIdProvider 可用于动态代码中,这样就可以根据不同的数据库厂商构建特定的语句。
<insert id="insert">
<selectKey keyProperty="id" resultType="int" order="BEFORE">
<if test="_databaseId == 'oracle'">
select seq_users.nextval from dual
</if>
<if test="_databaseId == 'db2'">
select nextval for seq_users from sysibm.sysdummy1"
</if>
</selectKey>
insert into users values (#{id}, #{name})
</insert>
OGNL(Object Graph Navigation Language )对象图导航语言
访问对象属性:person.name
调用方法:person.getName()
调用静态属性/方法:@java.lang.Math@PI
@java.util.UUID@randomUUID()
调用构造方法:new com.bean.Person(‘admin’).name
运算符:+,-*,/,%
逻辑运算符:in,not in,>,>=,<,<=,==,!=
提示:xml中特殊符号如”,>,<等这些都需要使用转义字符