#{ } 和 ${ } 取值的区别

  1. #{} : 是以预编译的形式,将参数设置到sql语句中,防止sql注入;
  2. ${} : 取出的值会直接拼接在sql语句中,会有安全问题;

resultMap 自定义结果

  • resultTyperesultMap 只能同时用一个
  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <!DOCTYPE mapper
  3. PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
  4. "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
  5. <mapper namespace="com.garcon.dao.StudentMapper">
  6. <!--自定义某个javaBean的封装规则
  7. type:自定义规则的Java类型
  8. id:唯一id方便引用
  9. -->
  10. <resultMap type="com.garcon.bean.Student" id="myStudent">
  11. <!--指定主键列的封装规则
  12. id定义主键会底层有优化
  13. column:指定哪一列
  14. property:指定对应的javaBean属性
  15. -->
  16. <id column="sid" property="sid"/>
  17. <!-- 定义普通列封装规则 -->
  18. <result column="last_name" property="lastName"/>
  19. <!-- 其他不指定的列会自动封装:我们只要写resultMap就把全部的映射规则都写上。 -->
  20. <result column="gender" property="gender"/>
  21. <result column="hobby" property="hobby"/>
  22. </resultMap>
  23. <!-- resultMap:自定义结果集映射规则; -->
  24. <select id="getStudentById" resultMap="myStudent">
  25. select * from student where sid=#{sid}
  26. </select>
  27. </mapper>

关联查询

  • 自定义 关联查询 结果集类型
  • 查询 学生信息 的时候把对应的 班级信息 也查询出来
  • Student.java 学生信息
  1. package com.garcon.bean;
  2. public class Student {
  3. private Integer sid;
  4. private String lastName;
  5. private String gender;
  6. private String hobby;
  7. private Sclass sclass;//班级信息
  8. ...
  9. }
  • Sclass.java 班级信息
  1. package com.garcon.bean;
  2. public class Sclass {
  3. private Integer cid;//班级id
  4. private String cName;//班级名称
  5. ...
  6. }
  • StudentMapper.java 接口
  1. package com.garcon.dao;
  2. public interface StudentMapper {
  3. //以sid查询学生信息
  4. public Student getStudentById(Integer sid);
  5. }
  • StudentMapper.xml 映射文件—— resultMap 级联属性
  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <!DOCTYPE mapper
  3. PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
  4. "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
  5. <mapper namespace="com.garcon.dao.StudentMapper">
  6. <!--联合查询:级联属性封装结果集 -->
  7. <resultMap type="com.garcon.bean.Student" id="mystudent">
  8. <id column="sid" property="sid"/>
  9. <result column="last_name" property="lastName"/>
  10. <result column="gender" property="gender"/>
  11. <result column="hobby" property="hobby"/>
  12. <!--关联列用级联属性-->
  13. <result column="cid" property="sclass.cid"/>
  14. <result column="cname" property="sclass.name"/>
  15. </resultMap>
  16. <!--级联查询-->
  17. <select id="getStudentById" resultMap="myStudent">
  18. SELECT
  19. s.sid,
  20. s.last_name,
  21. s.gender,
  22. s.hobby,
  23. c.cid,
  24. c.cname
  25. FROME
  26. student s,
  27. sclass c
  28. WHERE
  29. s.sid=c.cid
  30. AND
  31. sid=#{sid}
  32. </select>
  33. </mapper>

或 以下

  • StudentMapper.xml 映射文件—— resultMapassociation 属性
  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <!DOCTYPE mapper
  3. PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
  4. "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
  5. <mapper namespace="com.garcon.dao.StudentMapper">
  6. <!--使用association定义关联的单个对象的封装规则-->
  7. <resultMap type="com.garcon.bean.Student" id="myStudent">
  8. <id column="sid" property="sid"/>
  9. <result column="last_name" property="lastName"/>
  10. <result column="gender" property="gender"/>
  11. <result column="hobby" property="hobby"/>
  12. <!--
  13. association:可以指定联合的javaBean对象
  14. property="sclass":指定哪个属性是联合的对象
  15. javaType:指定这个属性对象的类型[不能省略]
  16. -->
  17. <association property="sclass" javaType="com.garcon.bean.Sclass">
  18. <id column="cid" property="cid"/>
  19. <result column="cname" property="cname"/>
  20. </association>
  21. </resultMap>
  22. <!--关联查询-->
  23. <select id="getStudentById" resultMap="myStudent">
  24. SELECT
  25. s.sid,
  26. s.last_name,
  27. s.gender,
  28. s.hobby,
  29. c.cid,
  30. c.cname
  31. FROME
  32. student s,
  33. sclass c
  34. WHERE
  35. s.sid=c.cid
  36. AND
  37. sid=#{sid}
  38. </select>
  39. </mapper>

