千家信息网

MyBatis的知识点有哪些

发表于:2024-11-29 作者:千家信息网编辑
千家信息网最后更新 2024年11月29日,这篇文章将为大家详细讲解有关MyBatis的知识点有哪些,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。4.1 注解模式开发初期的 MyBatis 是一个 XML 驱
千家信息网最后更新 2024年11月29日MyBatis的知识点有哪些

这篇文章将为大家详细讲解有关MyBatis的知识点有哪些,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。


4.1 注解模式开发

初期的 MyBatis 是一个 XML 驱动的框架。配置信息是基于 XML 的,映射语句也是定义在 XML 中的。而在 MyBatis 3 中,提供了其它的配置方式。MyBatis 3 构建在全面且强大的基于 Java 语言的配置 API 之上。它是 XML 和注解配置的基础。注解提供了一种简单且低成本的方式来实现简单的映射语句。

提示: Java 注解的表达能力和灵活性十分有限。尽管MyBatis团队花了很多时间在调查、设计和试验上,但最强大的 MyBatis 映射并不能用注解来构建。

经验对于单表的操作使用注解更加便利,但是对于复杂的多表,使用注解模式就显得难以维护建议使用XML。

常用注解

注解用途
@Insert新增
@Update更新
@Delete删除
@Select查询
@Result封装结果集
@Results与@Result配合,封装多个结果集
@One实现一对一结果集封装
@Many实现一对多结果集封装

以下的查询案例和要求均和XML模式一致,只是将xml操作替换为注解操作

对于注解的查询操作是不需要Mapper.xml配置文件的,因为sql的配置和结果映射都通过注解实现了

SqlMapConfig.xml更新

        
4.1.1简单操作

对于基础的单表新增、更新、查询、删除操作如下,sql语句和xml一致,这里不多介绍。

public interface UserMapper {    // 新增    @Insert(value = "insert into user(id, username, `password`, birthday) values (#{id}, #{username}, #{password}, #{birthday})")    void addUser(User user);    // 更新    @Update(value = "update user set username = #{username}, `password` = #{password}, birthday = #{birthday} where id = #{id}")    void updateUser(User user);    // 查询    @Select(value = "select * from user")    List selectAll();    // 删除    @Delete(value = "delete from user where id = #{id}")    void deleteUser(Integer id);}
4.1.2 一对一查询

执行过程:

1)执行@Select标签的sql语句。

2)执行@Results标签的语句封装@Select的查询结果。

3)封装结果的时候有一个属性是user ,内部的one属性关联到了另外一个查询结果。所以就会去UserMapper中执行selectById 根据 column=uidorderuid作为参数去查询结果。

// 订单一对一查询public interface OrdersMapper {    // select * from orders o left join user u on o.uid = u.id    @Results({            @Result(property = "id", column = "id"),            @Result(property = "ordertime", column = "ordertime"),            @Result(property = "total", column = "total"),            @Result(                    javaType = User.class,                    property = "user",                    column = "uid",                    one = @One(select = "com.zyj.mapper.UserMapper.selectById"))    })    @Select(value = "select * from orders")    List findAllOrderAndUser();}
// 用户查询public interface UserMapper {    @Select(value = "select * from user where id = #{id}")    User selectById(Integer id);}

注解和标签对应关系总结:

注解标签
@Selectselect
@ResultsresultMap
@Resultid和
@Oneassociation
4.1.3 一对多查询

执行过程:

1)执行@Select标签的sql语句。

2)执行@Results标签的语句封装@Select的查询结果。

3)封装结果的时候有一个属性是orderList ,内部的Many属性关联到了另外一个查询结果。所以就会去OrderMapper中执行selectByUId 根据 column=idUserid作为参数去查询结果。

// 用户查询一对多public interface UserMapper {    // select * from user u left join orders o on u.id = o.uid;    @Results({            @Result(property = "id", column = "id"),            @Result(property = "username", column = "username"),            @Result(property = "password", column = "password"),            @Result(property = "birthday", column = "birthday"),            @Result(                    property = "orderList",                    column = "id",                    javaType = List.class,                    many = @Many(select = "com.zyj.mapper.OrdersMapper.selectByUId")            )    })    @Select(value = "select * from user")    List findAllUserAndOrder();}
// 根据用户id查询用户订单public interface OrdersMapper {    // 根据用户id返回查询结果    @Select(value = "select * from orders where uid = #{uid}")    List selectByUId(Integer uid);}

注解和标签对应关系总结:

注解标签
@Select
@Results
@Result
@Many
4.1.4多对多查询

执行过程:

1)执行@Select标签的sql语句。

2)执行@Results标签的语句封装@Select的查询结果。

3)封装结果的时候有一个属性是roleList ,内部的Many属性关联到了另外一个查询结果。所以就会去RoleMapper中执行selectByUserId 根据 column=idUserid作为参数去查询结果。

