MyBatis-复习篇

南笙酒味 提交于 2020-02-12 11:31:36

 

 
1.Mybatis工作流程

2.封装方法
SqlSessionFactoryUtils 里面的openSession
 
3.采用映射方法实现接口查询
UserMapper userMapper =session.getMapper(UserMapper.class);
List<User> userList =userMapper.getList();

 

4.接口配置文件 讲述增删改查(源代码)

(1)模糊查询的方法

(2)Mapper生命周期

5.pojo实体类中的字段和数据库中的字段不一样
(1)换一个别名
 

(2)、使用返回类型 resultMap
结果集映射
只需要映射需要修改的

 
6.Mybatis分页查询
(1).通过UserMapper.xml配置来实现
UserMapper.xml配置:
<resultMap id="LimitType" type="User">
    <result column="address" property="addes"/>
</resultMap>
<select id="getUserByLimit" parameterType="map" resultMap="LimitType">
    select * from user limit #{startIndex},#{pageSize}
</select>

测试类:

@Test
public void getUserByLimit(){
    SqlSession sqlSession = SqlSessionFactoryUtil.openSqlSession();
    UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
    Map map = new HashMap<String , Integer>();
    map.put("startIndex", 0);
    map.put("pageSize",2);
    List <User> list=userMapper.getUserByLimit(map);
    for (User s :list) {
        System.out.println(s);
    }
    sqlSession.close();
}

 

(2).通过Java代码实现分页 (不建议使用,但是快)
RowBounds rowBoun RowBounds rowBounds= new RowBounds(0,5);
List<User> list = sqlSession.selectList("com.ybzn.dao.UserMapper.getUserByLimit", null,rowBounds);

 

两行代码即可查询出分页,在UserMapper.xml配置中:仅需如下
<resultMap id="LimitType" type="User">
    <result column="address" property="addes"/>
</resultMap>
<select id="getUserByLimit" parameterType="map" resultMap="LimitType">
    select * from user 
</select>

(3)分页可以使用其他方法

 
7.按照查询嵌套处理(多对一复杂查询)
(1).通过子查询来完成
StudentMapper.xml配置
思路:
1.查询所有学生信息
2.根据查询出来的学生tid,寻找对应的老师! 类似于子查询
  <select id="getStudent" resultMap="StudentTeacher">
        select * from new_user;
  </select>
    <resultMap id="StudentTeacher" type="Student">
        <result column="id" property="id"></result>
        <result column="stuname" property="stuname"></result>
        <result column="id" property="id"></result>
        <!--    复杂的属性 需要单独处理    对象:association     集合:collection     -->
        <association property="teacher" column="tid"
                             javaType="Teacher" select="getTeacher"/>
    </resultMap>
    <select id="getTeacher" resultType="Teacher">
        select * from teacher where tid=#{tid}
    </select>
(2).按照结果嵌套查询--联表查询
类似于联表查询 多对一
StudentMapper.xml
<select id="getStudent2" resultMap="StudentTeacher2">
    select s.id sid,s.stuname sname,s.stuclass sclass,t.teaname tname from new_user s,teacher t where s.tid=t.tid;
</select>
<resultMap id="StudentTeacher2" type="Student">
    <result column="sid" property="id"></result>
    <result column="sname" property="stuname"></result>
    <result column="sclass" property="stuclass"></result>
    <association property="teacher" javaType="Teacher">
        <result property="teaname" column="tname"></result>
    </association>
      //其中association 里面的property对应Pojo中的字段名 
     //javaType 对应pojo中的字段名类型
     //配置中所有property 表示数据库中的字段名,Column表示程序中的别名或者字段名
</resultMap>

 

POJO下的:Student.java
 
@Data public class Student { 
private int id; private String stuname;
 private String stuclass; 
private Teacher teacher; }  

 

8.类似于联表查询 一对多
 1 <!--按照结果来嵌套查询-->
 2 <select id="getTeacher" resultMap="TeacherStudent">
 3     select s.id  sid, s.stuname sname, s.stuclass sclass, t.teaname tname , t.tid tid
 4     from new_user s , teacher t
 5     where s.tid = t.tid and t.tid = #{tid};
 6 </select>
 7 <resultMap id="TeacherStudent" type="Teacher">
 8     <result column="tname" property="teaname"></result>
 9     <!--    复杂的属性 需要单独处理    对象:association     集合:collection
10             javaType="" 指定属性的类型
11             集合中的泛型信息 ,我们可以通过ofType获取
12       -->
13     <collection property="student" ofType="Student">
14         <result property="id" column="sid"></result>
15         <result property="stuname" column="sname"></result>
16         <result property="tid" column="tid"></result>
17         <result property="stuclass" column="sclass"></result>
18     </collection>
19 </resultMap>

 

 
POJO下的:Teacher.java
@Data
public class Teacher{
  private int tid;
    private String teaname;
    private List<Student> student;
    } 