关联查询 collection

  • 查询班级信息的同时查出班级所对应的学生信息

  • Student.java 学生类
  1. package com.garcon.bean;
  2. public class Student {
  3. private Integer sid;
  4. private String lastName;
  5. private String gender;
  6. private String hobby;
  7. private Sclass sclass;//班级信息
  8. ...
  9. }
  • Sclass.java 班级类
  1. package com.garcon.bean;
  2. public class Sclass {
  3. private Integer cid;//班级id
  4. private String cName;//班级名称
  5. private List<Student> students;
  6. ...
  7. }
  • SclassMapper.java 班级接口
  1. package com.garcon.dao;
  2. public interface SclassMapper {
  3. //以班级id查询班级
  4. public Sclass getSclassById(Integer cid);
  5. }
  • sclassMapper.xml 班级SQL映射文件
  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <!DOCTYPE mapper
  3. PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
  4. "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
  5. <mapper namespace="com.garcon.dao.SclassMapper">
  6. <!--嵌套结果集的方式,使用collection标签定义关联的集合类型的属性封装规则 -->
  7. <resultMap type="com.garcon.bean.Sclass" id="Mysclass">
  8. <id column="cid" property="cid"/>
  9. <result column="cname" property="cName"/>
  10. <!--
  11. collection定义关联集合类型的属性的封装规则
  12. ofType:指定集合里面元素的类型
  13. -->
  14. <collection property="students" ofType="com.garcon.bean.Student">
  15. <!-- 定义这个集合中元素的封装规则 -->
  16. <id column="sid" property="sid"/>
  17. <result column="last_name" property="lastName"/>
  18. <result column="gender" property="gender"/>
  19. <result column="hobby" property="hobby"/>
  20. </collection>
  21. </resultMap>
  22. <select id="getSclassById" resultMap="Mysclass">
  23. SELECT
  24. s.sid,
  25. s.last_name,
  26. s.gender,
  27. s.hobyy,
  28. c.cid
  29. c.cname
  30. FROM
  31. student s
  32. LEFT JOIN
  33. sclass c
  34. ON
  35. s.cid=c.cid
  36. WHERE
  37. c.cid=#{cid}
  38. </select>
  39. </mapper>

分步查询 association

  • 先以学生的 学号 查询学生信息,再以 学生信息中的班级编号 查询班级信息
  • SclassMapper.java 班级接口
  1. package com.garcon.dao;
  2. public interface Sclass {
  3. //以班级id查询班级信息
  4. public Sclass getSclasstById(Integer cid);
  5. }
  • StudentMapper.java 学生接口
  1. package com.garcon.dao;
  2. public interface StudentMapper {
  3. //以sid查询学生信息
  4. public Student getStudentById(Integer sid);
  5. }
  • sclassMapper.xml 班级SQL映射文件
  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <!DOCTYPE mapper
  3. PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
  4. "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
  5. <mapper namespace="com.garcon.dao.SclassMapper">
  6. <!--以班级号查询班级信息-->
  7. <select id="getSclassById" resultType="com.garcon.bean.Sclass">
  8. SELECT * FROM sclass WHERE cid=#{cid}
  9. </select>
  10. </mapper>
  • studentMapper.xml 学生SQL映射文件
  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <!DOCTYPE mapper
  3. PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
  4. "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
  5. <mapper namespace="com.garcon.dao.StudentMapper">
  6. <!--
  7. 使用association进行分步查询:
  8. 1、先按照学生id查询学生工信息
  9. 2、根据查询学生信息中的cid值去班级表查出班级信息
  10. 3、班级设置到学生中;
  11. -->
  12. <resultMap type="com.garcon.bean.Student" id="Mystudent">
  13. <id column="sid" property="sid"/>
  14. <result column="last_name" property="lastName"/>
  15. <result column="gender" property="gender"/>
  16. <result column="hobby" property="hobby"/>
  17. <!--
  18. association:定义关联对象的封装规则
  19. select:表明当前属性是调用select指定的方法查出的结果
  20. column:指定将哪一列的值传给这个方法
  21. 流程:使用select指定的方法(传入column指定的这列参数的值)查出对象,并封装给property指定的属性
  22. -->
  23. <association property="dept"
  24. select="com.garcon.dao.SclassMapper.getSclassById"
  25. column="cid">
  26. </association>
  27. </resultMap>
  28. <select id="getStudentById" resultMap="Mystudent">
  29. SELECT * FROM student WHERE sid=#{sid}
  30. </select>
  31. </mapper>

