Mybatis框架(全部基础知识)

news2024/11/27 9:32:58

👌 棒棒有言:也许我一直照着别人的方向飞,可是这次,我想要用我的方式飞翔一次!人生,既要淡,又要有味。凡事不必太在意,一切随缘,缘深多聚聚,缘浅随它去。凡事看淡点看开些,顺其自然,无意于得,就无所谓失。人生,看轻看淡多少,痛苦就远离你多少。

👌 本章简介:MyBatis本是apache的一个开源项目iBatis,2010年这个项目由apache software foundation迁移到了google code,并且改名为MyBatis。2013年11月迁移到Github。iBATIS一词来源于“internet”和“abatis”的组合,是一个基于Java的持久层框架。iBATIS提供的持久层框架包括SQL Maps和Data Access Objects(DAOs)。

当前,最新版本是MyBatis 3.5.11,其发布时间是2022年09月18日。

👍  作者:get棒棒给个关注呗

👍非常重要 :

如果不介意麻烦动动你们的小手点个关注

Mybatis框架

MyBatis简介

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

2010年这个项目由apache software foundation 迁移到了google code,并且改名为MyBatis 。2013年11月迁移到Github。

回顾JDBC的使用步骤:

  • 1.加载驱动

Class.forName("com.mysql.jdbc.Driver");
  • 2.获取连接对象

DiverManerger.getConnection(url,username,password)
  • 3.获取执行sql的Statement对象

connection.CreateStatement();
  • 4.执行sql语句

  • 5.处理结果集

  • 6.释放连接

connection.Close()

与JDBC相比:

  1. Mybatis通过参数映射方式,可以将参数灵活的配置在SQL语句中的配置文件中,避免在Java类中配置参数

  2. Mybatis通过输出映射机制,将结果集的检索自动映射成相应的Java对象,避免对结果集手工检索

  3. Mybatis可以通过Xml配置文件对数据库连接进行管理

MyBatis整体架构及运行流程

Mybatis整体构造由 数据源配置文件、Sql映射文件、会话工厂、会话、执行器和底层封装对象组成

1.数据源配置文件

通过配置的方式将数据库的配置信息从应用程序中独立出来,由独立的模块管理和配置。Mybatis的数据源配置文件包含数据库驱动、数据库连接地址、用户名密码、事务管理等,还可以配置连接池的连接数、空闲时间等

一个MapConfig.xml基本的配置信息如下:

<?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">
   <!-- 事务的管理 JDBC  MANAGED-->
      <transactionManager type="JDBC"/>
   <!-- 数据源 POOLED UNPOOLED JNDI -->
      <dataSource type="POOLED">
        <property name="driver" value="${driver}"/>
        <property name="url" value="${url}"/>
        <property name="username" value="${username}"/>
        <property name="password" value="${password}"/>
      </dataSource>
    </environment>
  </environments>
  <mappers>
    <mapper resource="org/mybatis/example/BlogMapper.xml"/>
  </mappers>
</configuration>

mybatis mapper文件映射

<!-- 使用相对于类路径的资源引用 -->
<mappers>
  <mapper resource="org/mybatis/builder/AuthorMapper.xml"/>
</mappers>
<!-- 使用映射器接口实现类的完全限定类名
    mybais去加载class对应的接口,然后还会去加载该接口同目录下的同名xml文件 
-->
<mappers>
  <mapper class="org.mybatis.builder.AuthorMapper"/>
</mappers>
<!-- 将包内的映射器接口实现全部注册为映射器   
 使用package元素批量注册Mapper接口
  1.包名和接口所在的包名字一致
  2.mapper文件的名字和接口的名字一致
  3.创建包是使用/分割
-->
<mappers>
  <package name="org.mybatis.builder"/>
</mappers>

设置资源文件路径

Maven中默认是只会打包resource下的资源文件。如果我们的文件不放在resource, 则需要通过配置告知Maven