联表查询 小结
1. 关联:- association 【多对一】
2. 集合: -collection 【一对多】
3. javaType && ofType
  • javaType 用来指定实体类中属性的类
  • ofType 用来指定映射到LIst《ofType=""》或者集合中的pojo类型,泛型中的约束类型
9.动态SQL查询
  • 利用IF 来完成查询
BlogMapper.xml 配置 通过传递map 的方式来完成查询
<select id="queryBlogIF" parameterType="map" resultType="blog">
    select * from blog 
    <where>
    <if test="title != null">
            and title = #{title}
    </if>
    <if test="author != null">
            and author = #{author}
    </if>
    </where>
</select>
  • 利用Choose来完成查询
<select id="queryBlogChoose" parameterType="map" resultType="blog">
    select * from blog
    <where>
        <choose>
            <when test="title !=null">
                title=#{title}
            </when>
            <when test="author != null">
                and author=#{author}
            </when>
            <otherwise>
               and views=#{views}
            </otherwise>
        </choose>
    </where>
</select>

 

  • 利用Set来完成更新操作
<update id="updateBlog" parameterType="map">
    update  blog
    <set>
        <if test="title !=null">
            title = #{title},
        </if>
        <if test="author !=null ">
            author = #{author},
        </if>
    </set>
    where id= #{id}
</update>
  • SQL片段
有时候可能某个 sql 语句我们用的特别多,为了增加代码的重用性,简化代码,我们需要将这些代码抽取出来,然后使用时直接调用。
提取SQL片段:
<sql id="if-title-author">
    <if test="title != null">
        title = #{title}
    </if>
    <if test="author != null">
        and author = #{author}
    </if>
</sql>

 

引用SQL片段:
<select id="queryBlogIf" parameterType="map" resultType="blog">
    select * from blog
    <where>
        <!-- 引用 sql 片段,如果refid 指定的不在本文件中,那么需要在前面加上 namespace -->
        <include refid="if-title-author"></include>
        <!-- 在这里还可以引用其他的 sql 片段 -->
    </where>
</select>

 

注意:
①、最好基于 单表来定义 sql 片段,提高片段的可重用性
②、在 sql 片段中不要包括 where
  • 利用Foreach 完成动态SQL的拼接
BlogMapper.xml 配置
   <!-- 传递一个万能的map, 这个Map可以存在一个集合-->
<select id="queryBlogForeach" parameterType="map" resultType="Blog">
    select * from blog
    <where>
        <foreach collection="ids" item="flagid"
        open="and (" close=")" separator="or">
            id=#{flagid}
        </foreach>
    </where>
</select>

 

测试 如下
@Test
public  void sqlSelect(){
    SqlSession session = SqlSessionFactoryUtil.openSqlSession();
    BlogMapper mapper = session.getMapper(BlogMapper.class);
    HashMap map = new HashMap();
    ArrayList <String> ids = new ArrayList <>();
    ids.add("1");
    ids.add("2");
    ids.add("3");
    ids.add("4");
    map.put("ids", ids);
    List <Blog> blogs = mapper.queryBlogForeach(map);
    for (Blog blog : blogs) {
        System.out.println(blog);
    }
}

 

10.二级缓存
二级缓存也叫全局缓存,一级缓存作用域太低了,所以诞生了二级缓存
  • 基于namespace级别的缓存,一个名称空间,对应一个二级缓存;
  • 工作机制
    • 一个会话查询一条数据,这个数据就会被放在当前会话的一级缓存中;
    • 如果当前会话关闭了,这个会话对应的一级缓存就没了;但是我们想要的是,会话关闭了,一级缓存中的数据被保存到二级缓存中;
    • 新的会话查询信息,就可以从二级缓存中获取内容;
    • 不同的mapper查出的数据会放在自己对应的缓存(map)中;
使用步骤
  1. 开启全局缓存 【mybatis-config.xml】
<setting name="cacheEnabled" value="true"/>

 

2.去每个mapper.xml中配置使用二级缓存,这个配置非常简单;【xxxMapper.xml】
<cache/>
<cache
  eviction="FIFO"
  flushInterval="60000"
  size="512"
  readOnly="true"/>

 

这个更高级的配置创建了一个 FIFO 缓存,每隔 60 秒刷新,最多可以存储结果对象或列表的 512 个引用,
注意:采用了二级缓存会出现序列化的问题
应该令POJO中的实体类 实现Serializable 接口
public class Blog implements Serializable {}

 

缓存工作流程图

结论
  • 只要开启了二级缓存,我们在同一个Mapper中的查询,可以在二级缓存中拿到数据
  • 查出的数据都会被默认先放在一级缓存中
  • 只有会话提交或者关闭以后,一级缓存中的数据才会转到二级缓存中
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!