分步查询 collection

  • 先以 班级编号 查询班级信息,再以 班级编号 查询班级的所有学生信息
  • SclassMapper.java 班级接口
  1. package com.garcon.dao;
  2. public interface Sclass {
  3. //以班级id查询班级信息
  4. public Sclass getSclasstById(Integer cid);
  5. }
  • StudentMapper.java 学生接口
  1. package com.garcon.dao;
  2. public interface StudentMapper {
  3. //以班级编号查询学生信息
  4. public List<Student> getStudentByClassId(Integer sid);
  5. }
  • sclassMapper.xml 班级SQL映射文件
  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <!DOCTYPE mapper
  3. PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
  4. "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
  5. <mapper namespace="com.garcon.dao.SclassMapper">
  6. <!-- collection:分段查询 -->
  7. <resultMap type="com.garcon.bean.Sclass" id="mySclass">
  8. <id column="cid" property="cid"/>
  9. <id column="cname" property="cName"/>
  10. <collection property="students"
  11. select="com.garcon.dao.StudentMapper.getStudentByClassId"
  12. column="cid" fetchType="lazy"></collection>
  13. </resultMap>
  14. <select id="getSclasstById" resultMap="mySclass">
  15. select cid,cName from sclass where cid=#{cid}
  16. </select>
  17. <!--
  18. 扩展:
  19. 多列的值传递过去:
  20. 将多列的值封装map传递;
  21. column="{key1=column1,key2=column2}"
  22. 如:
  23. <collection
  24. property=""
  25. select=""
  26. column="{key1=column1,key2=column2}"
  27. fetchType="lazy">
  28. </collection>
  29. fetchType="lazy":表示使用延迟加载;
  30. - lazy:延迟
  31. - eager:立即
  32. -->
  33. </mapper>
  • studentMapper.xml 学生SQL映射文件
  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <!DOCTYPE mapper
  3. PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
  4. "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
  5. <mapper namespace="com.garcon.dao.StudentMapper">
  6. <!--以班级编号查询所有学生-->
  7. <select id="getStudentById" resultType="com.garcon.bean.Student">
  8. SELECT * FROM student WHERE class_id=#{class_id}
  9. </select>
  10. </mapper>

分步查询 延迟加载

适用情况:假如查看学生信息的时候不加载班级信息,当需要查看学生的班级信息的时候再加载班级信息

  • 在分步查询的基础上,在mybatis的全局配置文件的settings设置项中添加如下设置即可
  1. <settings>
  2. <!--显示的指定每个我们需要更改的配置的值,即使他是默认的。防止版本更新带来的问题 -->
  3. <setting name="lazyLoadingEnabled" value="true"/>
  4. <setting name="aggressiveLazyLoading" value="false"/>
  5. </settings>

鉴别器-discriminator