<resources>
    <resource>
        <directory>src/main/java</directory>
        <includes>
            <include>**/*.properties</include>
            <include>**/*.xml</include>
        </includes>
        <filtering>false</filtering>
    </resource>
     <resource>
        <directory>src/main/resources</directory>
        <includes>
          <include>**/*.properties</include>
          <include>**/*.xml</include>
          <include>**/*.tld</include>
        </includes>
        <filtering>false</filtering>
      </resource>
</resources>

2.Sql映射文件

Mybatis中所有数据库的操作都会基于该映射文件和配置的sql语句,在这个配置文件中可以配置任何类型的sql语句。框架会根据配置文件中的参数配置,完成对sql语句以及输入输出参数的映射配置。

Mapper.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="命名空间">
​
<select id="方法名" resultMap="返回值类型" parameterType="参数类型">
​
-- sql语句
​
</select>
​
</mapper>

3.会话工厂与会话

Mybatis中会话工厂SqlSessionFactory类可以通过加载资源文件,读取数据源配置MapConfig.xml信息,从而产生一种可以与数据库交互的会话实例SqlSession,会话实例SqlSession根据Mapper.xml文件中配置的sql,对数据库进行操作。

4.运行流程

会话工厂SqlSessionFactory通过加载资源文件获取MapConfig.xml配置文件信息,然后生成可以与数据库交互的会话实例SqlSession。会话实例可以根据Mapper配置文件中的Sql配置去执行相应的增删改查操作

执行流程图:

mybatis实现增删改查

public class TestStudent {
​
    @Test
    public void test01(){
​
        try {//加载配置文件
            InputStream in = Resources.getResourceAsStream("config/mybatis-config.xml");
            //获取sqlSession对象
            SqlSession sqlSession = new SqlSessionFactoryBuilder().build(in).openSession();
            //查询所有学生信息
        List<Student> students = sqlSession.selectList("cn.kgc.mybatis.dao.StudentDao.getAll"); 
            students.forEach(student -> System.out.println(student) );
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
​
    @Test
    public void test02(){//查询一个学生信息
​
        try {//加载配置文件
            InputStream in = Resources.getResourceAsStream("config/mybatis-config.xml");
            //获取sqlSession对象
            SqlSession sqlSession = new SqlSessionFactoryBuilder().build(in).openSession();
            //根据用户名查询一个学生信息
            Student student = sqlSession.selectOne("cn.kgc.mybatis.dao.StudentDao.findOne","tom");
            System.out.println(student);
            sqlSession.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    @Test
    public void test03() {//添加一个学生信息
​
        try {//加载配置文件
            InputStream in = Resources.getResourceAsStream("config/mybatis-config.xml");
            //获取sqlSession对象
            SqlSession sqlSession = new SqlSessionFactoryBuilder().build(in).openSession();
            //添加一个学生信息
            Student student = Student.builder().stuBirth(new Date()).stuName("lilei").stuNo("2021073001").stuSex("男").build();
            int i = sqlSession.insert("cn.kgc.mybatis.dao.StudentDao.addOne", student);
            System.out.println(i);
            sqlSession.commit();
            sqlSession.close();
​
        } catch (IOException e) {
            e.printStackTrace();
        }
​
    }
    @Test
    public void test04() {//删除一个学生信息
​
        try{
            InputStream in = Resources.getResourceAsStream("config/mybatis-config.xml");
            //获取sqlSession对象 同时可设置事务的自动提交  openSession(true)
            SqlSession sqlSession = new SqlSessionFactoryBuilder().build(in).openSession();
            int delete = sqlSession.delete("cn.kgc.mybatis.dao.StudentDao.delOne","lilei" );
            sqlSession.commit();
            sqlSession.close();
            System.out.println(delete);
        }catch (Exception e){
            e.printStackTrace();
        }
​
    }
​
    @Test
    public void test05() {//修改一个学生信息
​
        try{
            InputStream in = Resources.getResourceAsStream("config/mybatis-config.xml");
            //获取sqlSession对象
            SqlSession sqlSession = new SqlSessionFactoryBuilder().build(in).openSession();
​
            Student student = Student.builder().stuBirth(new Date()).stuName("lili").stuNo("2021073001").stuSex("女").build();
            int delete = sqlSession.update("cn.kgc.mybatis.dao.StudentDao.updateStudent",student);
            sqlSession.commit();
            sqlSession.close();
            System.out.println(delete);
        }catch (Exception e){
            e.printStackTrace();
        }
​
​
    }
​
}
​

mybatis中使用log4j日志工具

1.配置mybatis-config.xml

<!--    开启日志-->
 <setting name="logImpl" value="LOG4J"/>

开启驼峰命名

<!--    设置驼峰命名-->
 <setting name="mapUnderscoreToCamelCase" value="true"/>

设置别名

<typeAliases>
    <!--设置别名-->
    <package name="cn.kgc.mybatis.pojo"/>
</typeAliases>

2.配置log4j.properties文件,放置在resources目录下

log4j.rootLogger=DEBUG,Console
​
#Console
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=%d [%t] %-5p [%c] - %m%n
​
log4j.logger.org.apache=ERROR
log4j.logger.org.mybatis=ERROR
log4j.logger.org.springframework=ERROR
​
#这个需要
log4j.logger.log4jdbc.debug=ERROR
log4j.logger.com.gk.mapper=ERROR
log4j.logger.jdbc.audit=ERROR
log4j.logger.jdbc.resultset=ERROR
#这个打印SQL语句非常重要
log4j.logger.jdbc.sqlonly=DEBUG
log4j.logger.jdbc.sqltiming=ERROR
log4j.logger.jdbc.connection=FATAL

使用mapper代理对象实现增删改查

public class TestStudentMapper {
    SqlSessionFactory factory;
    @Before
    public void init(){
        try {
            InputStream  in = Resources.getResourceAsStream("config/mybatis-config.xml");
            SqlSessionFactoryBuilder sfb = new SqlSessionFactoryBuilder();
            factory = sfb.build(in);
        } catch (IOException e) {
            e.printStackTrace();
        }
​
​
    }
    @Test
    public void test01(){
            //开启事务自动提交
            SqlSession sqlSession = factory.openSession(true);
            //获取dao层的代理对象
            StudentDao studentDao = sqlSession.getMapper(StudentDao.class);
            List<Student> students = studentDao.getAll();
            students.forEach(student -> System.out.println(student));
    }
​
    @Test
    public void test02(){ //添加数据
​
        SqlSession sqlSession = factory.openSession(true);
        Student student = Student.builder().stuSex("男").stuNo("2021073100").stuName("李四").stuBirth(new Date()).build();
        StudentDao studentDao = sqlSession.getMapper(StudentDao.class);
        Integer line = studentDao.addOne(student);
        System.out.println(line);
    }
​
    @Test
    public  void test03(){//删除一条数据
        SqlSession sqlSession = factory.openSession(true);
        StudentDao studentDao = sqlSession.getMapper(StudentDao.class);
        Integer line = studentDao.delOne("李四");
        System.out.println(line);
    }
​
    @Test
    public void test04() { //修改数据
        SqlSession sqlSession = factory.openSession(true);
        StudentDao studentDao = sqlSession.getMapper(StudentDao.class);
        Student student = Student.builder().stuSex("女").stuNo("2021073100").stuName("李四").stuBirth(new Date()).build();
        Integer line = studentDao.updateOne(student);
        System.out.println(line);
​
    }
    
    @Test
    public void test06(){//模糊查询一个学生信息 一个参数
        SqlSession sqlSession = factory.openSession(true);
        StudentDao studentDao = sqlSession.getMapper(StudentDao.class);
​
        List<Student> students = studentDao.selectLikeName("li");
        System.out.println(students.toString());
​
    }
​
    @Test
    public void test07(){//模糊查询一个学生信息 两个参数
        SqlSession sqlSession = factory.openSession(true);
        StudentDao studentDao = sqlSession.getMapper(StudentDao.class);
​
        List<Student> students = studentDao.selectLikeName2("li", "2021072902");
        System.out.println(students.toString());
​
​
    }
     @Test
    public void test08(){//模糊查询一个学生信息 一个集合参数  mapper文件中按照key取值
        SqlSession sqlSession = factory.openSession(true);
        StudentDao studentDao = sqlSession.getMapper(StudentDao.class);
​
        HashMap<String, String> map = new HashMap<>();
        map.put("stuname","li");
        map.put("stuno", "2021072902");
        List<Student> students = studentDao.selectLikeName3(map);
        System.out.println(students.toString());
    }
​
}
​

Mybatis的获取参数的方式

方式1:${} 字符串拼接

方式2:#{} 占位符

1.Mapper接口参数为单个参数

 <delete id="delUserById" parameterType="int">
        delete from user where id = #{id}
 </delete>
 
  <delete id="delUserById" parameterType="int">
        delete from user where id = ${id}
 </delete>
 
 注:如何参数是String类型使用${}获取参数是需要手动添加引号 ''

2.Mapper接口参数是多个参数的获取

mybatis在处理多个参数时,会将多个参数保存到map集合中会 以 agr0 ,agr1或param1 param2为键 以参数位置进行存储

User selectUserByUserNameAndPassword(String username,String password);
 <select id="selectUserByUserNameAndPassword" resultType="user">
        select  * from user where user_name = #{arg0} and password = #{arg1}
 </select>

3.将参数设为map集合进行数据的传递

User selectUserByMap(Map map);
<select id="selectUserByMap" resultType="cn.kgc.mybatis.entity.User">
        select  * from user where user_name = #{username} and password = #{password}
</select>

4.通过注解@param("键名")设置参数的获取名字

User selectUserByUserNameAndPassword(@param("username")String username,(@param("password")String password);
<select id="selectUserByUserNameAndPassword" resultType="user">
        select  * from user where user_name = #{username} and password = #{password}
</select>
​
或者
​
<select id="selectUserByUserNameAndPassword" resultType="user">
        select  * from user where user_name = #{param1} and password = #{param2}
</select>
​

5.将多个参数设置成对象进行数据的传递

int insertUser(User user);
 <insert id="insertUser" parameterType="user" useGeneratedKeys="true" keyProperty="id" >
         insert into user values ( #{id},#{userName},#{password})
 </insert>

Mybatis中的模糊查询

方式1:

SELECT * FROM tableName WHERE name LIKE #{text}
​
-- 传递的参数需要拼接  ‘%text%’

方式2:

SELECT * FROM tableName WHERE name LIKE '%${text}%';
 -- 使用$替代# 参数无需在拼接%  存在sql注入

方式3

SELECT * FROM tableName WHERE name LIKE CONCAT('%', #{text}), '%');
-- 使用mysql的函数  实现拼接

6.批量删除

int deleteMore(String ids);
  <delete id="deleteMore">
        delete from user where id in(${ids})
   </delete>

mapper中自定义映射

自定义映射的用法之一,解决表格查询的字段名和实体类中不一致的情况

<resultMap id="userMap" type="user">
        <id column="id" property="id"></id>
        <result column="user_name" property="userName"></result>
        <result column="password" property="password"></result>
</resultMap>

mybatis对象的关联关系

一对多关系处理(一方)

<resultMap id="selectByEIdMap" type="cn.kgc.mybatis.entity.Emp">
        <result column="id" property="dept.id" ></result>
        <result column="dname" property="dept.dName"></result>
 </resultMap>
​
​
    <resultMap id="selectByEIdMap2" type="cn.kgc.mybatis.entity.Emp">
        <id column="eid" property="eId"></id>
        <result column="ename" property="EName"></result>
        <result column="age" property="age"></result>
        <result column="deptno" property="deptNo"></result>
        <!--实体对象标识-->
       <association property="dept" javaType="dept">
           <id column="id" property="id"></id>
           <result column="dname" property="dName"></result>
       </association>
    </resultMap>
​
    <!-- 分步查询 -->
    <resultMap id="selectByEIdMap3" type="cn.kgc.mybatis.entity.Emp">
        <id column="eid" property="eId"></id>
        <result column="ename" property="EName"></result>
        <result column="age" property="age"></result>
        <result column="deptno" property="deptNo"></result>
        <association property="dept" select="cn.kgc.mybatis.mapper.DeptMapper.selectById" 
                                    column="deptno" 
                                    fetchType="eager">
        </association>
    </resultMap>
​
注:延迟加载设置  :
        1. <setting name="lazyLoadingEnabled" value="true"/> 
        2. <setting name="aggressiveLazyLoading" value="false"/>  3.4.1之前的版本需要设置
​
    <select id="selectByEId" resultMap="selectByEIdMap2">
            select  * from emp left  join  dept on  emp.deptno = dept.id  where eid = #{eid}
    </select>
​
    <select id="selectByEId2" resultMap="selectByEIdMap3">
            select  * from emp  where eid = #{eid}
    </select>

一对多关系处理(多方)

 <resultMap id="BaseResultMap" type="cn.kgc.mybatis.entity.Dept">
            <id property="id" column="id" />
            <result property="dName" column="dname" />
            <collection property="emps" ofType="emp">
                <id column="eid" property="eId"></id>
                <result column="ename" property="EName"></result>
                <result column="age" property="age"></result>
                <result column="deptno" property="deptNo"></result>
            </collection>
    </resultMap>
​
​
    <resultMap id="BaseResultMap2" type="cn.kgc.mybatis.entity.Dept">
        <id property="id" column="id" />
        <result property="dName" column="dname" />
        <collection property="emps" select="cn.kgc.mybatis.mapper.EmpMapper.selectByDeptId" column="id"></collection>
    </resultMap>
​
    <select id="selectById" resultType="dept">
        select  * from dept where id = #{id}
    </select>
​
    <select id="selectById2" resultMap="BaseResultMap">
        select emp.* ,dept.* from dept left join emp on dept.id = emp.deptno where id = #{id}
    </select>
​
    <select id="selectById3" resultMap="BaseResultMap2">
        select dept.* from dept  where id = #{id}
    </select>

mybatis动态sql

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

动态SQL:if 语句

根据 stu_name 和 stu_sex 来查询数据。如果stu_name为空,那么将只根据stu_sex来查询;反之只根据stu_name来查询

首先不使用 动态SQL 来书写

<select id="selectStudent" resultType="student" parameterType="cn.kgc.mybatis.pojo.Student">
    select * from user where stu_name=#{stu_name} and stu_sex=#{stu_sex}
</select>

可以发现,如果 #{stu_name} 为空,那么查询结果也是空,如何解决这个问题呢?使用 if 来判断

<select id="selectStudent" resultType="student" parameterType="cn.kgc.mybatis.pojo.Student">
     select * from student where  
     <if test="stu_name != null">
               stu_name=#{stu_name}
     </if>
    <if test="stu_sex!= null">
           and stu_sex=#{stu_sex}
    </if>
</select>

 这样写我们可以看到,如果 sex 等于 null,那么查询语句为 select * from student where stu_name=#{stu_name},但是如果stu_name 为空呢?那么查询语句为 select * from user where and stu_sex=#{sex},这是错误的 SQL 语句,如何解决呢?

if+where 语句

<select id="selectStudent" resultType="student" parameterType="cn.kgc.mybatis.pojo.Student">
     select * from student 
        <where> 
                 <if test="stu_name != null">
                         stu_name=#{stu_name}
                 </if>
                 <if test="stu_sex!= null">
                         and stu_sex=#{stu_sex}
                 </if>
        </where> 
</select>

这个where标签会知道如果它包含的标签中有返回值的话,它就插入一个where。此外,如果标签返回的内容是以AND 或OR 开头的,则它会剔除掉

动态SQL:if+set 语句

上面的对于查询 SQL 语句包含 where 关键字,如果在进行更新操作的时候,含有 set 关键词

<update id="updateStudentById" parameterType="cn.kgc.mybatis.pojo.Student">
    update student stu
        <set>
            <if test="stuname != null and stuname != ''">
                stu.stu_name = #{stuName},
            </if>
            <if test="stusex != null and stusex != ''">
                stu.stu_sex = #{stuSex}
            </if>
        </set>
     where id=#{id}
</update>
  • 如果第一个条件 username 为空,那么 sql 语句为:update user u set u.sex=? where id=?

  • 如果第一个条件不为空,那么 sql 语句为:update user u set u.username = ? ,u.sex = ? where id=?

动态SQL:choose(when,otherwise) 语句

有时候,我们不想用到所有的查询条件,只想选择其中的一个,查询条件有一个满足即可,使用 choose 标签可以解决此类问题,类似于 Java 的 switch 语句

<select id="selectStudentByChoose" resultType="com.ys.po.User" parameterType="com.ys.po.User">
      select * from student
      <where>
          <choose>
              <when test="id !='' and id != null">
                  id=#{id}
              </when>
              <when test="username !='' and username != null">
                  and username=#{username}
              </when>
              <otherwise>
                  and sex=#{sex}
              </otherwise>
          </choose>
      </where>
 </select>

这里我们有三个条件,id,username,sex,只能选择一个作为查询条件

  • 如果 id 不为空,那么查询语句为:select * from user where id=?

  • 如果 id 为空,那么看username 是否为空,如果不为空,那么语句为 select * from user where username=?;

  • 如果 username 为空,那么查询语句为 select * from user where sex=?

动态SQL:trim 语句

trim标记是一个格式化的标记,可以完成set或者是where标记的功能

用 trim 改写上面的 if+where 语句

<select id="selectStudent" resultType="student" parameterType="cn.kgc.mybatis.pojo.Student">
     select * from user 
       <trim prefix="where" prefixOverrides=" and | or">
            <if test="stu_name != null">
                stu_name=#{stu_name}
             </if>
            <if test="stu_sex!= null">
                and stu_sex=#{stu_sex}
            </if>
       </trim>
</select>
​
  • prefix:前缀  

  • prefixoverride:去掉第一个and或者是or   

用 trim 改写上面的 if+set 语句

<update id="updateStudentById" parameterType="cn.kgc.mybatis.pojo.Student">
    update student stu
       <trim prefix="set" suffixOverrides=",">
            <if test="stuname != null and stuname != ''">
                stu.stu_name = #{stuName},
            </if>
            <if test="stusex != null and stusex != ''">
                stu.stu_sex = #{stuSex}
            </if>
        </trim>
     where id=#{id}
</update>
  • suffix:后缀  

  • suffixoverride:去掉最后一个逗号(也可以是其他的标记,就像是上面前缀中的and一样)

动态SQL: foreach 语句

需求:我们需要查询 user 表中 id 分别为1,2,3的用户,sql语句:

select * from user where id=1 or id=2 or id=3
​
select * from user where id in (1,2,3)

用 foreach 来改写 select * from user where id=1 or id=2 or id=3

<select id="selectUserByListId" parameterType="com.ys.vo.UserVo" resultType="com.ys.po.User">
    select * from user
    <where>
        <!--
            collection:指定输入对象中的集合属性
            item:每次遍历生成的对象
            open:开始遍历时的拼接字符串
            close:结束时拼接的字符串
            separator:遍历对象之间需要拼接的字符串
            select * from user where 1=1 and (id=1 or id=2 or id=3)
          -->
        <foreach collection="ids" item="id" separator="or">
            id=#{id}
        </foreach>
    </where>
</select>

用 foreach 来改写 select * from user where id in (1,2,3)

<select id="selectUserByListId" parameterType="com.ys.vo.UserVo" resultType="com.ys.po.User">
        select * from user 
        <where>
            <!--
                collection:指定输入对象中的集合属性
                item:每次遍历生成的对象
                open:开始遍历时的拼接字符串
                close:结束时拼接的字符串
                separator:遍历对象之间需要拼接的字符串
                select * from user where1=1 and id in (1,2,3)
              -->
            <foreach collection="ids" item="id" open="id in ("separator="," close=") " >
                #{id}
            </foreach>
        </where>
 </select>

动态SQL: SQL 片段

有时候可能某个 sql 语句我们用的特别多,为了增加代码的重用性,简化代码,我们需要将这些代码抽取出来,然后使用时直接调用。

假如我们需要经常根据用户名和性别来进行联合查询,那么我们就把这个代码抽取出来,如下:

<sql id="selectUserByUserNameAndSexSQL">
    <if test="username != null and username != ''">
        AND username = #{username}
    </if>    
    <if test="sex != null and sex != ''">
        AND sex = #{sex}
    </if>
</sql>
<select id="selectUserByUsernameAndSex" resultType="user" parameterType="com.ys.po.User">
    select * from user
    <trim prefix="where" prefixOverrides="and | or">
        <!-- 引用 sql 片段,如果refid 指定的不在本文件中,那么需要在前面加上 namespace -->
        <include refid="selectUserByUserNameAndSexSQL"></include>
        <!-- 在这里还可以引用其他的 sql 片段 -->
    </trim>
</select>

注意:①、最好基于 单表来定义 sql 片段,提高片段的可重用性

    ②、在 sql 片段中最好不要包括 where

mybatis注解开发

public interface StudentDao2 {
​
    @Select("select * from student where stu_no = #{stu_no}")
    @Results({
            @Result(property = "stuNo" ,column="stu_no"),
            @Result(property = "stuSex",column = "stu_sex"),
            @Result(property = "birth",column = "stu_birth")
    })
   List<Student> getAll(String stu_no);
​
    @Insert("insert into student (stu_no,stu_name,stu_sex,stu_birth)values(#{stuNo},#{stuName},#{stuSex},#{birth})")
    int addStudent(Student student);
​
    @Delete("delete from student where stu_no = #{stu_no}")
    int delOne(String stu_no);
​
    @Update("update student set stu_name = #{stuName} where stu_no = #{stuNo}")
    int uptStudent(Student student);
​
}

mybatis缓存

MyBatis 中的缓存就是说 MyBatis 在执行一次SQL查询或者SQL更新之后,这条SQL语句并不会消失,而是被MyBatis 缓存起来,当再次执行相同SQL语句的时候,就会直接从缓存中进行提取,而不是再次执行SQL命令。

mybatis的缓存机制有两级:

(1)一级缓存:一级缓存mybatsi已经为我们自动开启,不用我们手动操作,而且我们是关闭不了的!!但是我们可以手动清除缓存。(SqlSession级别.提交事务,缓存清空)

一级缓存失效的情况:

1.不同的SqlSession对应不同的缓存
2.同一个SqlSession但是查询条件不同
3.同一个SqlSession执行两次相同查询之间做了增删改的操作
4.同一个SqlSession执行两次相同查询之间手动清空缓存

(2)二级缓存:二级缓存需要我们手动开启。(全局级别 SqlSessionFactory)

<!--开启二级缓存-->
​
开启二级缓存需要两个步骤,第一步在mybatis的全局配置文件中配置Setting属性,设置名为cacheEnabled的属性值为true即可
<settings>
        <!-- 
            (1):开启二级缓存,这个全局的配置二级缓存
                   默认是开启的,但是还是需要写上,防止版本的更新 
        -->
        <setting name="cacheEnabled" value="true"/>
</settings> 
​
第二步:在具体需要二级缓存的mapeer映射文件中开启二级缓存,值需要在相应的映射文件中添加一个cache标签即可
2):在相应的映射文件中开启二级缓存
<!-- 开启二级缓存 -->
 <cache></cache>
3)查询数据封装的实体类要实现序列化的接口
4)二级缓存需要在一级缓存关闭或者提交后生效
​
二级缓存失效的条件:
1.在两次查询之间进行了任意的增删改操作,一级二级缓存同时失效
​
 @Test
    public void test02(){//验证mybatis的缓存机制  一级缓存 默认开启 sqlsession级别
​
        try {
            InputStream resource = Resources.getResourceAsStream("config/mybatis-config.xml");
            SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(resource);
            SqlSession sqlSession = factory.openSession(true);
            StudentDao mapper1 = sqlSession.getMapper(StudentDao.class);
            StudentDao mapper2 = sqlSession.getMapper(StudentDao.class);
            System.out.println(mapper1);
            System.out.println(mapper2);
            List<Student> a1 = mapper1.getAll();
            System.out.println(a1);
            //手动提交事务 清空缓存
            sqlSession.commit();
            List<Student> a2 = mapper2.getAll();
            System.out.println(a2);
​
            sqlSession.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
​
​
    @Test
    public void test03(){//验证mybatis的缓存机制  二级缓存 需要配置mybatis-config.xml  和mapper文件
​
        try {
            InputStream resource = Resources.getResourceAsStream("config/mybatis-config.xml");
            SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(resource);
            SqlSession sqlSession1 = factory.openSession(true);
            SqlSession sqlSession2 = factory.openSession(true);
            SqlSession sqlSession3 = factory.openSession(true);
​
            StudentDao mapper1 = sqlSession1.getMapper(StudentDao.class);
            StudentDao mapper2 = sqlSession2.getMapper(StudentDao.class);
            StudentDao mapper3 = sqlSession3.getMapper(StudentDao.class);
            List<Student> a1 = mapper1.getAll();
            System.out.println(a1);
            //关闭session将查询结果写入二级缓存
            sqlSession1.close();
​
            //当对同一张表进行增删改操作后  二级缓存清除
            mapper3.delStudent("2021072901");
           // sqlSession3.close();
​
            List<Student> a2 = mapper2.getAll();
            System.out.println(a2);
​
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

mybatis分页插件

<!-- https://mvnrepository.com/artifact/com.github.pagehelper/pagehelper -->
<dependency>
    <groupId>com.github.pagehelper</groupId>
    <artifactId>pagehelper</artifactId>
    <version>5.2.1</version>
</dependency>
<!--在mybatis配置文件中 配置mybatis插件 -->
    <plugins>
        <plugin interceptor="com.github.pagehelper.PageInterceptor">
            <!-- 配置mysql方言 -->
            <property name="helperDialect" value="mysql" />
            <!-- 设置为true时,如果pageSize=0就会查询出全部的结果 -->
            <property name="pageSizeZero" value="true" />
            <!-- 3.3.0版本可用,分页参数合理化,默认false禁用 -->
            <!-- 启用合理化时,如果pageNum<1会查询第一页,如果pageNum>pages会查询最后一页 -->
            <!-- 禁用合理化时,如果pageNum<1或pageNum>pages会返回空数据 -->
            <property name="reasonable" value="true" />
        </plugin>
    </plugins>

实例

 // 测试分页插件的使用
    @Test
    public void  test06(){
        SqlSession session = factory.openSession(true);
        StudentDao mapper = session.getMapper(StudentDao.class);
        PageHelper.startPage(5, 3);
        List<Student> all = mapper.findAll();
        PageInfo<Student> pageInfo = new PageInfo<>(all);
​
        //获取分页的相关数据
        System.out.println(pageInfo);
        //获取总条数
        long total = pageInfo.getTotal();
        System.out.println(total);
        //获取当前页的显示数据
        List<Student> list = pageInfo.getList();
        list.forEach(student-> System.out.println(student));
​
    }

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/336042.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

2023年了,来试试前端格式化工具

在大前端时代&#xff0c;前端的各种工具链穷出不断&#xff0c;有eslint, prettier, husky, commitlint 等, 东西太多有的时候也是trouble&#x1f602;&#x1f602;&#x1f602;,怎么正确的使用这个是每一个前端开发者都需要掌握的内容&#xff0c;请上车&#x1f697;&…

DHCP Relay中继实验

DHCP Relay实验拓扑图设备配置结果验证拓扑图 要求PC1按照地址池自动分配&#xff0c;而PC要求分配固定的地址&#xff0c;网段信息已经在图中进行标明。 设备配置 AR1&#xff1a; AR1作为DHCP Server基本配置跟DHCP Server没区别&#xff0c;不过要加一条静态路由&#xff…

基础篇:02-SpringCloud概述

1.SpringCloud诞生 基于前面章节&#xff0c;我们深知微服务已成为当前开发的主流技术栈&#xff0c;但是如dubbo、zookeeper、nacos、rocketmq、rabbitmq、springboot、redis、es这般众多技术都只解决了一个或一类问题&#xff0c;微服务并没有一个统一的解决方案。开发人员或…

计算机组成原理(三)

5.掌握定点数的表示和应用&#xff08;主要是无符号数和有符号数的表示、机器数的定点表示、数的机器码表示&#xff09;&#xff1b; 定点数&#xff1a;小数点位置固定不变。   定点小数&#xff1a;小数点固定在数值位与符号位之间&#xff1b;   定点整数&#xff1a;小…

R语言贝叶斯方法在生态环境领域中的高阶技术

贝叶斯统计学即贝叶斯学派是一门基本思想与传统基于频率思想的统计学即频率学派完全不同的统计学方法&#xff0c;它在统计建模中具有灵活性和先进性特点&#xff0c;使其可以轻松应对复杂数据和模型结构。然而&#xff0c;很多初学者在面对思想、技术和方法都与传统统计学有着…

Springcloud----Nacos快速搭建使用

Nacos使用指南 Nacos完整的搭建和项目配置流程&#xff0c;上手简单 一、Nacos安装启动 1.Windows安装 开发阶段采用单机安装即可。 1.1.下载安装包 在Nacos的GitHub页面&#xff0c;提供有下载链接&#xff0c;可以下载编译好的Nacos服务端或者源代码&#xff1a; GitHub主…

尚硅谷的尚融宝项目

先建立一个Maven springboot项目 进来先把src删掉&#xff0c;因为是一个父项目&#xff0c;我们删掉src之后&#xff0c;pom里配置的东西&#xff0c;也能给别的模块使用。 改一下springboot的版本号码 加入依赖和依赖管理&#xff1a; <properties><java.versi…

大型智慧校园系统源码 智慧校园源码 Android电子班牌源码

一款针对中小学研发的智慧校园系统源码&#xff0c;智慧学校源码带电子班牌、人脸识别系统。系统有演示&#xff0c;可正常上线运营正版授权。 私信了解更多&#xff01; 技术架构&#xff1a; 后端&#xff1a;Java 框架&#xff1a;springboot 前端页面&#xff1a;vue e…

keepalived+mysql高可用

一.设置mysql同步信息两节点安装msyql略#配置节点11.配置权限允许远程访问mysql -u root -p grant all on *.* to root% identified by Root1212# with grant option; flush privileges;2.修改my.cnf#作为主节点配置(节点1)#作为主节点配置 server-id 1 …

leetcode刷题 | 关于前缀和题型总结1

leetcode刷题 | 关于前缀和题型总结1 文章目录leetcode刷题 | 关于前缀和题型总结1题目链接和为K的子数组连续数组/0 和 1 个数相同的子数组和大于等于 target 的最短子数组/长度最小的子数组路经总和Ⅲ题目链接 560. 和为 K 的子数组 - 力扣&#xff08;LeetCode&#xff09;…

Python-第三天 Python判断语句

Python-第三天 Python判断语句一、 布尔类型和比较运算符1.布尔类型2.比较运算符二、if语句的基本格式1.if 判断语句语法2.案例三、 if else 语句1.语法2.案例四 if elif else语句1.语法五、判断语句的嵌套1.语法六、实战案例一、 布尔类型和比较运算符 1.布尔类型 布尔&…

【学习笔记】Nginx实战

反向代理实战 解压Tomcat两次-Tomcat8081、Tomcat8082两个文件夹Tomcat8081只需要修改http协议端口8081Tomcat8082&#xff1a;&#xff08;三个都需要改&#xff0c;不然只会启动其中一个&#xff09;1.修改server的默认端口2.修改http协议的默认端口3.膝盖默认ajp协议的默认端…

面试题: Redis的数据备份

1 RDBRDB全称为Redis Database Backup file &#xff0c;也被叫做Redis数据快照&#xff0c;简单来说就是将当前的所有数据都记录打哦磁盘中&#xff0c;当redis故障重启时&#xff0c;从磁盘读取快照文件进行数据恢复。连接客户端后&#xff0c;使用save命令进保存&#xff0c…

设置Visual Studio 2022背景图

前言 编写代码时界面舒服&#xff0c;自己喜欢很重要。本篇文章将会介绍VS2022壁纸的一些设置&#xff0c;主题的更改以及如何设计界面。 理想的界面应该是这样的 接下来我们来一步步学习如何将界面设计成这样 一、壁纸插件下载 1.拓展->点击拓展管理 2.右上角搜索backgro…

【shell 编程大全】shell 变量的定义以及使用

shell 变量定义 以及使用从此刻开始跟我一起学习shell 相关知识吧 前情回顾 上一章节【shell 前奏知识】 我们已经学习了很多shell的必备知识&#xff0c;让我们一起来回顾下。 shelll的存放位置如何切换shellshell文件中的注释有哪些查看当前系统的shell类型执行shell的n种方…

ubuntu20.04如何安装nvidia-docker?

文章目录安装步骤导入 NVIDIA GPG 密钥添加 NVIDIA Docker 存储库安装 nvidia-container-toolkit检查nvidia-docker是否安装成功安装步骤 导入 NVIDIA GPG 密钥 curl -s https://nvidia.github.io/nvidia-docker/gpgkey | sudo apt-key add -添加 NVIDIA Docker 存储库 dist…

2010-2019年290个地级市经济发展与城市绿化数据

2010-2019年290个地级市经济发展与城市绿化数据 1、时间&#xff1a;2010-2019年 2、来源&#xff1a;城市统计NJ&#xff0c;缺失情况与NJ一致 3、范围&#xff1a;290个地级市 4、指标&#xff1a; 综合经济&#xff1a;地区生产总值、人均地区生产总值、地区生产总值增…

开源的电子邮件客户端Cypht

网友 OOXX 在找好用的 webmail&#xff0c;老苏觉得 Cypht 还不错 什么是 Cypht &#xff1f; Cypht 是一个简单、轻量级和现代的 Webmail 客户端&#xff0c;它将多个帐户聚合到一个界面中。除了电子邮件帐户&#xff0c;它还支持 Atom/RSS 源。 安装 建数据库 数据库直接用…

MySQL数据库03——数据表的创建、修改和删除

接着上一章的内容&#xff0c;第一章安装好了Mysql和对应的编译器workbench&#xff0c;并且简单的创造了一个数据库college&#xff0c;第二章了解了SQL基础的动词和数据类型。这一章我们学习怎么用这些动词&#xff0c;在这个college库里面创建数据表&#xff0c;并且修改删除…

学习周报-2023-0210

文章目录一 在SUSE11sp3系统中将openssh从6升级到8一 需求二 系统环境三 部署流程1.上传编译安装的软件包2.安装 gcc编译软件3.安装依赖zlib4.安装依赖openssl5.安装openssh二 在CentOS-6.9配置apache服务&#xff08;3&#xff09;---虚拟主机配置一 定义二 系统环境三 基于域…