mybatis

Mybatis

配置_MyBatis中文网

MyBatis是什么,有什么用

  • MyBatis 是一个 Java 持久层框架(用于操作数据库的工具),它简化了数据库的增删改查(CRUD)操作。你可以把它理解成一个帮你“翻译”和“跑腿”的助手:你写 SQL 语句,它帮你自动处理 Java 代码和数据库之间的繁琐对接

  • 持久化

    就是把瞬时数据变为永久数据

    存数据到数据库,io存到文件,都是持久化

  • MyBatis 就像一个“SQL 执行管家”,帮你把 Java 对象和数据库之间的操作变得简单、清晰,适合需要灵活控制 SQL 的中小型项目。

  • 导入方法

    1. maven 依赖导入
    2. github 下载jar包
  • 前提

    1. JDBC
    2. Mysql
    3. java基础
    4. maven
    5. junit(测试用)

第一个Mybatis

image-20250218211034726

  • 共七步,从左往右

    1. 配置maven依赖,建立子maven模块

      <dependencies>
          <!--mysql驱动-->
          <!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java -->
          <dependency>
              <groupId>mysql</groupId>
              <artifactId>mysql-connector-java</artifactId>
              <version>5.1.47</version>
          </dependency>
          <!--mybatis-->
          <!-- https://mvnrepository.com/artifact/org.mybatis/mybatis -->
          <dependency>
              <groupId>org.mybatis</groupId>
              <artifactId>mybatis</artifactId>
              <version>3.5.19</version>
          </dependency>
          <!--junit-->
          <!-- https://mvnrepository.com/artifact/junit/junit -->
          <dependency>
              <groupId>junit</groupId>
              <artifactId>junit</artifactId>
              <version>4.13.2</version>
          </dependency>
      </dependencies>
      
      <!--解决资源导出问题-->
      <build>
          <resources>
              <resource>
                  <directory>src/main/resources</directory>
                  <includes>
                      <include>**/*.properties</include>
                      <include>**/*.xml</include>
                  </includes>
                  <filtering>true</filtering>
              </resource>
              <resource>
                  <directory>src/main/java</directory>
                  <includes>
                      <include>**/*.properties</include>
                      <include>**/*.xml</include>
                  </includes>
                  <filtering>true</filtering>
              </resource>
          </resources>
      </build>
      
    2. 写工具类获取SqlSessionFactory,返回SqlSession

      package com.zhm.utils;
      
      import org.apache.ibatis.io.Resources;
      import org.apache.ibatis.session.SqlSession;
      import org.apache.ibatis.session.SqlSessionFactory;
      import org.apache.ibatis.session.SqlSessionFactoryBuilder;
      
      import java.io.IOException;
      import java.io.InputStream;
      
      // 此工具类为了获取SqlSession
      public class MybatisUtils {
          static SqlSessionFactory sqlSessionFactory = null;
          static {
              try {
                  // mybatis配置,配置jdbc连接信息
                  String resource = "mybatis-config.xml";
                  InputStream inputStream = Resources.getResourceAsStream(resource);
                  // SqlSessionFactoryBuilder获取SqlSessionFactory
                 sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
              } catch (IOException e) {
                  throw new RuntimeException(e);
              }
          }
      
          public static SqlSession getSqlSession(){
              SqlSession sqlSession = sqlSessionFactory.openSession(true);
              return sqlSession;
          }
      }
      
    3. 写mybatis配置,SqlSessionFactory的配置(连接mysql数据库)

      <?xml version="1.0" encoding="UTF-8" ?>
      <!DOCTYPE configuration
              PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
              "http://mybatis.org/dtd/mybatis-3-config.dtd">
      
      <configuration>
          <environments default="development">
              <environment id="development">
                  <transactionManager type="JDBC"/>
                  <dataSource type="POOLED">
                      <property name="driver" value="com.mysql.jdbc.Driver"/>
                      <property name="url" value="jdbc:mysql://localhost:3306/mybatis?useSSL=true&amp;useUnicode=true&amp;characterEncoding=utf8"/>
                      <property name="username" value="root"/>
                      <property name="password" value="123456"/>
                  </dataSource>
              </environment>
          </environments>
          <!--每一个mapper.xml都要注册mapper-->
          <mappers>
              <mapper resource="com/zhm/dao/UserMapper.xml"></mapper>
          </mappers>
      </configuration>
      
    4. 写实体类

      package com.zhm.pojo;
      
      public class User {
          private int id;
          private String name;
          private String pwd;
      
          public User() {
          }
      
          public User(int id, String name, String pwd) {
              this.id = id;
              this.name = name;
              this.pwd = pwd;
          }
      
          public int getId() {
              return id;
          }
      
          public void setId(int id) {
              this.id = id;
          }
      
          public String getName() {
              return name;
          }
      
          public void setName(String name) {
              this.name = name;
          }
      
          public String getPwd() {
              return pwd;
          }
      
          public void setPwd(String pwd) {
              this.pwd = pwd;
          }
      
          @Override
          public String toString() {
              return "User{" +
                      "id=" + id +
                      ", name='" + name + '\'' +
                      ", pwd='" + pwd + '\'' +
                      '}';
          }
      }
      
    5. 写UserMapper接口

      package com.zhm.dao;
      
      import com.zhm.pojo.User;
      
      import java.util.List;
      
      public interface UserDao {
          List<User> getUserList();
      }
      
    6. 写实现类,用xml文件

      <?xml version="1.0" encoding="UTF-8" ?>
      <!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
      <!--绑定接口名-->
      <mapper namespace="com.zhm.dao.UserDao">
      <!--方法名,返回值-->
        <select id="getUserList" resultType="com.zhm.pojo.User">
          select * from mybatis.user;
        </select>
      </mapper>
      
    7. 测试(新建完全相同文件夹测试,@test),最后记得关闭sqlsession,释放资源

      package com.zhm.dao;
      
      import com.zhm.pojo.User;
      import com.zhm.utils.MybatisUtils;
      import org.apache.ibatis.session.SqlSession;
      import org.junit.Test;
      
      import java.util.List;
      
      public class UserDaoTest {
      
          @Test
          public void test(){
              SqlSession sqlSession = MybatisUtils.getSqlSession();
      
              UserDao mapper = sqlSession.getMapper(UserDao.class);
              List<User> userList = mapper.getUserList();
      
              for (User user : userList) {
                  System.out.println(user);
              }
              
              sqlSession.close();
          }
      }
      