鉴别器:mybatis可以使用discriminator判断某列的值,然后根据某列的值改变封装行为

  • 如果查出的是女生:就把班级信息查询出来,否则不查询;如果是男生,把last_name这一列的值赋值给 hobby;
  • studentMapper.xml
  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <!DOCTYPE mapper
  3. PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
  4. "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
  5. <mapper namespace="com.garcon.dao.StudentMapper">
  6. <!--
  7. 鉴别器:mybatis可以使用discriminator判断某列的值,然后根据某列的值改变封装行为
  8. 封装Student:
  9. 如果查出的是女生:就把班级信息查询出来,否则不查询;
  10. 如果是男生,把last_name这一列的值赋值给 hobby;
  11. -->
  12. <resultMap type="com.garcon.bean.Student" id="mystudent">
  13. <id column="sid" property="sid"/>
  14. <result column="last_name" property="lastName"/>
  15. <result column="gender" property="gender"/>
  16. <result column="hobby" property="hobby"/>
  17. <!--
  18. column:指定判定的列名
  19. javaType:列值对应的java类型
  20. -->
  21. <discriminator javaType="string" column="gender">
  22. <!--女生 resultType:指定封装的结果类型;不能缺少。/resultMap-->
  23. <case value="女" resultType="com.garcon.bean.Student">
  24. <association property="sclass"
  25. select="com.garcon.dao.SclassMapper.getSclasstById"
  26. column="class_id">
  27. </association>
  28. </case>
  29. <!--男生 ;如果是男生,把last_name这一列的值赋值给hobby; -->
  30. <case value="男" resultType="com.garcon.bean.Student">
  31. <id column="id" property="id"/>
  32. <result column="last_name" property="lastName"/>
  33. <result column="last_name" property="hobby"/>
  34. <result column="gender" property="gender"/>
  35. </case>
  36. </discriminator>
  37. </resultMap>
  • sclassMapper.xml
  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <!DOCTYPE mapper
  3. PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
  4. "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
  5. <mapper namespace="com.garcon.dao.SclassMapper">
  6. <!--以班级号查询班级信息-->
  7. <select id="getSclassById" resultType="com.garcon.bean.Sclass">
  8. SELECT * FROM sclass WHERE cid=#{cid}
  9. </select>
  10. </mapper>

动态SQL

if

  1. <!--test:判断表达式(OGNL)-->
  2. <if test=""></if>
  3. <!--
  4. 应用场境:按条件查询学生,
  5. 如果参数中有sid则查询条件带上sid
  6. 如果参数中有last_name则查询条件带上last_name
  7. 如果参数中有gender则查询条件带上gender
  8. -->
  9. <select id="getStudent" resultType="com.garcon.dao.StudentMapper">
  10. select * from student
  11. <!-- where -->
  12. <where>
  13. <if test="sid!=null">
  14. sid=#{sid}
  15. </if>
  16. <if test="lastName!=null AND lastName!=''">
  17. and last_name like #{lastName}
  18. </if>
  19. <if test="hobby!=null and hobby.trim()!=''">
  20. and hobby=#{hobby}
  21. </if>
  22. <!-- ognl会进行字符串与数字的转换判断 "0"==0 -->
  23. <if test="gender==0 or gender==1">
  24. and gender=#{gender}
  25. </if>
  26. </where>
  27. </select>

where

  • 去除查询条件中多余的第一个 andor
  1. <!--
  2. 检查以下sql语句
  3. -->
  4. <select id="getStudent" resultType="com.garcon.dao.StudentMapper">
  5. select * from student
  6. where
  7. <if test="sid!=null">
  8. sid=#{sid}
  9. </if>
  10. <if test="lastName!=null AND lastName!=''">
  11. and last_name like #{lastName}
  12. </if>
  13. </select>
  14. <!--
  15. 可以发现,当以上参数 sid 为空时,sql语句就变成了:
  16. select * from student where and last_name=?
  17. 多出的 and 语法错误;
  18. 解决以上情况可以加标签<where></where>:
  19. 把所有的<if></if>条件都放在<where></where>标签中,可以去除第一个 and 和 or 如下:
  20. -->
  21. <select id="getStudent" resultType="com.garcon.dao.StudentMapper">
  22. select * from student
  23. <where>
  24. <if test="sid!=null">
  25. sid=#{sid}
  26. </if>
  27. <if test="lastName!=null AND lastName!=''">
  28. and last_name like #{lastName}
  29. </if>
  30. </where>
  31. </select>