public interface UserMapper {    // select * from user u left join sys_user_role ur on u.id = ur.userid left join sys_role r on ur.roleid = r.id;    @Results({            @Result(property = "id", column = "id"),            @Result(property = "username", column = "username"),            @Result(property = "password", column = "password"),            @Result(property = "birthday", column = "birthday"),            @Result(                    property = "roleList",                    column = "id",                    javaType = List.class,                    many = @Many(select = "com.zyj.mapper.RoleMapper.selectByUserId")            )    })    @Select(value = "select * from user")    List findAllUserAndRole();}
// 根据用户id查询角色public interface RoleMapper {    @Select(value = "select r.* from sys_role r inner join sys_user_role ur on r.id = ur.roleid where userid = #{uid}")    List selectByUserId(Integer uid);}

注解和标签对应关系总结:

注解标签
@Selectselect
@ResultsresultMap
@Resultid和result
@Manycollection
4.1.5 注解的动态SQL

MyBatis提供的动态Sql标签在注解模式中也是一样适用,但是写法和刚才的一对一一对多多对多 的查询有所差异。作用和效果是一样的。所以这里只给出一个案例即可。

    @Update({""})    void updateAuthorValues(Author author);

如果想在注解的映射器接口中使用动态SQL,那么可以使用script元素。

4.2 缓存机制
       Mybatis 使用到了两种缓存:本地缓存(local cache)和二级缓存(second level cache)。 两个缓存的关系如下图:

每当一个新 session 被创建,MyBatis 就会创建一个与之相关联的本地缓存。任何在 session 执行过的查询结果都会被保存在本地缓存中,所以,当再次执行参数相同的相同查询时,就不需要实际查询数据库了。本地缓存将会在做出修改、事务提交或回滚,以及关闭 session 时清空。

4.2.1 验证一级缓存

1)在同一个sqlSession中,对User用户表根据id进行2次查询,观察控制台的sql打印情况。

@Testpublic void test1(){        // 获取一个sqlSession        SqlSession sqlSession = sessionFactory.openSession();        UserMapper userMapper = sqlSession.getMapper(UserMapper.class);        // 使用sqlSession执行第一次查询        User u1 = userMapper.selectUserByUserId(1);        System.out.println(u1);        // 使用sqlSession执行第二次查询        User u2 = userMapper.selectUserByUserId(1);        System.out.println(u2);        sqlSession.close();}

2)在同一个sqlSession中,对User用户表根据id进行2次查询。但是,中间对查询到的用户执行Update更新操作,并提交事务,观察控制台的sql打印情况。

@Testpublic void test2(){        // 获取一个sqlSession        SqlSession sqlSession = sessionFactory.openSession();        UserMapper userMapper = sqlSession.getMapper(UserMapper.class);        // 使用sqlSession执行第一次查询        User u1 = userMapper.selectUserByUserId( 1 );        System.out.println(u1);        // 第二次查询之前执行更新操作并提交事务    u1.setSex("女");        userMapper.updateUserByUserId(u1);        sqlSession.commit();        // 使用sqlSession执行第二次查询        User u2 = userMapper.selectUserByUserId(1);        System.out.println(u2);        sqlSession.close();}

总结:

1)第一次查询用户的时候,会在一级缓存中去查询用户信息,如果查询不到就去数据库中查询。并将查询到的结果更新到以及缓存中。

2)如果同一个SqlSession中执行了commit事务提交操作(增加、更新、删除),那么就会清空SqlSession中的缓存信息,避免下次查询的时候出现脏数据。

3)第二次查询的时候同样去一级缓存查询,如果有值就获取返回,如果没有就查询数据库并添加到一级缓存中。

4.2.2 验证二级缓存

二级缓存和一级缓存原理类似,只不过缓存的级别更高而已。一级缓存针对sqlSession,但是二级缓存就针对Mapper文件。所以二级缓存可以被多个sqlSession共享。

二级缓存和一级缓存不一样,一级缓存默认都是开启的,二级缓存默认是关闭的。所以需要配置开启。二级缓存的开启需要配置2个地方。

  • 总开关开启二级缓存SqlMapConfig.xml配置文件开启。

    
  • 由于二级缓存是Mapper级别的缓存,所以可以针对单个Mapper配置是否需要开启。

基于上诉流程测试二级缓存

@Testpublic` `void` `testTwoCache(){        // 获取sqlSession        SqlSession sqlSession1 = sessionFactory.openSession();        SqlSession sqlSession2 = sessionFactory.openSession();        SqlSession sqlSession3 = sessionFactory.openSession();            String statement = "com.zyj.UserMapper.selectById" ;        UserMapper userMapper1 = sqlSession1.getMapper(UserMapper. class );        UserMapper userMapper2 = sqlSession2.getMapper(UserMapper. class );        UserMapper userMapper3 = sqlSession2.getMapper(UserMapper. class );            // 第一次执行查询,结果会放入二级缓存中        User u1 = userMapper1.selectById( 1 );        System.out.println(u1);        sqlSession1.close(); // 关闭第一个session        // 执行更新操作,并提交        u1.setUsername("知春秋");        userMapper3.selectById(u1);        sqlSession3.commit();        // 第二次查询,由于更新操作导致二级缓存被更新,所以会重新查询数据库        User u2 = userMapper2.selectById( 1 );        System.out.println(u2);    sqlSession2.close();}
4.3 MyBatis学习思维导图(提供参考)

4.4 MyBatis源码剖析思维导图(提供参考)

关于"MyBatis的知识点有哪些"这篇文章就分享到这里了,希望以上内容可以对大家有一定的帮助,使各位可以学到更多知识,如果觉得文章不错,请把它分享出去让更多的人看到。

0