CRUD

  • 我们经常会听到CRUD,但是自己不知道,增删改查
    c create 创建
    r read 阅读
    u update 更改
    d delete 删除

  • 配置好环境后,实现增删改查只用3步

    1. 增加UserDao(mapper)接口方法,要什么加什么
    2. 在usermapper.xml绑定接口,绑定方法,绑定方法返回类型,参数,编写sql代码
    3. 测试类测试,获取UserDao对象,直接调用方法,传入参数,获取返回
  • 注意点:

    namespace 绑定接口位置

    id 方法名

    resultType 返回值类型

    parameterType 参数类型

    #{id}为占位符,跟接口方法里面参数一样

    增删改记得commit提交事务,不如数据库数据不会更新

  • <?xml version="1.0" encoding="UTF-8" ?>
    <!DOCTYPE mapper
      PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
      "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
    <!--namespace绑定接口名-->
    <mapper namespace="com.zhm.dao.UserDao">
    <!--id方法名,resultType返回值类型-->
      <select id="getUserList" resultType="com.zhm.pojo.User">
        select * from mybatis.user;
      </select>
    <!--parameterType参数类型,#{id}为占位符,跟接口方法里面参数一样-->
      <select id="getUserById" resultType="com.zhm.pojo.User" parameterType="int">
        select * from mybatis.user
                 where id = #{id};
      </select>
    
      <insert id="addUser" parameterType="com.zhm.pojo.User">
        insert into mybatis.user(id, name, pwd)
        values (#{id},#{name},#{pwd});
      </insert>
    
      <update id="updateUser" parameterType="com.zhm.pojo.User">
        update mybatis.user set name = #{name},pwd = #{pwd}
                            where id = #{id};
      </update>
    
      <delete id="deleteUser" parameterType="int">
        delete from mybatis.user
               where id=#{id};
      </delete>
    
    </mapper>
    
  • 不变的测试代码

    @Test
    public void deleteUser(){
        SqlSession sqlSession = MybatisUtils.getSqlSession();
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
    // 此处选择调用方法,commit看情况
    //    sqlSession.commit();
        sqlSession.close();
    }
    

出现错误,java报错,从下面往上面看

万能Map

  • 在实体类数据库属性过多可以使用map

    类似修改情况,假如属性过多,但修改只修改某个属性,就可以用这个方法

    1. 首先在usermapper参数改为map

    2. 在mybatismapper.xml里编写sql,修改参数列表parameterType=map,

      sql语句的#{随意填写k},调用时存入随意填写k与v就行

  • int updateUser2(Map<String,Object> map);
    
    <update id="updateUser2" parameterType="map">
      update mybatis.user set pwd = #{newpwd} where id = #{getid};
    </update>
    
    public void updateUser2(){
        SqlSession sqlSession = MybatisUtils.getSqlSession();
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        // 万能map键值对,实现类里面写k,调用时,写k和对应v
        Map<String, Object> map = new HashMap<String, Object>();
        map.put("newpwd","135792");
        map.put("getid",6);
    
        int i = mapper.updateUser2(map);
        if (i>0){
            System.out.println("修改成功");
        }
        sqlSession.commit();
        sqlSession.close();
    }
    
  • 模糊查询,安全写法

      <select id="getUserById" resultType="com.zhm.pojo.User" parameterType="String">
        select * from mybatis.user
                 where name like #{String};
      </select>
    
    @Test
    public void getUserByName(){
        SqlSession sqlSession = MybatisUtils.getSqlSession();
    
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        User user = mapper.getUserByName("%李%");
        System.out.println(user);
    
        sqlSession.close();
    }
    

优化配置文件mybatis-config

XML(可扩展标记语言)文件是一种用于存储和传输数据的文本文件

配置顺序,必须按着顺序来,标的是重要的

// 属性
properties
// 设置
settings
// 别名
typeAliases
    
typeHandlers
objectFactory
objectWrapperFactory
reflectorFactory
plugins
// 环境
environments
databaseIdProvider
// mapper注册
mappers

属性优化

<!--属性标签,可以从外面导入外部配置文件-->
    <properties resource="db.properties">
<!--可以自己配置属性-->
        <property name="pwd" value="123456"/>
    </properties>
<!--环境标签,可以配置多套-->
    <environments default="development">
        <environment id="development">
            <transactionManager type="JDBC"/>
            <dataSource type="POOLED">
                <property name="driver" value="${driver}"/>
                <property name="url" value="${url}"/>
                <property name="username" value="${username}"/>
                <property name="password" value="${pwd}"/>
            </dataSource>
        </environment>
    </environments>

别名优化

    <typeAliases>
<!--第一种,自定义别名-->
		<typeAlias type="com.zhm.pojo.User" alias="User"></typeAlias>
<!--第二种,传包定义系统帮你首字母小写定义别名,自定义可以用注解-->
        <package name="com.zhm.pojo"/>
    </typeAliases>
// 第二种的注解
@Alias("hello")
public class User {}
  • 一般实体类少用第一种,多就第二种

设置优化

这是 MyBatis 中极为重要的调整设置,它们会改变 MyBatis 的运行时行为。 下表描述了设置中各项设置的含义、默认值等。

配置_MyBatis中文网直接看链接

映射器Mappers优化(重要)

  • 每一个mapper.xml文件,都需要在mybatis-config中映射注册,否则报错

    Type interface com.zhm.dao.UserMapper is not known to the MapperRegistry.

  • 三种

    1. 映射xml资源
    2. 映射xml资源对应的类(类和xml资源要同名同包)
    3. 映射xml资源的包(类和xml资源要同名同包)
  •     <mappers>
    <!--        &lt;!&ndash;第一种,直接映射Mapeer.xml资源地址&ndash;&gt;-->
            <mapper resource="com/zhm/dao/UserMapper.xml"/>
            <!--第二种,映射Mapeer.xml对应的类,要求xml和对应类同名同包-->
    <!--        <mapper class="com.zhm.dao.UserMapper"/>-->
            <!--第三种,映射Mapeer.xml所在包,要求xml和对应类同名同包-->
    <!--        <package name="com.zhm.dao"/>-->
        </mappers>
    

补充,sqlsessionfactory相对于连接池image-20250219220337988

解决属性名和字段名不一致

  • 数据库列字段和实体类属性不一致

  • 类似数据库pwd,实体类password

  • 用resultmap映射解决

    <!--column代表数据库列名,property代表实体类属性-->
      <resultMap id="gUL" type="User">
        <result column="pwd" property="password"/>
      </resultMap>
    
    <!--gUL代表resultMap的id-->
      <select id="getUserList" resultMap="gUL">
        select * from mybatis.user;
      </select>
    

日志工厂

  • mybatis-config.xml里配置
  • 设置加上logImpl属性

STDOUT_LOGGING

  • 标准日志输出

  • <!--设置-->
        <settings>
    <!--日志工厂,注意键值的空格和大小写,要跟官网一致-->
            <setting name="logImpl" value="STDOUT_LOGGING"/>
        </settings>
    
    日志输出
    F:\Environment\java\jdk1.8\bin\java.exe -ea -Didea.test.cyclic.buffer.size=1048576 "...
    Logging initialized using 'class org.apache.ibatis.logging.stdout.StdOutImpl' adapter.
    PooledDataSource forcefully closed/removed all connections.
    PooledDataSource forcefully closed/removed all connections.
    PooledDataSource forcefully closed/removed all connections.
    PooledDataSource forcefully closed/removed all connections.
    Opening JDBC Connection
    Created connection 1891546521.
    Setting autocommit to false on JDBC Connection [com.mysql.jdbc.JDBC4Connection@70beb599]
    ==>  Preparing: select * from mybatis.user;
    ==> Parameters: 
    <==    Columns: id, name, pwd
    <==        Row: 1, xiaohong, 123456
    <==        Row: 2, xiaolan, 12345
    <==        Row: 3, xiaohuang, 1234
    <==        Row: 6, xax, 135792
    <==      Total: 4
    User{id=1, name='xiaohong', password='123456'}
    User{id=2, name='xiaolan', password='12345'}
    User{id=3, name='xiaohuang', password='1234'}
    User{id=6, name='xax', password='135792'}
    Resetting autocommit to true on JDBC Connection [com.mysql.jdbc.JDBC4Connection@70beb599]
    Closing JDBC Connection [com.mysql.jdbc.JDBC4Connection@70beb599]
    Returned connection 1891546521 to pool.
    
    进程已结束,退出代码0
    

LOG4J

  • 可以输出到文件,可以自定义格式,方便,一般用这个

    用法

    1. 先导依赖到pom.xml,mybatis-config.xml的setting设置配置

      <!--设置-->
          <settings>
      <!--日志工厂,注意键值的空格和大小写,要跟官网一致-->
              <setting name="logImpl" value="LOG4J"/>
          </settings>
      
    2. 配置log4j的配置文件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.Threshold=DEBUG
      log4j.appender.console.layout = org.apache.log4j.PatternLayout
      log4j.appender.console.layout.ConversionPattern=[%c]-%m%n
      
      #文件输出的相关设置
      log4j.appender.file = org.apache.log4j.RollingFileAppender
      log4j.appender.file.File=./log/kuang.log
      log4j.appender.file.MaxFileSize=10mb
      log4j.appender.file.Threshold=DEBUG
      log4j.appender.file.layout=org.apache.log4j.PatternLayout
      log4j.appender.file.layout.ConversionPattern=[%p][%d{yy-MM-dd}][%c]%m%n
      
      #日志输出级别
      log4j.logger.org.mybatis=DEBUG
      log4j.logger.java.sql=DEBUG
      log4j.logger.java.sql.Statement=DEBUG
      log4j.logger.java.sql.ResultSet=DEBUG
      log4j.logger.java.sql.PreparedStatement=DEBUG
      
    3. 使用,导包名

      import org.apache.log4j.Logger;
      import org.apache.log4j.Priority;

      package com.zhm.dao;
      
      import com.zhm.pojo.User;
      import com.zhm.utils.MybatisUtils;
      import org.apache.ibatis.session.SqlSession;
      import org.apache.log4j.Logger;
      import org.apache.log4j.Priority;
      import org.junit.Test;
      
      import java.util.HashMap;
      import java.util.List;
      import java.util.Map;
      
      public class UserDaoTest {
      
          public static Logger logger = Logger.getLogger(UserDaoTest.class);
      
          @Test
          public void test(){
              SqlSession sqlSession = MybatisUtils.getSqlSession();
              // 打印sqlSession
              logger.info(sqlSession);
      
              UserMapper mapper = sqlSession.getMapper(UserMapper.class);
              List<User> userList = mapper.getUserList();
      
              for (User user : userList) {
                  System.out.println(user);
              }
      
              sqlSession.close();
          }
      
          @Test
          public void testLog4j(){
              // 可以放在程序中用于打印测试
              logger.info("进入info");
              logger.debug("进入debug");
              logger.error("进入error");
          }
      
      }
      

注解开发

  • 一般简单的用注解,mapper.xml配置更全能,注解更简单

  • 注解不能用resultmap解决属性名和字段名不一致

  • 本质就是通过注解获取类的信息,获取到方法信息(参数,返回,注解),通过注解自动实现

  • 过程

    1. 在接口里面写新方法,加上@注解,编写sql,注意sql不能错

      @Select("select * from user;")
      List<User> getUserList2();
      
    2. mybatis-config.xml(mybatis配置文件)配置注册mapper,用class=的方式

      <mappers>
          <!--注解开发也要注册mapper,用class来注册-->
          <mapper class="com.zhm.dao.UserMapper"/>
      </mappers>
      
    3. 测试

      @Test
      public void getUserList2(){
          SqlSession sqlSession = MybatisUtils.getSqlSession();
          UserMapper mapper = sqlSession.getMapper(UserMapper.class);
          List<User> userList2 = mapper.getUserList2();
          for (User user : userList2) {
              System.out.println(user);
          }
      
          sqlSession.close();
      }
      
  • 自动提交

    修改mybatis.utils工具类

    本质是重载方法里面,不写autocommit默认false

    public static SqlSession getSqlSession(){
        // 设置自动提交为true,增删改就不用手动commit
        SqlSession sqlSession = sqlSessionFactory.openSession(true);
        return sqlSession;
    }
    
  • 增删改查

    // @Param 多个参数,基本类型或者String,要使用@param注解
    // 否则会MyBatis 会将参数封装成map对象
    // {param1=id, param2=name}
    @Select("select * from user where id = #{uid} and name = #{uname};")
    User getUserByIdAndName(@Param("uid") int id, @Param("uname") String name);
    
    @Insert("insert into user(id,name,pwd) values (#{id},#{name},#{password})")
    int addUser(User user);
    
    // password sql引用要用实体类定义的变量名
    @Update("update user set name=#{name},pwd=#{password} where id=#{id}")
    int updateUser(User user);
    
    // @param注解 sql里引用要用注解里定义的
    @Delete("delete from user where id=#{uid}")
    int deleteUser(@Param("uid") int id);
    
  • 关于@Param

    尽量多用

    1. 基本参数和string要加上
    2. 引用类型不需要
    3. 只有单个参数不需要,但是尽量多用
    4. sql里面的引用#{x},传入要写设定的@Param("x")

Lombok

  • 简化代码,主要简化实体类的构造器,getset,tostring等等

  • package com.zhm.pojo;
    
    import lombok.AllArgsConstructor;
    import lombok.Data;
    import lombok.NoArgsConstructor;
    import org.apache.ibatis.type.Alias;
    
    /*
    @Data 无参,getset,tostring,hash等等
    @AllArgsConstructor 全参构造器
    @NoArgsConstructor 无参构造器
    其他的见名知意
     */
    @Data
    @AllArgsConstructor
    @NoArgsConstructor
    public class User {
        private int id;
        private String name;
        private String password;
    }
    

重新配置复杂情况环境

步骤

  1. pom.xml导入lombok依赖
  2. 复制配置mybatis-config.xml文件,db.properties,log4j.properties配置文件
  3. 复制utils工具类
  4. 新建java pojo文件夹实体类student teacher,@Data注解
  5. 新建dao层,写studentmapper接口 teachermapper接口
  6. resources新建对应studentmapper.xml和teachermapper.xml配置,要和dao层对应
  7. 在dao层编写注解测试
  8. 测试环境

一对多和多对一复杂情况

  • 多个学生对一个老师 associate
  • 一个老师对多个学生 collection
  • 本质是多表查询
    1. 连表查询
    2. 子查询

多对一

  • student实体类有list teacher
  • association处理复杂属性teacher
<mapper namespace="com.zhm.dao.StudentMapper">
    <!--连表查询-->
    <select id="getStudent" resultMap="StudentTeacher">
        select s.id sid,s.name sname,t.name tname,t.id tid
        from student s,teacher t
        where s.tid=t.id;
    </select>

    <resultMap id="StudentTeacher" type="Student">
        <result property="id" column="sid"/>
        <result property="name" column="sname"/>
        <!--复杂属性单独处理 -->
        <association property="teacher" javaType="Teacher">
            <result property="name" column="tname"/>
            <result property="id" column="tid"/>
        </association>
    </resultMap>


    <!--子查询-->
    <select id="getStudent2" resultMap="StudentTeacher2">
        select * from student;
    </select>

    <resultMap id="StudentTeacher2" type="Student">
        <result property="id" column="id"/>
        <result property="name" column="name"/>
        <!--复杂属性单独处理 -->
        <association property="teacher" column="tid" javaType="Teacher" select="getTeacher"/>
    </resultMap>

    <select id="getTeacher" resultType="teacher">
        select * from teacher where id=#{tid};
    </select>
</mapper>

一对多

  • teachrt实体类有list students
  • collection 处理复杂属性student
  • ofType 跟集合有关,设置为集合内的泛型类型,javatype是arraylist
<mapper namespace="com.zhm.dao.TeacherMapper">
    <select id="getTeacherById" parameterType="int" resultMap="getTeacher">
        select t.id tid,t.name tname,s.id sid,s.name sname
        from student s,teacher t
        where s.tid=t.id and t.id=#{tid};
    </select>

    <resultMap id="getTeacher" type="Teacher">
        <result property="id" column="tid"/>
        <result property="name" column="tname"/>
        <collection property="students" ofType="Student">
            <result property="name" column="sname"/>
            <result property="id" column="sid"/>
            <result property="tid" column="tid"/>
        </collection>
    </resultMap>
    
    <!-------------------------------------------------------------------------------->

    <select id="getTeacherById2" parameterType="int" resultMap="getTeacher2">
        select * from teacher where id=#{tid};
    </select>

    <resultMap id="getTeacher2" type="Teacher">
        <!--一样的可以省略,mybatis会能帮你匹配-->
<!--        <result property="id" column="id"/>-->
<!--        <result property="name" column="name"/>-->
        <!--column="id"传给下面查询语句老师的id-->
        <collection property="students" column="id" javaType="ArrayList" ofType="Student" select="TeacherStudent"/>
    </resultMap>

    <select id="TeacherStudent" resultType="student">
        select * from student where tid=#{id};
    </select>

</mapper>

总结

image-20250225174602582

动态sql

环境搭建

  1. 导依赖
  2. 配置资源文件
  3. sqlsession工具类
  4. 工具数据库创pojo实体类Blog
  5. BlogMapper接口和BlogMapper.xml实现类,记得在mybatis-config.xml注册
  • 注意点 驼峰命名自动映射,在 mybatis-config.xml里面配置
<!--mapUnderscoreToCamelCase是否开启驼峰命名自动映射,即从经典数据库列名 A_COLUMN 映射到经典 Java 属性名 aColumn-->
        <setting name="mapUnderscoreToCamelCase" value="true"/>

if

  • 如果test为true,则执行后面
<select id="queryBlogIf" parameterType="map" resultType="blog">
    select * from mybatis.blog where 1=1
    <if test="title!=null">and title=#{title}</if>
    <if test="author!=null">and author=#{author}</if>
</select>

choose(when,otherwise)

  • 跟switch一样,otherwise就是default
<!--跟java switch一样,从上到下when的条件满足就执行条件后sql,然后结束,都不满足就执行最后otherwise的sql-->
<!--where标签可以帮你忽略首句and,如果where内没有满足的,就会忽略where-->
    <select id="queryBlogChoose" parameterType="map" resultType="blog">
        select * from mybatis.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>

trim(where,set)

  • 本质就是帮助写sql,帮你忽略and和,的工具
<!--where标签可以帮你忽略首句and,如果where内没有满足的,就会忽略where-->
    <select id="queryBlogChoose" parameterType="map" resultType="blog">
        select * from mybatis.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="updateBlogSet" parameterType="map">
        update mybatis.blog
        <set>
        <if test="title!=null">
            title=#{title},
        </if>
        <if test="author!=null">
            author=#{author}
        </if>
        </set>
        <where>
            <if test="views!=null">
                views=#{views}
            </if>
        </where>
    </update>

sql片段和foreach

  • sql片段就是复用sql代码,打包重复的sql,写id,调用时用include标签

  • foreach执行迭代遍历集合

    <!--select * from blog where (views=1000 or views=2000 or views=3000)-->
    <!--迭代,传入list集合,collection对应k,item为sql#{}内引用-->
    <!--当使用可迭代对象或者数组时,index 是当前迭代的序号,item 的值是本次迭代获取到的元素。
    当使用 Map 对象(或者 Map.Entry 对象的集合)时,index 是键,item 是值。-->
        <select id="queryBlogForeach" parameterType="map" resultType="blog">
            select * from mybatis.blog
            <where>
                <include refid="myForeach"></include>
            </where>
        </select>
    
        <sql id="myForeach">
            <foreach collection="viewss" item="views" open="(" separator="or" close=")">
                views=#{views}
            </foreach>
        </sql>
    

总结

  • 动态sql就算在sql里面进行逻辑运算,用的最多的是if
  • 动态sql编写,先写静态sql,再根据静态来编写动态

缓存

  • 减少并发,每次查询一样数据都要重新执行sql很消耗资源
  • 一般缓存作用于多读少改的数据,存入缓存(内存),相反,多改少读的数据存磁盘

一级缓存

  • 作用域在sqlsession存活时间内

  • 一级缓存,一般只在读同一数据才生效

  • 几种一级缓存无效情况

    1. 清除一级缓存
      sqlSession.clearCache();

    2. 执行增删改

      后可能影响数据,缓存数据可能改变,所以要重新查询

      mapper.updateUser(new User(2,"xiaoer","axxaa"));

  • 一级缓存就是Map

  • package com.zhm.dao;
    
    import com.zhm.pojo.User;
    import com.zhm.utils.MybatisUtils;
    import org.apache.ibatis.session.SqlSession;
    import org.junit.Test;
    
    public class UserMapperTest {
    
        @Test
        public void test(){
            // 一级缓存只在sqlSession开启关闭内,且查询同一数据有效,
            // 查询同一记录执行一次查询
            SqlSession sqlSession = MybatisUtils.getSqlSession();
            UserMapper mapper = sqlSession.getMapper(UserMapper.class);
            User user = mapper.queryUser(1);
            System.out.println(user);
            System.out.println("===============================");
            // 清除一级缓存,重新执行sql
    //        sqlSession.clearCache();
            // 执行增删改后可能影响数据,缓存数据可能改变,所以要重新查询
    //        mapper.updateUser(new User(2,"xiaoer","axxaa"));
            User user2 = mapper.queryUser(2);
            System.out.println(user2);
            User user3 = mapper.queryUser(1);
            System.out.println(user3);
            sqlSession.close();
        }
    }
    

二级缓存

  • 作用于整个mapper

    1. mybatis-config.xml setting 开启全局缓存(默认就是开启)

    2. mapper配置

      <cache/>
      
      <cache
             eviction="FIFO"
             flushInterval="60000"
             size="512"
             readOnly="true"/>
      
    3. 测试

      @Test
      public void test2(){
          // 二级缓存,整个mapper都有效果UserMapper.class
          // 开启二级缓存后,当会话提交或者关闭,一级缓存会继承给二级缓存
          SqlSession sqlSession1 = MybatisUtils.getSqlSession();
          UserMapper mapper1 = sqlSession1.getMapper(UserMapper.class);
          User user1 = mapper1.queryUser(1);
          System.out.println(user1);
          sqlSession1.close();
      
          System.out.println("------------------------------------------------------");
      
          SqlSession sqlSession2 = MybatisUtils.getSqlSession();
          UserMapper mapper2 = sqlSession2.getMapper(UserMapper.class);
          User user2 = mapper2.queryUser(1);
          System.out.println(user2);
          sqlSession2.close();
      }
      
  • 注意点

    readOnly 默认为false,实体类记得实现Serializable接口,序列化

    • 序列化就是把对象转换成一种通用的格式,方便存储、传输和共享。
    • MyBatis 二级缓存需要序列化实体类,因为缓存数据可能被多个会话共享,或者存储到不同的地方(如硬盘、远程缓存)。
    • 如果实体类不序列化,MyBatis 就无法正确存储和读取缓存数据。

缓存查询顺序

  • 用户从上面进来,先看二级,再一级,都没有再执行连接数据库查询sql

image-20250226154019665

posted @ 2025-04-22 22:09  学习java的白菜  阅读(22)  评论(0)    收藏  举报