trim

  1. <!--
  2. 检查以下sql语句
  3. -->
  4. <select id="getStudent" resultType="com.garcon.dao.StudentMapper">
  5. select * from student
  6. where
  7. <if test="sid!=null">
  8. sid=#{sid} and
  9. </if>
  10. <if test="lastName!=null AND lastName!=''">
  11. last_name like #{lastName}
  12. </if>
  13. </select>
  14. <!--
  15. 可以发现,当以上参数 lastName 为空时,sql语句就变成了:
  16. select * from student where sid=? and
  17. 结尾多出的 and 语法错误;
  18. 解决以上情况可以加标签<trim></trim>:
  19. <trim prefix="" suffixOverrides="" suffix="" suffixOverrides=""></trim>
  20. 后面多出的and或者or where标签不能解决
  21. prefix="":前缀:trim标签体中是整个字符串拼串 后的结果。
  22. prefix给拼串后的整个字符串加一个前缀
  23. prefixOverrides="":
  24. 前缀覆盖: 去掉整个字符串前面多余的字符
  25. suffix="":后缀
  26. suffix给拼串后的整个字符串加一个后缀
  27. suffixOverrides=""
  28. 后缀覆盖:去掉整个字符串后面多余的字符
  29. 如下:
  30. -->
  31. <select id="getStudent" resultType="com.garcon.dao.StudentMapper">
  32. select * from student
  33. <trim prefix="where" suffixOverrides="and">
  34. <if test="sid!=null">
  35. sid=#{sid} and
  36. </if>
  37. <if test="lastName!=null AND lastName!=''">
  38. last_name like #{lastName}
  39. </if>
  40. </trim>
  41. </select>

choose

  1. <!--
  2. 使用场景:
  3. 如果参数中的id不为空就以id为条件查询,如果name不为空就已以name做查询条件
  4. 如下:
  5. -->
  6. <select id="getStudent" resultType="com.garcon.dao.StudentMapper">
  7. select * from student
  8. <where>
  9. <!-- 如果带了id就用id查,如果带了lastName就用lastName查;只会进入其中一个 -->
  10. <choose>
  11. <when test="id!=null">
  12. sid=#{sid}
  13. </when>
  14. <when test="lastName!=null">
  15. last_name like #{lastName}
  16. </when>
  17. <when test="hobby!=null">
  18. hobby = #{hobby}
  19. </when>
  20. <!--如果以上条件都不满足,使用如下条件-->
  21. <otherwise>
  22. gender = '女'
  23. </otherwise>
  24. </choose>
  25. </where>
  26. </select>

update-set

如果javaBean中哪个属性带了值就更新那个字段

  1. <update id="updateStudent">
  2. <!-- Set标签的使用 -->
  3. update student
  4. <set>
  5. <if test="lastName!=null">
  6. last_name=#{lastName},
  7. </if>
  8. <if test="hobby!=null">
  9. hobby=#{hobby},
  10. </if>
  11. <if test="gender!=null">
  12. gender=#{gender}
  13. </if>
  14. </set>
  15. where id=#{id}
  16. </update>

update-trim

  1. <update id="updateStudent">
  2. update student
  3. <trim prefix="set" suffixOverrides=",">
  4. <if test="lastName!=null">
  5. last_name=#{lastName},
  6. </if>
  7. <if test="email!=null">
  8. email=#{email},
  9. </if>
  10. <if test="gender!=null">
  11. gender=#{gender}
  12. </if>
  13. </trim>
  14. where id=#{id}
  15. </update>

select-foreach

  1. <select id="getStudent" resultType="com.garcon.bean.Student">
  2. select * from student
  3. <!--
  4. collection:指定要遍历的集合:
  5. list类型的参数会特殊处理封装在map中,map的key就叫list
  6. item:将当前遍历出的元素赋值给指定的变量
  7. separator:每个元素之间的分隔符
  8. open:遍历出所有结果拼接一个开始的字符
  9. close:遍历出所有结果拼接一个结束的字符
  10. index:索引。遍历list的时候是index就是索引,item就是当前值
  11. 遍历map的时候index表示的就是map的key,item就是map的值
  12. #{变量名}就能取出变量的值也就是当前遍历出的元素
  13. -->
  14. <foreach collection="ids" item="item_id" separator=","
  15. open="where id in(" close=")">
  16. #{item_id}
  17. </foreach>
  18. </select>

insert-foreach

