Mybatis基础知识大全!!!

1.1什么是Mybatis

  1. MyBatis 是一款优秀的持久层框架
  2. 它支持自定义 SQL、存储过程以及高级映射。
  3. MyBatis 免除了几乎所有的 JDBC 代码以及设置参数和获取结果集的工作。
  4. MyBatis 可以通过简单的 XML 或注解来配置和映射原始类型、接口和 Java POJO(Plain Old Java Objects,普通老式 Java 对象)为数据库中的记录。

1.2 如何获得Mybatis

  • 获得maven仓库:

     org.mybatis
     mybatis
     3.5.9

1.3 使用Mybatis的好处:

  • 使用简单,传统的JDBC代码太复杂
  • 简单易学:没有任何第三方依赖,最简单安装只要两个jar文件+配置几个sql映射文件。
  • 灵活
  • 解除sql与程序代码的耦合
  • 提供映射标签,支持对象与数据库的orm字段关系映射。
  • 提供对象关系映射标签,支持对象关系组建维护。
  • 提供xml标签,支持编写动态sql。

2.初涉Mybatis

2.1环境搭建

  1. 使用navicat创建一个数据库 Mybatis基础知识大全!!!
  2. 新建项目
  3. 导入依赖

    org.mybatis
    mybatis
    3.5.9

2.2、创建一个模块(项目)

  1. 编写mybatis的核心配置文件

  1. 编写mybatis工具类(封装):
