MyBatis-快速入门

               博客目录

1.Mybatis工作流程
2.封装方法
3.采用映射方法实现接口查询
4.接口配置文件 讲述增删改查(源代码)
(1)模糊查询的方法
(2)Mapper生命周期
5.pojo实体类中的字段和数据库中的字段不一样
(1)换一个别名
(2)、使用返回类型 resultMap
6.Mybatis分页查询
(1).通过UserMapper.xml配置来实现,UserMapper.xml配置:
(2).通过Java代码实现分页 (不建议使用,但是快)
(3)分页可以使用其他方法
7.按照查询嵌套处理(多对一复杂查询)
(1).通过子查询来完成
(2).按照结果嵌套查询--联表查询
8.类似于联表查询 一对多
联表查询 小结
10.二级缓存
注意:采用了二级缓存会出现序列化的问题
缓存工作流程图
结论
 
1.Mybatis工作流程
2.封装方法
SqlSessionFactoryUtils 里面的openSession
 
 1 public class SqlSessionFactoryUtil {
 2     //创建SqlSessionFactory对象
 3     private static SqlSessionFactory sqlSessionFactory =null;
 4     //类线程死锁
 5     private static final Class CLASS_LOCK = SqlSessionFactoryUtil.class;
 6 
 7     /**
 8      * 私有化构造参数
 9      */
10     private SqlSessionFactoryUtil(){
11     }
12 
13     /**
14      * @return
15      * 单例模式,构造函数要私有化,并且需要用线程锁住,保证所有对象都使用一个SqlSessionFactory
16      */
17     public static SqlSessionFactory initSqlSessionFactory() {
18         String resource ="mybatis-config.xml";
19         InputStream inputStream = null;
20         try{
21             inputStream = Resources.getResourceAsStream(resource);
22         }catch(IOException ex) {
23             Logger.getLogger(SqlSessionFactoryUtil.class.getName()).log(Level.SEVERE,
24                     null,ex);
25         }
26         synchronized(CLASS_LOCK) {
27             if(sqlSessionFactory==null) {
28                 sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
29             }
30         }
31         return sqlSessionFactory;
32     }
33 
34     public static SqlSession openSqlSession() {
35         if(sqlSessionFactory==null) {
36             initSqlSessionFactory();
37         }
38         return sqlSessionFactory.openSession();
39     }
40 }
3.采用映射方法实现接口查询
UserMapper userMapper =session.getMapper(UserMapper.class);
List<User> userList =userMapper.getList();
4.接口配置文件 讲述增删改查(源代码)
(1)模糊查询的方法
 <!--  模糊查询 需要:同时满足 3 个参数,不然失败,所以需要动态SQL方法-->
    <select id="selectByMap" parameterType="map" resultType="User">
        select * from user
                        where sex=#{sex} and
                        address like concat("%",#{address},"%") and
                        username like concat("%",#{username},"%d")
    </select>
<!--    改进版的模糊查询-->
        <select id="selectByMap1" parameterType="map" resultType="user">
            select * from user
                        <where>
                            <if test="sex !=null and sex !=''">sex=#{sex}</if>
                            <if test="address !=null and address !=''">address=#{address}</if>
                            <if test="username !=null and username !=''">username=#{username}</if>
                        </where>
        </select>
(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中的查询,可以在二级缓存中拿到数据
  • 查出的数据都会被默认先放在一级缓存中
  • 只有会话提交或者关闭以后,一级缓存中的数据才会转到二级缓存中

猜你喜欢

转载自www.cnblogs.com/blogger-Li/p/12298299.html