批量插入

  1. <!--
  2. MySQL下:
  3. 第一种方法
  4. 可以foreach遍历 mysql支持values(),(),()语法-->
  5. <insert id="addStudents">
  6. insert into student(last_name,gender,hobby,class_id)
  7. values
  8. <foreach collection="students" item="student" separator=",">
  9. (#{student.lastName},#{student.gender},#{student.hobby},#{student.sclass.cid})
  10. </foreach>
  11. </insert>
  12. <!--
  13. 第二种方法
  14. 这种方式需要数据库连接属性allowMultiQueries=true;
  15. 这种分号分隔多个sql可以用于其他的批量操作(删除,修改) -->
  16. <insert id="addEmps">
  17. <foreach collection="emps" item="emp" separator=";">
  18. insert into student(last_name,gender,hobby,class_id)
  19. values((#{student.lastName},#{student.gender},#{student.hobby},#{student.sclass.cid})
  20. </foreach>
  21. </insert>
  22. <!--
  23. Oracle数据库批量保存:
  24. Oracle不支持values(),(),()
  25. Oracle支持的批量方式
  26. 1、多个insert放在begin - end里面
  27. begin
  28. insert into employees(employee_id,last_name,email)
  29. values(employees_seq.nextval,'test_001','test_001@atguigu.com');
  30. insert into employees(employee_id,last_name,email)
  31. values(employees_seq.nextval,'test_002','test_002@atguigu.com');
  32. end;
  33. 2、利用中间表:
  34. insert into employees(employee_id,last_name,email)
  35. select employees_seq.nextval,lastName,email from(
  36. select 'test_a_01' lastName,'test_a_e01' email from dual
  37. union
  38. select 'test_a_02' lastName,'test_a_e02' email from dual
  39. union
  40. select 'test_a_03' lastName,'test_a_e03' email from dual
  41. )
  42. oracle第一种批量方式
  43. -->
  44. <insert id="addEmps" databaseId="oracle">
  45. <foreach collection="emps" item="emp" open="begin" close="end;">
  46. insert into employees(employee_id,last_name,email)
  47. values(employees_seq.nextval,#{emp.lastName},#{emp.email});
  48. </foreach>
  49. </insert>
  50. <!-- oracle第二种批量方式 -->
  51. <insert id="addEmps" databaseId="oracle">
  52. insert into employees(employee_id,last_name,email)
  53. <foreach collection="emps" item="emp" separator="union"
  54. open="select employees_seq.nextval,lastName,email from("
  55. close=")">
  56. select #{emp.lastName} lastName,#{emp.email} email from dual
  57. </foreach>
  58. </insert>

获取自增主键的值

方式一 :
使用insert标签的属性useGeneratedKeys="true" keyProperty="id"

  1. <insert id="addUser" useGeneratedKeys="true" keyProperty="id">
  2. insert into user(username,password,email) values(#{username},#{password},#{email})
  3. </insert>

方式二 : 插入时先查询将要插入数据的自增id值

  1. <insert id="addUser" useGeneratedKeys="true" keyProperty="id">
  2. <selectKey order="AFTER" keyProperty="id" resultType="int">
  3. select last_insert_id()
  4. </selectKey>
  5. insert into user(username,password,email) values(#{username},#{password},#{email})
  6. </insert>

参数处理

单个参数

可以接受基本类型,对象类型,集合类型的值。这种情况 MyBatis可直接使用这个参数,不需要经过任何处理。

多个参数

任意多个参数,都会被MyBatis重新包装成一个Map传入。Map的key是param1,param2,0,1…,值就是参数的值。

命名参数

为参数使用@Param起一个名字,MyBatis就会将这些参数封装进map中,key就是我们自己指定的名字

POJO

当这些参数属于我们业务POJO时,我们直接传递POJO

Map

我们也可以封装多个参数为map,直接传递

注意 : 当参数是一个Connection , List , Array数组时, 参数会封装成一个Map , key值为 : connection , list , array .

缓存机制

MyBatis 包含一个非常强大的查询缓存特性, 它可以非常方便地配置和定制。缓存可以极大的提升查询效率。

MyBatis系统中默认定义了两级缓存。

一级缓存 和 二级缓存。

  1. 默认情况下,只有一级缓存(SqlSession级别的缓存, 也称为本地缓存)开启。
  2. 二级缓存需要手动开启和配置,他是基于namespace级别的缓存。
  3. 为了提高扩展性。MyBatis定义了缓存接口Cache。我们可以通过实现Cache接口来自定义二级缓存

一级缓存

  • 一级缓存(local cache), 即本地缓存, 作用域默认 为sqlSession。当 Session flush 或 close 后, 该Session 中的所有 Cache 将被清空。
  • 本地缓存不能被关闭, 但可以调用 clearCache() 来清空本地缓存, 或者改变缓存的作用域.
  • 在mybatis3.1之后, 可以配置本地缓存的作用域. 在 mybatis.xml 中配置

一级缓存失效情况

同一次会话期间只要查询过的数据都会保存在当 前SqlSession的一个Map中

• key:hashCode+查询的SqlId+编写的sql查询语句+参数

一级缓存失效的四种情况

  1. 不同的SqlSession对应不同的一级缓存
  2. 同一个SqlSession但是查询条件不同
  3. 同一个SqlSession两次查询期间执行了任何一次增 删改操作
  4. 同一个SqlSession两次查询期间手动清空了缓存

二级缓存(second level cache),全局作用域缓存

  • 二级缓存默认不开启,需要手动配置
  • MyBatis提供二级缓存的接口以及实现,缓存实现要求 POJO实现Serializable接口
  • 二级缓存在 SqlSession 关闭或提交之后才会生效

使用步骤

  1. 全局配置文件中开启二级缓存
  1. <setting name="cacheEnabled" value="true"/>
  1. 在需要使用二级缓存的映射文件处使用cache配置缓存
  1. <cache type="org.mybatis.caches.ehcache.EhcacheCache"></cache>
  2. <!-- <cache eviction="FIFO" flushInterval="60000" readOnly="false" size="1024"></cache> -->
  3. <!--
  4. eviction:缓存的回收策略:
  5. • LRU – 最近最少使用的:移除最长时间不被使用的对象。
  6. • FIFO – 先进先出:按对象进入缓存的顺序来移除它们。
  7. • SOFT – 软引用:移除基于垃圾回收器状态和软引用规则的对象。
  8. • WEAK – 弱引用:更积极地移除基于垃圾收集器状态和弱引用规则的对象。
  9. • 默认的是 LRU。
  10. flushInterval:缓存刷新间隔
  11. 缓存多长时间清空一次,默认不清空,设置一个毫秒值
  12. readOnly:是否只读:
  13. true:只读;mybatis认为所有从缓存中获取数据的操作都是只读操作,不会修改数据。
  14. mybatis为了加快获取速度,直接就会将数据在缓存中的引用交给用户。不安全,速度快
  15. false:非只读:mybatis觉得获取的数据可能会被修改。
  16. mybatis会利用序列化&反序列的技术克隆一份新的数据给你。安全,速度慢
  17. size:缓存存放多少元素;
  18. type="":指定自定义缓存的全类名;
  19. 实现Cache接口即可;
  20. -->
  1. 注意:POJO需要实现Serializable接口

缓存相关设置

  1. 全局setting的cacheEnable:– 配置二级缓存的开关。一级缓存一直是打开的。
  2. select标签的useCache属性: – 配置这个select是否使用二级缓存。一级缓存一直是使用的
  3. sql标签的flushCache属性: – 增删改默认flushCache=true。sql执行以后,会同时清空一级和二级缓存。 查询默认flushCache=false。
  4. sqlSession.clearCache(): – 只是用来清除一级缓存。
  5. 当在某一个作用域 (一级缓存Session/二级缓存 Namespaces) 进行了 C/U/D 操作后,默认该作用域下所有 select 中的缓存将被clear。

第三方缓存整合

  • EhCache 是一个纯Java的进程内缓存框架,具有快速、精 干等特点,是Hibernate中默认的CacheProvider。
  • MyBatis定义了Cache接口方便我们进行自定义扩展。

步骤:

  1. 导入ehcache包,以及整合包,日志包
    1. ehcache-core-2.6.8.jar
    2. mybatis-ehcache-1.0.3.jar
    3. slf4j-api-1.6.1.jar
    4. slf4j-log4j12-1.6.2.jar
  2. 编写ehcache.xml配置文件
  3. 配置cache标签
  1. <ehcache type="org.mybatis.caches.ehcache.EhcacheCache">

参照缓存:若想在命名空间中共享相同的缓存配置和实例。 可以使用 cache-ref 元素来引用另外一个缓存。