public class MybatisUtils {
    private static SqlSessionFactory sqlSessionFactory;
    //第一步:获取SqlSessionFactory对象
    static {
        try {
            String resource = "mybatis-config.xml";//路径写对
            InputStream inputStream = Resources.getResourceAsStream(resource);
            sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    //通过SqlSessionFactory对象获取SqlSession对象
    //SqlSession:SqlSession 提供了在数据库执行 SQL 命令所需的所有方法。你可以通过 SqlSession 实例来直接执行已映射的 SQL 语句。
    public static SqlSession getSqlSession(){return  sqlSessionFactory.openSession();}//当传递一个true参数时表示自动提交事务
}
  1. 编写
  2. 编写实体类
//注;实体类的属性名必须与数据库的列名一致,否则无法进行匹配从而出现数据为空的现象,当然也可以在Mapper.xml配置中通过编写一个resultMap来进行映射,此时名字可以不相同

public class User {
    private int id;
    private String username;
    private String password;

    public User() {
    }

    public User(int id, String username, String password) {
        this.id = id;
        this.username = username;
        this.password = password;
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }
}
  • 编写Mapper接口(Dao)
public interface UserMapper {
    public List getUser();
}
  • 编写Mapper配置文件
//注:每个Mapper文件都需要在mybatis-config.xml文件中去注册
//
//相当于Mapper的接口实现类

    //namespace:命名空间,指定要实现的Mapper接口,路径映射

    //id:唯一匹配于Mapper接口的方法名
    //resultType:返回类型,必须写全限定名称

        select * from user;

  1. 测试
public class UserMapperTest {
    @Test
    public void test(){
        //获得sqlSession对象
        SqlSession sqlSession = MybatisUtils.getSqlSession();
        //获取UserMapper的对象以调用接口内的方法
        UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
        //调用方法
        List users = userMapper.getUser();
        //遍历结果集
        for (User user : users) {
            System.out.println(user.getId() + " " + user.getUsername() + " " + user.getPassword());
        }
        //关闭sqlSessoin
        sqlSession.close();
    }
}

2.3、使用Mybatis的三个重要类

  1. SqlSessionFactoryBuilder: 可以重用 SqlSessionFactoryBuilder 来创建多个 SqlSessionFactory 实例,但最好还是不要一直保留着它,以保证所有的 XML 解析资源可以被释放给更重要的事情
  2. SqlSessionFactory: SqlSessionFactory 一旦被创建就应该在应用的运行期间一直存在,没有任何理由丢弃它或重新创建另一个实例,最简单的就是使用单例模式或者静态单例模式
  3. SqlSession: SqlSession 的实例不是线程安全的,因此是不能被共享的,每次打开一个 SqlSession,记得关闭它, 这个关闭操作很重要

3.Mybatis的CRUD简单实现

3.1、通过id查找用户:

  1. 接口:
public User getUserById(int id);
  1. Mapper配置文件

    select * from user where id=#{id};

  1. 测试
SqlSession sqlSession = MybatisUtils.getSqlSession();
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
User user = userMapper.getUserById(1);
sqlSession.close();

3.2、插入用户:

  1. 接口:
public void insertUser(User user);
  1. Mapper配置文件

    insert into user values (#{id},#{username},#{password});

  1. 测试
SqlSession sqlSession = MybatisUtils.getSqlSession();
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
userMapper.insertUser(new User(5,"老六","1234"));
sqlSession.commit();
sqlSession.close();
//注:在Mybatis中增删改查找都需要使用事务,必须手动提交事务如果没有配置自动管理事务的情况下

3.3、根据id更改用户名字:

  1. 接口:
public void insertUser(User user);
  1. Mapper配置文件

    insert into user values (#{id},#{username},#{password});

  1. 测试
//当有多个参数的时候,可以使用@Param()注解指定名字
//public void updateName(@Param("id") int id,@Param("username") String username);

SqlSession sqlSession = MybatisUtils.getSqlSession();
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
userMapper.updateName(3,"王五");
sqlSession.commit();
sqlSession.close();

3.4、 根据id删除用户:

  1. 接口:
public void insertUser(User user);
  1. Mapper配置文件

    insert into user values (#{id},#{username},#{password});

  1. 测试
SqlSession sqlSession = MybatisUtils.getSqlSession();
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
userMapper.deleteUserById(5);
sqlSession.commit();
sqlSession.close();

3.5、好用的Map

当接口中传递的对象有多个的时候,除了可以使用·@Param()注解之外,我们常常使用一个不算规范但是特别好用的方式,那就是传递Map

  1. 接口:
 public void updateNameById(Map map);
  1. mapper配置文件:

    update user set username=#{username} where id=#{id};

  1. 调用:
SqlSession sqlSession = MybatisUtils.getSqlSession();
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
Map map=new HashMap();
map.put("username","战三");
map.put("id",2);
userMapper.updateNameById(map);
sqlSession.commit();
sqlSession.close();

总结:

  • 当接口只传递一个参数的时候:可以直接在mapper文件使用,且不需要与参数名字对应
  • 当需要多个参数的时候:
  • 如果有一个实体类正好与之对应,那么可以传递一个对象,然后在mapper文件中通过#{对象.属性}调用
  • 通过使用注解的方式@Param()指定名字
  • 通过传递一个Map

3.6、模糊查询

  1. 方式一:在java代码在传递”%”
userMapper.getUserLike("%张%");
  1. 方式二:在mapper文件的sql语句中实现

    select * from user where username like "%"#{name}"%" ;

4.配置解析

MyBatis 的配置文件包含了会深深影响 MyBatis 行为的设置和属性信息。 配置文档的顶层结构如下:

  • configuration(配置)
  • properties(属性)
  • settings(设置)
  • typeAliases(类型别名)
  • typeHandlers(类型处理器)
  • objectFactory(对象工厂)
  • plugins(插件)
  • environments(环境配置)
    • environment(环境变量)
    • transactionManager(事务管理器)
    • dataSource(数据源)
  • databaseIdProvider(数据库厂商标识)
  • mappers(映射器)

4.1、environments 环境配置

MyBatis 可以配置成适应多种环境, 不过要记住:尽管可以配置多个环境,但每个 SqlSessionFactory 实例只能选择一种环境。

environments 元素定义了如何配置环境。


注意点:

  • 默认使用的环境 ID(比如:default=”development”)。
  • 每个 environment 元素定义的环境 ID(比如:id=”development”)。
  • 事务管理器的配置(比如:type=”JDBC”)。
  • 数据源的配置(比如:type=”POOLED”)。

4.2、properties(属性)

可以从外部的资源环境读取,也可以在内部定义,可以动态的替换环境中的配置信息

  1. 外部资源文件引入:
  2. db.properties
driver=com.mysql.cj.jdbc.Driver
url=jdbc:mysql://localhost:3306/mybatis?useUnicode=true&characterEncoding=utf-8&serverTimezone=Asia/Shanghai
username=root
password=11111111
  1. 引入:

  1. 内部使用property定义:

设置好的属性可以动态替换:


注:如果同时使用了外部资源文件和内部定义的方式那么会使用外部资源文件。

4.3、typeAliases(类型别名)

类型别名可为 Java 类型设置一个缩写名字,降低冗余的全限定类名书写

  1. 方式一:使用具体的全限定类名

注:设定之后在其他使用domain.blog.Author的地方就可以使用Author代替
2. 方式二:使用实体类包名


注:通过这种方式设定之后,在该包下所有的实体类的全限定类名可以使用该类名的首字母小写来代替,比如User使用user代替

总结:两种方式各有优劣,当类比较少的时候可以使用第一种方式,当类比较多的时候可以使用第二种方式,如果想在使用第二种方式的同时给特点的类设定指定名字,可以使用注解的方式,且如果同时使用了第一种方式和第二种方式那么使用两个别名都正确。

@Alias("author")
public class Author {}

4.4、settings(设置)

1.常用的一些设置:

设置名 描述 有效值 默认值 cacheEnabled 全局性地开启或关闭所有映射器配置文件中已配置的任何缓存。 true | false true lazyLoadingEnabled 延迟加载的全局开关。当开启时,所有关联对象都会延迟加载。 特定关联关系中可通过设置 fetchType

属性来覆盖该项的开关状态。 true | false false useGeneratedKeys 允许 JDBC 支持自动生成主键,需要数据库驱动支持。如果设置为 true,将强制使用自动生成主键。尽管一些数据库驱动不支持此特性,但仍可正常工作(如 Derby)。 true | false False mapUnderscoreToCamelCase 是否开启驼峰命名自动映射,即从经典数据库列名 A_COLUMN 映射到经典 Java 属性名 aColumn。 true | false False logImpl 指定 MyBatis 所用日志的具体实现,未指定时将自动查找。 SLF4J | LOG4J | LOG4J2 | JDK_LOGGING | COMMONS_LOGGING | STDOUT_LOGGING | NO_LOGGING 未设置

日志:

  • STDOUT_LOGGING (mybatis默认)
  • LOG4J (掌握)
  • LOG4J2
  • JDK_LOGGING
  • COMMONS_LOGGING
  • SLF4J
  • NO_LOGGING:

4.5、mappers(映射器)

  1. 作用:告诉 MyBatis 到哪里去找映射文件
  2. 实现方式:
  3. 方式一:resource(推荐)

  1. 方式二:url(极不推荐)

  1. 方式三:class

注:
+ 接口必须和mapper配置文件在同一个包下
+ 接口和mapper配置文件的名字必须相同
4. 方式四:name


注:
+ 接口必须和mapper配置文件在同一个包下
+ 接口和mapper配置文件的名字必须相同

4.6、其他(暂时了解)

  • typeHandlers(类型处理器)
  • objectFactory(对象工厂)
  • plugins(插件)(有用)
  • Mybatis PageHelper分页插件
  • Mybatis通用Mapper插件
  • Mybatis Plus插件
  • 代码生成插件mybatis-generator

5.拓展:当属性名和列名不一致

假设存在一个数据库user表,字段如下:

Mybatis基础知识大全!!!

一个User实体类如下:

public class User {
    private int id;
    private String username;
    private String password;
    }

那么当查询结果集为User类型的时候,会出现姓名为空的问题。

解决方式:

  1. 方式一:在sql语句中使用别名
select id ,name as usernaem,password from user;
  1. 方式二:resultMap结果映射

    select * from user  ;

  • resultMap 元素是 MyBatis 中最重要最强大的元素。
  • ResultMap 的设计思想是,对简单的语句做到零配置,对于复杂一点的语句,只需要描述语句之间的关系就行了。
  • ResultMap 的优秀之处——你完全可以不用显式地配置它们,如上面的resultMap可以改为

即只需要显示的配置不匹配的情况即可。 注:其实第一种方法使用别名的本质上还是使用了resultMap的映射,因为在这些情况下,MyBatis 会在幕后自动创建一个 ResultMap,再根据属性名来映射列到 JavaBean 的属性上。

6.日志

6.1、日志工厂

  1. 当我们操作数据库出现错误时,需要借助一些手段进行排错
  2. 之前:sout,debug
  3. 现在:日志
  4. 日志类别:
  5. STDOUT_LOGGING(掌握)(默认的标准日志工厂)
  6. LOG4J(掌握)
  7. LOG4J2
  8. SLF4J
  9. JDK_LOGGING
  10. COMMONS_LOGGING
  11. NO_LOGGING
  12. 配置日志:

Mybatis基础知识大全!!!

6.2、Log4j

  1. 介绍:
  2. Log4j是Apache的一个开源项目,通过使用Log4j,我们可以控制日志信息输送的目的地是控制台、文件、GUI组件等
  3. 我们也可以控制每一条日志的输出格式;
  4. 通过定义每一条日志信息的级别,我们能够更加细致地控制日志的生成过程。
  5. 可以通过一个配置文件来灵活地进行配置,而不需要修改应用的代码。
  6. log4j:
  7. 导入log4j依赖

    log4j
    log4j
    1.2.17

  1. log4j.properties
#将等级为debug的日志信息输出到console和file,其中console为控制台,名字可以自己定义,file相同
log4j.rootLogger=DEBUG,console,file

#控制台输出的相关设置
log4j.appender.console=org.apache.log4j.ConsoleAppender
log4j.appender.console.Target=System.out
log4j.appender.console.layout=org.apache.log4j.PatternLayout
log4j.appender.console.layout.ConversionPattern=%p:%c%n%m%l%n%m

#文件输出的相关设置
log4j.appender.file=org.apache.log4j.FileAppender
log4j.appender.file.File=d:/log4jFile/mybatis.log
log4j.appender.file.layout=org.apache.log4j.PatternLayout
log4j.appender.file.layout.ConversionPattern=%d{yyyy-MM-dd   HH:mm:ss} %l %F %p %m%n
log4j.appender.file.MaxFileSize=10mb

#控制日志的输出鉴别
log4j.logger.org.mybatis=DEBUG
log4j.logger.java.sql.ResultSet=DEBUG
log4j.logger.java.sql=DEBUG
log4j.logger.java.sql.Statement=DEBUG
log4j.logger.java.sql.PreparedStatement=DEBUG
  1. 在mybatis-config中配置log4j的使用

7.分页

思考:为什么要分页

  • 减少数据的处理量

7.1、 limit分页:

select * from user limit startIndex,pagesize;

select *from user limit pagesize; -- 当只有一个参数的时候,从第一个数据开始

7.2、 RowBounds分页(不推荐使用)

  1. 接口:
public List getUser();
  1. mapper.xml:

    select * from user ;

  1. 实现:
SqlSession sqlSession = MybatisUtils.getSqlSession();

RowBounds rowBounds=new RowBounds(1,2);
List list = sqlSession.selectList("com.study.dao.UserMapper.getUser", null, rowBounds);
for (Object user : list) {
    System.out.println(user.toString());
}

7.3、分页插件

使用PageHelper分页插件,https://pagehelper.github.io/,了解一下即可,如有需要再看使用文档。

8.注解开发

  • 使用注解来映射简单语句会使代码显得更加简洁
  • 但对于稍微复杂一点的语句,Java 注解不仅力不从心,还会让你本就复杂的 SQL 语句更加混乱不堪
  • 如果需要做一些很复杂的操作,最好用 XML 来映射语句。

使用建议:除非是很简单的操作,否则尽量建议使用xml方式完成,一般而言我们都会使用xml。

8.1、常用的注解

  1. @Insert: 插入记录的时候麻烦的一点是主键如何生成,对此基本上有三种方案,分别是手动指定(应用层)、自增主键(数据层单表)、选择主键(数据层多表)。(如想了解可以查)
@Insert("insert into user values (#{id},#{username},null)")
  1. @Delete:
@Delete("delete from user where id=#{id};")
  1. @Updata:
@Update(" update user set username=#{username} where id=#{id};")
  1. @select:
@Select("select * from user")
  1. @Param: 在接口中传递多个参数的时候可以指定
 public void updateName(@Param("id") int id,@Param("username") String username);

注:
– 基本类型或者String类型需要加上
– 引用类型不需要加
– 如果只有一个基本类型的参数可以不加
– 在mapper.xml中使用的就是它指定的名字
6. @Results, @Result: 当使用select标签时,如果查询的字段与当前实体类不能进行很好的匹配那么需要我们进行一个映射

@Results(id = "userMap", value = {
    @Result(id=true, column = "id", property = "id"),
    @Result(column = "username", property = "username"),
    @Result(column = "passwd", property = "passwd"),
})
@Select("SELECT * FROM t_user WHERE id=#{id}")
User loadByIdResultMap(Long id);
  1. @ResultMap: 如果以及存在一个@Results,那么可以通过@ResultMap指定id名字去引用它
@ResultMap("userMap")
@Select("SELECT * FROM t_user WHERE id=#{id}")
User loadByIdResultMapReference(Long id);

8.2、使用注解开发

  1. 接口:
public interface UserMapper {
    @Select("select * from user")
    public List getUser();
    @Update(" update user set username=#{username} where id=#{id};")
    public void updateName(@Param("id") int id,@Param("username") String username);
    @Insert("insert into user values (#{id},#{username},null)")
    public void insertUser(User user);
    @Delete("delete from user where id=#{id};")
    public void deleteUserById(int id);
}
  1. mybatis-config.xml注册接口:

  1. 测试:
SqlSession sqlSession = MybatisUtils.getSqlSession();
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
List user = userMapper.getUser();
//userMapper.insertUser(new User(6,"随便","123123"));
//userMapper.updateName(2,"还行");
//userMapper.deleteUserById(1);
for (User user1 : user) {
    System.out.println(user1);
}
sqlSession.commit();
sqlSession.close();

本质:反射机制实现

底层:动态代理

8.3、关于#{}和${}的比较

  • 前者是占位,在使用时会将传入的字符串加上引号当做一个整体,${}是拼接,在使用的时候会将传入的字符串不做处理直接拼接
  • 使用#{}时会进行预编译可以防止sql注入,使用${}不会预编译不可以防止sql注入
  • 使用时#{}是编译好SQL后语句再去取值,${}取值以后再去编译SQL语句
  • 建议:一般能用#{}就不用${}

8.4、当注解开发和xml开发同时使用

注:虽然注解和xml配置文件可以同时使用,但是如果在接口中的同一个方法上既使用了注解,有在xml文件中进行了配置,也就是对同一个方法同时使用了注解配置文件两种方式,那么程序会报错。

9.Lombok

Lombok项目是一个java库,它可以自动插入到编辑器和构建工具中,增强java的性能。不需要再写getter、setter或equals方法,只要有一个注解,你的类就有一个功能齐全的构建器、自动记录变量等等.

  1. 常用注解:
  2. Data:整合了Getter、Setter、ToString、EqualsAndHashCode、无参构造函数注解。
  3. Getter:快速构建Getter方法。
  4. Setter:快速构建Setter方法。
  5. ToString:快速将当前对象转换成字符串类型,便于log
  6. EqualsAndHashCode:快速进行相等判断
  7. NonNull:判断变量(对象)是否为空。
  8. AllArgsConstructor:快速构建全部参数的构造函数
  9. NoArgsConstructor:快速构建无参构造函数
  10. Lombok的使用:
  11. 在IDEA中安装Lombok插件
  12. 在项目中导入lombok的jar包

    org.projectlombok
    lombok
    1.18.16

  1. 使用:
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Persosn {
    private String name;
    private int age;
}

注:由于使用@Data只含有无参构造函数,使用要结合@AllArgsConstructor使用,但是使用了@AllArgsConstructor之后@Data的无参构造函数就会消失,使用需要再搭配@NoArgsConstructor使用。

注:缺点:无法承载有各种参数的构造函数,但是我们可以手动的去添加。

10.复杂查询

10.1、模拟场景环境搭建

  1. 新建项目,导入相关依赖
  2. 配置文件的编写
  3. 新建实体类Student和Teacher
  4. 建立对应的Mapper接口
  5. 建立对应的Mapper配置文件
  6. 注册配置文件
  7. 测试环境搭建是否成功

10.2、多对一实际应用:关联

比如多个学生对应一个老师,就是多对一

实体类如下:

@Data
public class Student {
    private int id;
    private String name;
    private Teacher teacher;//多个学生一个老师
}

@Data
public class Teacher {
    private int id;
    private String name;
}

实现关键: association

10.2.1、嵌套查询


    select * from student ;

    select * from teacher where id=#{id}

通过嵌套一个子查询的方式,通过学生的tid去找到对应的老师

10.2.2、嵌套结果


    select s.id sid,s.name sname,t.id tid ,t.name tname from student s,teacher t where s.tid=t.id;

通过对结果集直接进行映射

10.3、一对多实际应用:集合

比如一个老师有多个学生,对于老师而言就是一对多

实体类如下:

@Data
public class Student {
    private int id;
    private String name;
    private int tid;
}

@Data
public class Teacher {
    private int id;
    private String name;
    private List students;
}

实现关键: collection

10.3.1、嵌套查询


    select * from teacher t;

    select * from student where tid=#{id};

10.3.2、嵌套结果


    select s.id sid,s.name sname,t.id tid ,t.name tname from student s,teacher t where s.tid=t.id;

10.4、小结

  1. 关联:association
  2. 集合:collection
  3. javaType:用来指定实体类中的属性的类型
  4. ofType:用来指定映射到List或者集合中的pojo类型,泛型中的约束类型

附:面试高频问题;

  • MySql引擎
  • InnoDB底层原理
  • 索引
  • 索引优化

11.动态SQL

11.1、简单介绍

动态 SQL 是 MyBatis 的强大特性之一。如果你使用过 JDBC 或其它类似的框架,你应该能理解根据不同条件拼接 SQL 语句有多痛苦,例如拼接时要确保不能忘记添加必要的空格,还要注意去掉列表最后一个列名的逗号。利用动态 SQL,可以彻底摆脱这种痛苦。

种类:

  • if
  • choose (when, otherwise)
  • trim (where, set)
  • foreach

11.2、实例项目的搭建

  1. 在数据库中根据以下实体类创建blog表
@Data
public class Blog {
    private String id;
    private String title;
    private String author;
    private Date createTime;
    private int views;
}

拓展:实体类中的id类型是String,在具体的一个项目中其实我们可以使用UUID这个类来随机生成一个唯一的ID,工具类简单封装如下:

public class IDUtils {
    public static String getId(){
        return UUID.randomUUID().toString().replace("-","");
    }
}
  1. 新建项目,导入相关依赖
  2. 配置文件的编写

注:开启这个设置可以自动将数据库的下划线映射到实体类的驼峰命名属性
4. 新建实体类Blog
5. 建立对应的Mapper接口
6. 建立对应的Mapper配置文件
7. 注册配置文件
8. 测试环境搭建是否成功

11.3动态SQL的使用

11.3.1、if

  • if提供了条件判断的功能,可以根据情况决定是否要追加语句。

        select * from blog where 1=1

            and id=#{id}

            and title =#{title}

            and author =#{author}

            and views>#{views}

注:第一个where条件后面加一个1=1是为了方便后面的每一个判断条件追加sql的第一个能写and

11.3.2、choose (when, otherwise)

  • 有时候,我们不想使用所有的条件,而只是想从多个条件中选择一个使用。针对这种情况,MyBatis 提供了 choose 元素,它有点像 Java 中的 switch 语句。

    select * from blog

                id=#{id}

                and title =#{title}

                and author =#{author}

                and views>#{views}

  • 注:当同时满足多个when的时候,按照顺序选择拼接,比如第一个when满足那么即是后面的满足了也不会拼接,然后都不满足那么拼接otherwise里面的内容,另外otherwise不是必须的

11.3.3、trim (where, set)

  • where: where 元素只会在子元素返回任何内容的情况下才插入 “WHERE” 子句。而且,若子句的开头为 “AND” 或 “OR”, where 元素也会将它们去除。
  • set: set 元素可以用于动态包含需要更新的列,忽略其它不更新的列

  update Author

      author=#{author},
      title=#{title},
      views=#{views}

  • trim:
  • trim包含的属性;
    • prefix:自定义前缀
    • prefixOverrides:需要被移除的前缀
    • suffix:自定义后缀
    • suffixOverrides:需要被移除的后缀
  • 可以自定义标签的替换方式,比如与where等同效果的格式如下:

  ...

prefixOverrides 属性会忽略通过管道符分隔的文本序列(注意此例中的空格是必要的)。上述例子会移除所有 prefixOverrides 属性中指定的内容,并且插入 prefix 属性中指定的内容。
– 与set等同效果的格式如下:


  ...

11.3.4、foreach

  • foreach 元素的功能非常强大,它允许你指定一个集合,声明可以在元素体内使用的集合项(item)和索引(index)变量。它也允许你指定开头与结尾的字符串以及集合项迭代之间的分隔符。
  • 可以将任何可迭代对象(如 List、Set 等)、Map 对象或者数组对象作为集合参数传递给 foreach。当使用可迭代对象或者数组时,index 是当前迭代的序号,item 的值是本次迭代获取到的元素。当使用 Map 对象(或者 Map.Entry 对象的集合)时,index 是键,item 是值。

    select * from blog

            #{name}

测试:

@Test
public void test() {
    SqlSession sqlSession = MybatisUtils.getSqlSession();
    BlogMapper blogMapper = sqlSession.getMapper(BlogMapper.class);
    ArrayList names = new ArrayList<>();
    names.add("张三");
    names.add("李四");
    Map map=new HashMap<>();
    map.put("names",names);
    List blogs = blogMapper.queryBlog(map);
    for (Blog blog : blogs) {
        System.out.println(blog);
    }
    sqlSession.close();
}

11.3.5、sql片段

sql片段的作用就是可以将一部分sql代码抽取出来,然后可以对他进行一个复用。


    select * from blog

            id=#{id}

            and title =#{title}

            and author =#{author}

注意事项:

  • 尽量不要使sql片段太过复杂

11.3.6、小结

动态sql本质上就是拼接sql语句

建议:

  • 我们可以在mysql中去写写出我们需要的sql语句,然后再去拼接

12.Mybatis缓存

12.1、简介

  1. 什么是缓存
  2. 存储在内存中的临时数据
  3. 将经常查询的信息从内存中复制一份到缓存,当再次查找时就直接从缓存中查找,从而提高效率,解决高并发的性能问题
  4. 使用缓存的好处
  5. 减少数据库的交互次数,减小系统的开销,提高效率
  6. 什么样的数据库可以使用缓存
  7. 查询比较频繁并且不经常改动的数据库

12.2、Mybatis缓存

mybatis本身有两种缓存,分别为一级缓存和二级缓存

  1. 一级缓存:
  2. MyBatis默认开启了一级缓存,一级缓存是在 SqlSession 层面进行缓存的。即,同一个 SqlSession ,多次调用同一个 Mapper 和同一个方法的同一个参数,只会进行一次数据库查询,然后把数据缓存到缓冲中,以后直接先从缓存中取出数据,不会直接去查数据库。
  3. 二级缓存:
  4. 二级缓存需要手动开启,他是基于namespce级别的缓存
  5. 为了提高拓展性,mybatis定义了缓存接口Cache,我们可以通过该接口自定义二级缓存

12.3、一级缓存

  • 一级缓存也叫本地缓存:SqlSession
  • 在同一个SqlSession之间查询到的数据会放到本地的缓存中
  • 之后如果想要获取数据自己从本地缓存中取

测试步骤:

  1. 开启日志

  1. 测试在同一个SqlSession期间查询相同的数据
    Mybatis基础知识大全!!!

缓存失效的情况:

  1. 查询不一样的数据
    Mybatis基础知识大全!!!
  2. 查询不同的Mapper.xml
  3. 手动清除缓存
sqlSession.clearCache();

Mybatis基础知识大全!!!
5. 缓存会使用最近最少使用算法(LRU, Least Recently Used)算法来清除不需要的缓存。
6. 缓存不会定时进行刷新(也就是说,没有刷新间隔)

小结:一级缓存是默认开启的,也关闭不掉,只能手动清理或者设置,一级缓存其实就相当于一个Map

12.4、二级缓存

  • 二级缓存也叫全局缓存,它的出现是为了解决一级缓存的作用域太低
  • 它是基于namespace级别的缓存,一个命名空间,对应一个二级缓存
  • 机制:
  • 一个SqlSession查询一条数据,这个数据会被放到一级缓存中;
  • 当这个SqlSession断开的时候,一级缓存就会消失,为了能够继续保存,我们就产生了二级缓存
  • 当其他的SqlSession查询数据时,就可以先从二级缓存中查询
  • 不同的mapper.xml文件查出的数据会放到自己的缓存(map)之中

测试步骤:

  1. 开启二级缓存设置;

  1. 在要使用二级缓存的mapper.xml配置文件中开启缓存:

  1. 测试

小结:

  1. 在使用二级缓存的时候可能会报错:
Error serializing object.  Cause: java.io.NotSerializableException

解决:原因是没有将实体类序列化,所以直接将类序列化即可
2. 在mapper.xml文件中,对于查找标签都可以手动设置是否开启缓存

 useCache="true"
  1. 缓存清除的策略:
  2. LRU – 最近最少使用:移除最长时间不被使用的对象。
  3. FIFO – 先进先出:按对象进入缓存的顺序来移除它们。
  4. SOFT – 软引用:基于垃圾回收器状态和软引用规则移除对象。
  5. WEAK – 弱引用:更积极地基于垃圾收集器状态和弱引用规则移除对象。
  6. 所有的数据都会先存到一级缓存,只有当会话提交或者关闭才会提交到二级缓存

12.5、缓存原理

Mybatis基础知识大全!!!

12.6、自定义缓存(了解)

注:一般可以采用redis来做缓存!!

Original: https://www.cnblogs.com/xiaoye-Blog/p/16528921.html
Author: 小也取不到名字
Title: Mybatis基础知识大全!!!

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/620922/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球