当前位置: 首页 > news >正文

Mybatis(第一篇)

Mybatis(第一篇)

目录

  • Mybatis(第一篇)
    • Mybatis进行CRUD
    • 一、①指令ID方式——Mybatis基础案例项目搭建
    • 二、代码的优化封装
      • 2.1 数据库链接信息的封装
      • 2.2 Mybatis工具类对获取sqlSession连接进行了封装
      • 2.3 typeAliases给类配置别名
    • 三、②接口代理方式
    • 四、日志配置
      • 4.1 引入日志相关jar包依赖
      • 4.2 创建log4j.properties的日志配置文件
      • 4.3 修改mybatis-config.xml配置文件
    • 五、结果映射
    • 六、#和$
      • 6.1 #和$的引入
        • 使用@Param注解
      • 6.2 #和$的对比
    • 七、SQL片段
    • 八、模糊查询
    • 九、多个参数问题
      • 方案一:封装成对象
      • 方案二:封装成map
      • 方案三:使用@Param注解
    • 十、分页查询(PageHelper)
    • 十一、新增自增长
    • 十二、动态SQL
      • 1.if标签
      • 2.where标签
      • 3.Foreach标签
        • 3.1 批量查询
          • 3.1.1 数组
            • ① 普通数组
            • ② 数组+@Param注解
          • 3.1.2 集合
            • ①普通集合
            • ② 集合+@Param注解
        • 3.2 批量新增
      • 4 choose标签
      • 5.set标签
    • 十三、缓存
      • 一级缓存
      • 二级缓存
    • 十四、Mybatis注解

Mybatis进行CRUD

一、①指令ID方式——Mybatis基础案例项目搭建

user.sql

/*
 Navicat Premium Data Transfer

 Source Server         : mysql80
 Source Server Type    : MySQL
 Source Server Version : 80029
 Source Host           : localhost:3306
 Source Schema         : mybatis

 Target Server Type    : MySQL
 Target Server Version : 80029
 File Encoding         : 65001

 Date: 02/10/2022 23:26:46
*/

SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;

-- ----------------------------
-- Table structure for user
-- ----------------------------
DROP TABLE IF EXISTS `user`;
CREATE TABLE `user`  (
  `id` bigint NOT NULL AUTO_INCREMENT,
  `name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NULL DEFAULT NULL,
  `age` int NULL DEFAULT NULL,
  `sex` bit(1) NULL DEFAULT NULL,
  `address` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NULL DEFAULT NULL,
  `birth` date NULL DEFAULT NULL,
  PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 5 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_bin ROW_FORMAT = DYNAMIC;

-- ----------------------------
-- Records of user
-- ----------------------------
INSERT INTO `user` VALUES (2, 'tony', 12, b'1', '成都', '2022-10-02');
INSERT INTO `user` VALUES (3, 'tony', 12, b'1', '成都', '2022-10-02');
INSERT INTO `user` VALUES (4, 'tony', 12, b'1', '成都', '2022-10-02');

SET FOREIGN_KEY_CHECKS = 1;

pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.bjpowernode</groupId>
    <artifactId>hellomybatis</artifactId>
    <version>1.0.0</version>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <maven.compiler.source>1.8</maven.compiler.source>
        <maven.compiler.target>1.8</maven.compiler.target>
    </properties>

    <dependencies>
        <!--mysql-->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.28</version>
        </dependency>
        <!--mybatis-->
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis</artifactId>
            <version>3.4.6</version>
        </dependency>
        <!--junit-->
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
            <scope>test</scope>
        </dependency>
    </dependencies>


</project>

com.bjpowernode.domain包
User.java类

package com.bjpowernode.domain;

import java.util.Date;

public class User {

    private Long id;
    private String name;
    private Integer age;
    private int sex;
    private String address;
    private Date birth;

    public Long getId() {
        return id;
    }

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

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }

    public int getSex() {
        return sex;
    }

    public void setSex(int sex) {
        this.sex = sex;
    }

    public String getAddress() {
        return address;
    }

    public void setAddress(String address) {
        this.address = address;
    }

    public Date getBirth() {
        return birth;
    }

    public void setBirth(Date birth) {
        this.birth = birth;
    }

    @Override
    public String toString() {
        return "User{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", age=" + age +
                ", sex=" + sex +
                ", address='" + address + '\'' +
                ", birth=" + birth +
                '}';
    }
}

com.bjpowernode.mapper包
UserMapper.java接口

package com.bjpowernode.mapper;

public interface UserMapper {
}

resources资源文件夹下
mybatis-config.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>
    <!--配置开发环境
     在真实开发中,我们的环境的问题 , 一般 分三个环境
     开发环境
     测试环境
     生产环境
     三个环境中,链接的数据库是不同,那么 我么如果手动切换环境,是很容易输错
     所以我么可以提前配置好多个 环境,然后通过 default 关键字来进行切换

     default 属性 的  值  必须 要和子标签中的 id 属性的值 保持一直

     -->
     <environments default="dev">

         <environment id="dev">
             <!--事务管理器,目前 采用的是 myBatis提供的 -->
             <transactionManager type="JDBC"/>
             <!--数据源 (链接池) ,目前 采用的是  MyBatis 提供的 -->
             <dataSource type="POOLED">
                 <property name="driver" value="com.mysql.cj.jdbc.Driver"/>
                 <property name="url" value="jdbc:mysql:///mybatis?useSSL=false"/>
                 <property name="username" value="root"/>
                 <property name="password" value="root"/>
             </dataSource>
         </environment>

     </environments>

    <mappers>
        <!--挂载 sql的映射文件-->
        <mapper resource="com/bjpowernode/mapper/UserMapper.xml"/>
    </mappers>
</configuration>

resources文件夹下
com,bjpowernode.mapper文件夹下
UserMapper.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">
        <!--namespace 命名空间 作用: 起到整个项目的唯一标示
          要求: 在mapper包中,定义一个 XxxMapper 的 接口
          然后使用该接口的全限定名的值作为namespace 的值-->
<mapper namespace="com.bjpowernode.mapper.UserMapper">

<!-- insert 是 插入 标签 , 表示 插入数据,编写插入的sql ,
id 属性 ,作用 : 在当前文档中 , 唯一的一个标示符
#{变量} ,这个整体 是 占位符 相当于 ?
里面的变量 必须使用 对应的类中的 属性的名称


-->
 <insert id="insertUser" >
   insert into user (name,age,sex,address,birth)

   values (#{name},#{age},#{sex},#{address},#{birth})
</insert>

<update id="updateUser">
 update user set name = #{name},age=#{age},
 sex = #{sex},address=#{address},birth = #{birth}
 where id = #{id}
</update>

<!--
 resultType 属性  表示 查询结果中存储的对象的真实类型
-->
<select id="selectUsers"  resultType="com.bjpowernode.domain.User">
  select * from user
</select>

<delete id="deleteById">
 delete from user where id = #{id}
</delete>


</mapper>

test包下
java包下
com,bjpowernode.text包下
CRUDTest.java测试类

package com.bjpowernode.test;

import com.bjpowernode.domain.User;
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 org.junit.Test;

import java.io.IOException;
import java.io.InputStream;
import java.util.Date;
import java.util.List;

public class CRUDTest {

    @Test
    public void testInsert() throws IOException {
        //1.加载MyBatis 主配置文件
//        Thread.currentThread().getContextClassLoader()
//                .getResourceAsStream("mybatis-config.xml");

        InputStream resourceAsStream = Resources.getResourceAsStream("mybatis-config.xml");

        //2. 构建 SqlSessionFactory 工厂对象    SqlSessionFactory 想像 成 连接池 对象
        SqlSessionFactory build = new SqlSessionFactoryBuilder().build(resourceAsStream);
        //3. 通过工厂对象 获取sqlSession 会话对象  想象 成 链接对象
        SqlSession sqlSession = build.openSession();
        //4. 调用MyBatis 框架 提供该 接口方法
        /*
         * SqlSession扩展方法(过时不建议使用)
         * 说明: 可以通过namespace名称.ID的方式直接调用sql
         */
        /*
        * insert 方法 有两个参数
        * 第一个参数(statement):namespace的值 + "." + sql的id的值 (找寻sql的 唯一凭证)
        * 第二个参数 (替换sql语句中的占位符的参数): 如果占位符有很多那么封装成一个对象或者容器对象
        *
        * */
        User user1 = new User();
        user1.setName("tony");
        user1.setAge(12);
        user1.setSex(1);
        user1.setBirth(new Date());
        user1.setAddress("成都");
        sqlSession.insert("com.bjpowernode.mapper.UserMapper.insertUser",user1);
        //5.提交事务
        sqlSession.commit();
        //6.释放资源
        sqlSession.close();
    }

    @Test
    public  void  testUpdate() throws IOException {
        InputStream resourceAsStream = Resources.getResourceAsStream("mybatis-config.xml");
        SqlSessionFactory build = new SqlSessionFactoryBuilder().build(resourceAsStream);
        SqlSession sqlSession = build.openSession();
        User user1 = new User();
        user1.setId(1L);
        user1.setName("lili");
        user1.setAge(18);
        user1.setSex(0);
        user1.setBirth(new Date());
        user1.setAddress("成都");
        sqlSession.update("com.bjpowernode.mapper.UserMapper.updateUser",user1);
        sqlSession.commit();
        sqlSession.close();

    }

    @Test
    public void testSelect() throws IOException {
        InputStream resourceAsStream = Resources.getResourceAsStream("mybatis-config.xml");
        SqlSessionFactory build = new SqlSessionFactoryBuilder().build(resourceAsStream);
        SqlSession sqlSession = build.openSession();
        List<User> users = sqlSession.selectList("com.bjpowernode.mapper.UserMapper.selectUsers");
        for (User user : users) {
            System.out.println("user = " + user);
        }
        sqlSession.commit();
        sqlSession.close();
    }

    @Test
    public void testDelete() throws IOException {
        InputStream resourceAsStream = Resources.getResourceAsStream("mybatis-config.xml");
        SqlSessionFactory build = new SqlSessionFactoryBuilder().build(resourceAsStream);
        SqlSession sqlSession = build.openSession();
         sqlSession.delete("com.bjpowernode.mapper.UserMapper.deleteById",1L);

        sqlSession.commit();
        sqlSession.close();
    }
}

二、代码的优化封装

2.1 数据库链接信息的封装

在resources文件夹下新建db.properties配置文件

driverClassName=com.mysql.jdbc.Driver
url=jdbc:mysql:///test?useSSL=false
username=root
password=kong1234

在mybatis-config.xml配置文件中,<configuration></configuration>中关联数据库的链接配置信息

   <!--关联数据库的配置信息-->
    <properties resource="db.properties"/>

在environment中的dataSource里面的property通过“$”符号引用db.properties中的变量

<!--配置环境-->
<environments default="dev">
    <environment id="dev">
        <transactionManager type="JDBC"/>
        <dataSource type="POOLED">
            <property name="driver" value="${driverClassName}"/>
            <property name="url" value="${url}"/>
            <property name="username" value="${username}"/>
            <property name="password" value="${password}"/>
        </dataSource>
    </environment>
</environments>

2.2 Mybatis工具类对获取sqlSession连接进行了封装

com.bjpowernode.util下的
Mybatis.util类

package com.bjpowernode.util;


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;

public class MybatisUtil {

    private MybatisUtil(){

    }

    private static SqlSessionFactory factory = null;

    static {
        try {
            //把配置文件转成IO流
            InputStream resourceAsStream = Resources.getResourceAsStream("mybatis-config.xml");
            //通过构建器 加载流
            factory = new SqlSessionFactoryBuilder().build(resourceAsStream);
        } catch (IOException exception) {
            exception.printStackTrace();
        }
    }

    public static SqlSession openSession(){
        return factory.openSession();
    }
}

test类
java
com.bjpowenode.text
CRUDTest2.java

package com.bjpowernode.test;

import com.bjpowernode.domain.User;
import com.bjpowernode.util.MybatisUtil;
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 org.junit.Test;

import java.io.IOException;
import java.io.InputStream;
import java.util.Date;
import java.util.List;

public class CRUDTest2 {

    @Test
    public void insertUser() throws IOException {
        SqlSession sqlSession = MybatisUtil.openSession();

        User user = new User();
        user.setName("tony");
        user.setAge(12);
        user.setSex(1);
        user.setBirth(new Date());
        user.setAddress("成都");
        //4. 调用MyBatis 框架 提供该 接口方法
        /*
        * SqlSession扩展方法(过时不建议使用)
        * 说明: 可以通过namespace名称.ID的方式直接调用sql
        */
        /*
         * insert 方法 有两个参数
         * 第一个参数(statement):namespace的值 + "." + sql的id的值 (找寻sql的 唯一凭证)
         * 第二个参数 (替换sql语句中的占位符的参数): 如果占位符有很多那么封装成一个对象或者容器对象
         *
         * */
        sqlSession.insert("com.bjpowernode.mapper.UserMapper.insertUser",user);
        //5.提交事务
        sqlSession.commit();
        //6.释放资源
        sqlSession.close();
    }

    @Test
    public void updateUser() throws IOException {
        SqlSession sqlSession = MybatisUtil.openSession();
        User user = new User();
        user.setId(1L);
        user.setName("lili");
        user.setAge(18);
        user.setSex(0);
        user.setBirth(new Date());
        user.setAddress("成都");
        sqlSession.update("com.bjpowernode.mapper.UserMapper.updateUser",user);

        sqlSession.commit();
        sqlSession.close();

    }

    @Test
    public void selectUsers() throws IOException {
        SqlSession sqlSession = MybatisUtil.openSession();

        List<User> userList = sqlSession.selectList("com.bjpowernode.mapper.UserMapper.selectUsers");
        for (User user : userList) {
            System.out.println("user = " + user);
        }

        sqlSession.commit();
        sqlSession.close();
    }

    @Test
    public void deleteUser() throws IOException {
        SqlSession sqlSession = MybatisUtil.openSession();

     sqlSession.delete("com.bjpowernode.mapper.UserMapper.deleteUserById",1L);

        sqlSession.commit();
        sqlSession.close();
    }

}

2.3 typeAliases给类配置别名

在mybatis-config.xml配置文件中,给类配置别名

  <!--  2.1 给类配置别名 -->
    <typeAliases>
        <!--包扫描:Mybatis框架,它会扫描domain这个包下面的所有的类,然后给类取别名
        默认别名为 类 的名称,不区分大小写-->
        <package name="com.bjpowernode.domain"/>
    </typeAliases>

那么在UserMapper.xml中原来对User的查询语句的写法

  <select id="selectUsers" resultType="com.bjpowernode.domain.User">
        select * from user
    </select>

就可以优化简写成如下写法

<!--  在mybatis-config.xml文件中使用了typeAliases  -->
    <select id="selectUsers" resultType="user">
        select * from user
    </select>

三、②接口代理方式

student.sql

/*
 Navicat Premium Data Transfer

 Source Server         : mysql57
 Source Server Type    : MySQL
 Source Server Version : 50738
 Source Host           : localhost:13306
 Source Schema         : test

 Target Server Type    : MySQL
 Target Server Version : 50738
 File Encoding         : 65001

 Date: 02/10/2022 20:08:52
*/

SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;

-- ----------------------------
-- Table structure for student
-- ----------------------------
DROP TABLE IF EXISTS `student`;
CREATE TABLE `student`  (
  `id` bigint(20) NOT NULL AUTO_INCREMENT,
  `name` varchar(12) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,
  `age` int(10) UNSIGNED NULL DEFAULT NULL,
  `gender` bit(1) NULL DEFAULT NULL,
  `create_time` date NULL DEFAULT NULL,
  PRIMARY KEY (`id`) USING BTREE,
  INDEX `index_name`(`name`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 13 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = DYNAMIC;

-- ----------------------------
-- Records of student
-- ----------------------------
INSERT INTO `student` VALUES (1, '张三丰111', 23, b'1', '2022-03-01');
INSERT INTO `student` VALUES (2, '李四民', 11, b'0', '2022-03-30');
INSERT INTO `student` VALUES (3, '结衣', 12, b'1', '2022-08-08');
INSERT INTO `student` VALUES (4, 'Lisa', 26, b'1', '2022-03-30');
INSERT INTO `student` VALUES (5, 'tony', 32, b'1', '2022-08-07');
INSERT INTO `student` VALUES (6, '露露', 2, b'1', '2022-08-07');
INSERT INTO `student` VALUES (7, '丽丽', 13, b'1', '2022-08-12');
INSERT INTO `student` VALUES (8, '花花', 14, b'1', '2022-08-12');
INSERT INTO `student` VALUES (9, '猫咪', 15, b'1', '2022-08-12');
INSERT INTO `student` VALUES (10, '如花', 17, b'1', '2022-08-12');
INSERT INTO `student` VALUES (12, 'hhh', 23, b'0', '2022-09-18');

SET FOREIGN_KEY_CHECKS = 1;

pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.bjpowernode</groupId>
    <artifactId>proxyProject</artifactId>
    <version>1.0.0</version>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <maven.compiler.source>1.8</maven.compiler.source>
        <maven.compiler.target>1.8</maven.compiler.target>
    </properties>

    <dependencies>
        <!--mysql-->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.28</version>
        </dependency>
        <!--mybatis-->
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis</artifactId>
            <version>3.4.6</version>
        </dependency>

        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.20</version>
        </dependency>

        <!--junit-->
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
            <scope>test</scope>
        </dependency>

    </dependencies>





</project>

resources资源文件下
mybatis-config.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>

    <!-- 关联数据库的配置信息   -->
    <properties resource="db.properties"/>

    <!--给所有的 javaBean 起别名-->
    <typeAliases>
        <package name="com.bjpowernode.domain"/>
    </typeAliases>

    <!--  配置环境  -->
    <environments default="dev">
        <environment id="dev">
            <transactionManager type="JDBC"/>
            <dataSource type="POOLED">
                <property name="driver" value="${driverClassName}"/>
                <property name="url" value="${url}"/>
                <property name="username" value="${username}"/>
                <property name="password" value="${password}"/>
            </dataSource>
        </environment>
    </environments>

    <!-- 挂载sql的映射文件   -->
    <mappers>
        <mapper resource="com\bjpowernode\mapper\StudentMapper.xml"/>
    </mappers>
</configuration>

db.properties


driverClassName=com.mysql.cj.jdbc.Driver
url=jdbc:mysql:///mybatis?useSSL=false
username=root
password=root

com.powernode
domain包下

package com.bjpowernode.domain;

import lombok.Data;

import java.util.Date;

@Data
public class Student {
    private Long id;
    private String name;
    private Integer age;
    private int gender;
    private Date create_time;
}

util包
MybatisUtil.java

package com.bjpowernode.util;

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;


public class MyBatisUtil {

    private MyBatisUtil(){}

    private static SqlSessionFactory factory = null;
    static {
        try {
            InputStream resourceAsStream = Resources.getResourceAsStream("mybatis-config.xml");
            factory  = new SqlSessionFactoryBuilder().build(resourceAsStream);

        } catch (IOException e) {
            e.printStackTrace();
        }

    }

    public static SqlSession openSession() {
    	//设置为true则自动提交了事务
        return factory.openSession(true);
    }
}

mapper包
StudentMapper.java

package com.bjpowernode.mapper;

import com.bjpowernode.domain.Student;

import java.util.List;

public interface StudentMapper {
  void insertStudent(Student student);

  void updateStudent(Student student);

  void deleteStudentById(long id);

  Student selectStudentById(long id);

  List<Student> selectStudentList();
}

StudentMapper.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.bjpowernode.mapper.StudentMapper">

<!--
  parameterType 表示传入的参数的类型,写类的全限定类名或别名
  由于mybatis框架的强大 它能识别传入的参数类型,无需告知给Mybatis
-->
 <insert id="insertStudent" parameterType="student">
   insert into student(name,age,gender,create_time)
   values (#{name},#{age},#{gender},#{create_time})
</insert>

<update id="updateStudent">
    update student
    set
    name = #{name},
    age=#{age},
    gender=#{gender},
    create_time=#{create_time}
    where id = #{id}
</update>

    <delete id="deleteStudentById">
        delete from student where id = #{id}
    </delete>

<!--    <select id="selectStudentById" resultType="com.bjpowernode.domain.Student">-->
    <select id="selectStudentById" resultType="student">
        select * from student where id = #{id}
    </select>

<!--    <select id="selectStudentList" resultType="com.bjpowernode.domain.Student">-->
    <select id="selectStudentList" resultType="student">
        select * from student
    </select>


</mapper>

测试类

package com.bjpowernode.test;

import com.bjpowernode.domain.Student;
import com.bjpowernode.mapper.StudentMapper;
import com.bjpowernode.util.MyBatisUtil;
import org.apache.ibatis.session.SqlSession;
import org.junit.Test;

import java.util.List;
import java.util.Date;

public class CRUDTest {
    @Test
    public void insertStudent(){
        // 获取SqlSession对象
        SqlSession sqlSession = MyBatisUtil.openSession();
        // 获取 mapper 接口的代理对象
        StudentMapper studentMapper = sqlSession.getMapper(StudentMapper.class);
        System.out.println(studentMapper.getClass());
        Student student = new Student();
        student.setAge(12);
        student.setName("cat");
        student.setCreate_time(new Date());
        student.setGender(1);
        // 调用方法 使用代理对象调用接口中的方法
        studentMapper.insertStudent(student);

        //在MybatisUtil中openSession(true)设置为true,则会自动提交事务
//        //提交事务
//        sqlSession.commit();
        //释放资源
        sqlSession.close();

    }

    @Test
    public void updateStudent(){
        // 获取sqlSession对象
        SqlSession sqlSession = MyBatisUtil.openSession();
        // 获取 mapper 接口的代理对象
        StudentMapper studentMapper = sqlSession.getMapper(StudentMapper.class);
        System.out.println(studentMapper.getClass());
        Student student = new Student();
        student.setId(12L);
        student.setAge(12);
        student.setName("mybatis");
        student.setCreate_time(new Date());
        student.setGender(1);
        // 调用方法 使用代理对象调用接口中的方法
        studentMapper.updateStudent(student);
        //提交事务
        sqlSession.commit();
        //释放资源
        sqlSession.close();
    }

    @Test
    public void deleteStudentById(){
        // 获取sqlSession对象
        SqlSession sqlSession = MyBatisUtil.openSession();
        // 获取 mapper 接口的代理对象
        StudentMapper studentMapper = sqlSession.getMapper(StudentMapper.class);
        System.out.println(studentMapper.getClass());
        // 调用方法 使用代理对象调用接口中的方法
        studentMapper.deleteStudentById(16L);
        //提交事务
        sqlSession.commit();
        //释放资源
        sqlSession.close();
    }

    @Test
    public void selectStudentById() {
        // 获取sqlSession对象
        SqlSession sqlSession = MyBatisUtil.openSession();
        // 获取 mapper 接口的代理对象
        StudentMapper studentMapper = sqlSession.getMapper(StudentMapper.class);
        System.out.println(studentMapper.getClass());
        // 调用方法 使用代理对象调用接口中的方法
        Student student = studentMapper.selectStudentById(3L);
        System.out.println("student = " + student);
        // 提交事务
        sqlSession.commit();
        // 释放资源
        sqlSession.close();

    }

    @Test
    public void selectStudentList() {
        // 获取sqlSession对象
        SqlSession sqlSession = MyBatisUtil.openSession();
        // 获取 mapper 接口的代理对象
        StudentMapper studentMapper = sqlSession.getMapper(StudentMapper.class);
        System.out.println(studentMapper.getClass());
        // 调用方法 使用代理对象调用接口中的方法
        List<Student> studentList = studentMapper.selectStudentList();
        for (Student student : studentList) {
            System.out.println("student = " + student);
        }
        // 提交事务
        sqlSession.commit();
        // 释放资源
        sqlSession.close();

    }
}

四、日志配置

4.1 引入日志相关jar包依赖

<!-- 日志相关依赖 -->
<dependency>
    <groupId>commons-logging</groupId>
    <artifactId>commons-logging</artifactId>
    <version>1.2</version>
</dependency>
<dependency>
    <groupId>org.apache.logging.log4j</groupId>
    <artifactId>log4j-core</artifactId>
    <version>2.13.3</version>
</dependency>
<dependency>
    <groupId>log4j</groupId>
    <artifactId>log4j</artifactId>
    <version>1.2.17</version>
</dependency>

4.2 创建log4j.properties的日志配置文件

在这里插入图片描述
注意:圈出来的部分要配置成你自己的mapper包


log4j.rootLogger=ERROR, stdout

log4j.logger.com.bjpowernode.mapper=TRACE

log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%5p [%t] - %m%n

4.3 修改mybatis-config.xml配置文件

在mybatis-config.xml设置日志
注意:设置日志部分代码只能放在configuration里面的第2个

在这里插入图片描述

   <!-- 设置日志   -->
    <settings>
        <setting name="logImpl" value="LOG4J"/>
    </settings>
    

此时再去测试类运行,就可以看到sql语句了
在这里插入图片描述

五、结果映射

domain包下的Student

package com.bjpowernode.domain;

import lombok.Data;

import java.util.Date;

@Data
public class Student {
    private Long id;
    private String name;
    private Integer age;
    private int gender;
//    private Date create_time;
    private Date createTime;
}

StudentMapper.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.bjpowernode.mapper.StudentMapper">

<!--
  parameterType 表示传入的参数的类型,写类的全限定类名或别名
  由于mybatis框架的强大 它能识别传入的参数类型,无需告知给Mybatis
-->
    <insert id="insertStudent" parameterType="student">
   insert into student(name,age,gender,create_time)
   values
   (
   #{name},
   #{age},
   #{gender},
   #{createTime}
   )
</insert>


    <update id="updateStudent">
    update student
    set
    name = #{name},
    age=#{age},
    gender=#{gender},
    create_time=#{createTime}
    where id = #{id}
</update>

    <delete id="deleteStudentById">
        delete from student where id = #{id}
    </delete>



    <resultMap id="baseMap" type="com.bjpowernode.domain.Student">
        <!--
            id标签是应用在主键上性能比较高
            property是类中的属性名称
            colunn是表中的字段名称
            result标签是应用在非主键上
        -->
        <id property="id" column="id"/>
        <result property="name" column="name"/>
        <result property="gender" column="gender"/>
        <result property="age" column="age"/>
        <result property="createTime" column="create_time"/>
    </resultMap>

    <select id="selectStudentById" resultMap="baseMap">
        select * from student where id = #{id}
    </select>


        <select id="selectStudentList" resultMap="baseMap">
            select * from student
        </select>



</mapper>

CRUD.Test

package com.bjpowernode.test;

import com.bjpowernode.domain.Student;
import com.bjpowernode.mapper.StudentMapper;
import com.bjpowernode.util.MyBatisUtil;
import org.apache.ibatis.session.SqlSession;
import org.junit.Test;

import java.util.List;
import java.util.Date;

public class CRUDTest {
    @Test
    public void insertStudent(){
        // 获取SqlSession对象
        SqlSession sqlSession = MyBatisUtil.openSession();
        // 获取 mapper 接口的代理对象
        StudentMapper studentMapper = sqlSession.getMapper(StudentMapper.class);
        System.out.println(studentMapper.getClass());
        Student student = new Student();
        student.setAge(12);
        student.setName("cat");
//        student.setCreate_time(new Date());
        student.setCreateTime(new Date());
        student.setGender(1);
        // 调用方法 使用代理对象调用接口中的方法
        studentMapper.insertStudent(student);

        //在MybatisUtil中openSession(true)设置为true,则会自动提交事务
//        //提交事务
//        sqlSession.commit();
        //释放资源
        sqlSession.close();

    }

    @Test
    public void updateStudent(){
        // 获取sqlSession对象
        SqlSession sqlSession = MyBatisUtil.openSession();
        // 获取 mapper 接口的代理对象
        StudentMapper studentMapper = sqlSession.getMapper(StudentMapper.class);
        System.out.println(studentMapper.getClass());
        Student student = new Student();
        student.setId(12L);
        student.setAge(12);
        student.setName("mybatis");
//        student.setCreate_time(new Date());
        student.setCreateTime(new Date());
        student.setGender(1);
        // 调用方法 使用代理对象调用接口中的方法
        studentMapper.updateStudent(student);
        //提交事务
        sqlSession.commit();
        //释放资源
        sqlSession.close();
    }

    @Test
    public void deleteStudentById(){
        // 获取sqlSession对象
        SqlSession sqlSession = MyBatisUtil.openSession();
        // 获取 mapper 接口的代理对象
        StudentMapper studentMapper = sqlSession.getMapper(StudentMapper.class);
        System.out.println(studentMapper.getClass());
        // 调用方法 使用代理对象调用接口中的方法
        studentMapper.deleteStudentById(16L);
        //提交事务
        sqlSession.commit();
        //释放资源
        sqlSession.close();
    }

    @Test
    public void selectStudentById() {
        // 获取sqlSession对象
        SqlSession sqlSession = MyBatisUtil.openSession();
        // 获取 mapper 接口的代理对象
        StudentMapper studentMapper = sqlSession.getMapper(StudentMapper.class);
        System.out.println(studentMapper.getClass());
        // 调用方法 使用代理对象调用接口中的方法
        Student student = studentMapper.selectStudentById(3L);
        System.out.println("student = " + student);
        // 提交事务
        sqlSession.commit();
        // 释放资源
        sqlSession.close();

    }

    @Test
    public void selectStudentList() {
        // 获取sqlSession对象
        SqlSession sqlSession = MyBatisUtil.openSession();
        // 获取 mapper 接口的代理对象
        StudentMapper studentMapper = sqlSession.getMapper(StudentMapper.class);
        System.out.println(studentMapper.getClass());
        // 调用方法 使用代理对象调用接口中的方法
        List<Student> studentList = studentMapper.selectStudentList();
        for (Student student : studentList) {
            System.out.println("student = " + student);
        }
        // 提交事务
        sqlSession.commit();
        // 释放资源
        sqlSession.close();

    }
}

7.1.2注意
映射关系中,column查询结果的列别名,不是原始列名

 <resultMap id="baseMap" type="com.bjpowernode.domain.Student">
        <!--
            id标签是应用在主键上性能比较高
            property是类中的属性名称
            colunn是表中的字段名称
            result标签是应用在非主键上
        -->
        <id property="id" column="id"/>
        <result property="name" column="name"/>
        <result property="gender" column="gender"/>
        <result property="age" column="age"/>
<!--        <result property="createTime" column="create_time"/> -->
        <result property="createTime" column="time"/>
    </resultMap>
  <select id="selectStudentList" resultMap="baseMap">
            select id,name,age,gender,create_time time from student
        </select>

在查询指令中,resultMap属性,指向定义的映射关系的ID

六、#和$

6.1 #和$的引入

将#号改成$符号

 <select id="selectStudentById" resultMap="baseMap">
--         select * from student where id = #{id}
        select * from student where id = ${id}
    </select>

再运行test类会报错:没有getter方法
在这里插入图片描述
解决办法

使用@Param注解

在Student.Mapper中添加@Param注解

 //使用${}来查询 @Param("id") 表示提供了getter
  Student selectStudentById$(@Param("id") Long id);

6.2 #和$的对比

在mybatis中,会将开发者定义的sql进行解析,解析分为了2类sql:
1.静态sql ,在解析时,直接将参数拼接到sql中,这种就是静态sql
2.动态sql,在解析时,会使用?这个占位符,替代参数

这两种解析方式,mybatis是根据${}和#{}进行区分的
${}的sql是静态sql
#{}的sql是动态sql

不论是静态sql,还是动态sql都能获取传递参数,但是${}是使用的字符拼接,#{}使用PreparedStatement进行参数的预处理。

在一定程度上说,${}能实现的功能,#{}都能实现,并且由于#{}PreparedStatement进行SQL的预处理,一定程度上可以防止SQL注入攻击。所以在开发中,能使用#{}尽量使用#{}。

PreparedStatement预处理的本质是将参数进行转换为字符串,当做参数字符串处理。所以,如果参数信息是一个特殊的关键字,例如: 数据库名,表名,函数名,内置关键字,使用预处理,则关键字转为了字符串,无效了,此时必须使用字符串拼接也即是statement,也即意味着必须只能使用${}.

#{变量} 占位符 一般情况下的都是使用这个
${变量} 拼接符 如果sql语句中 有分组,排序,则分组的字段和 排序的条件 必须使用$(变量)

StudentMapper.java

package com.bjpowernode.mapper;

import com.bjpowernode.domain.Student;
import org.apache.ibatis.annotations.Param;

import java.util.List;

public interface StudentMapper {


  //使用${}来查询 @Param("id") 表示提供了getter
  Student selectStudentById$(@Param("id") Long id);

  //使用#{}来查询
  Student selectStudentById(Long id);

  List<Student> selectStudentOrderByAge(@Param("age") String age);
}

StudentMapper.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.bjpowernode.mapper.StudentMapper">


    <resultMap id="baseMap" type="com.bjpowernode.domain.Student">
        <!--
            id标签是应用在主键上性能比较高
            property是类中的属性名称
            colunn是表中的字段名称
            result标签是应用在非主键上
        -->
        <id property="id" column="id"/>
        <result property="name" column="name"/>
        <result property="gender" column="gender"/>
        <result property="age" column="age"/>
        <result property="createTime" column="create_time"/>
    </resultMap>

    <select id="selectStudentById" resultMap="baseMap">
        select * from student where id = #{id}
    </select>

    <select id="selectStudentById$" resultMap="baseMap">
        select * from student where id = ${id}
    </select>

    <select id="selectStudentOrderByAge" resultMap="baseMap">
            select * from student order by ${age}
    </select>



</mapper>

test测试类

package com.bjpowernode.test;

import com.bjpowernode.domain.Student;
import com.bjpowernode.mapper.StudentMapper;
import com.bjpowernode.util.MyBatisUtil;
import org.apache.ibatis.session.SqlSession;
import org.junit.Test;

import java.util.Date;
import java.util.List;

public class VS$Test {

    //#{}
    /*
    *select * from student where id = ? 先解析把#{}转成了"?",然后再把真实的值替换掉"?"
    * 底层使用的是PreparedStatement 防止注入
    *
     */
    @Test
    public void selectStudentById(){
        SqlSession sqlSession = MyBatisUtil.openSession();
        StudentMapper studentMapper = sqlSession.getMapper(StudentMapper.class);
        Student student = studentMapper.selectStudentById(3L);
        System.out.println("student = " + student);
    }

    //${}
    /*
    *${变量}:这个变量必须提供getter方法 在不同的版本中 要求不同,有的要求提供getter,有的不要求提供
    *
    * select * from student where id = 3 直接把参数拼接到了sql中,直接替换了${}
    * 底层使用的是statement 拼接的方式
    * 很多时候 都是使用 #{} 来做占位符
    * ${} 是拼接符,使用的场景有:排序、分组、动态的拼接字段和表名
     */
    @Test
    public void selectStudentById$(){
        SqlSession sqlSession = MyBatisUtil.openSession();
        StudentMapper studentMapper = sqlSession.getMapper(StudentMapper.class);
        Student student = studentMapper.selectStudentById$(3L);
        System.out.println("student = " + student);
    }

    @Test
    public void selectStudentOrderByAge(){
        SqlSession sqlSession = MyBatisUtil.openSession();
        StudentMapper studentMapper = sqlSession.getMapper(StudentMapper.class);
        List<Student> studentList = studentMapper.selectStudentOrderByAge("age");
        for (Student student : studentList) {
            System.out.println("student = " + student);
        }
        sqlSession.close();
    }

}

七、SQL片段

使用<sql id=“baseColumn”><sql>标签和<include refid=“baseColumn”/>实现
StudentMapper.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.bjpowernode.mapper.StudentMapper">


    <resultMap id="baseMap" type="com.bjpowernode.domain.Student">
        <!--
            id标签是应用在主键上性能比较高
            property是类中的属性名称
            colunn是表中的字段名称
            result标签是应用在非主键上
        -->
        <id property="id" column="id"/>
        <result property="name" column="name"/>
        <result property="gender" column="gender"/>
        <result property="age" column="age"/>
        <result property="createTime" column="create_time"/>
    </resultMap>

    <sql id="baseColumn">
        id,name,age,gender,create_time
    </sql>

    <select id="selectStudentById" resultMap="baseMap">
        select <include refid="baseColumn"/> from student where id = #{id}
    </select>

    <select id="selectStudentById$" resultMap="baseMap">
        select <include refid="baseColumn"/> from student where id = ${id}
    </select>

    <select id="selectStudentOrderByAge" resultMap="baseMap">
            select <include refid="baseColumn"/> from student order by ${age}
    </select>



</mapper>
<?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.bjpowernode.mapper.StudentMapper">


    <resultMap id="baseMap" type="com.bjpowernode.domain.Student">
        <!--
            id标签是应用在主键上性能比较高
            property是类中的属性名称
            colunn是表中的字段名称
            result标签是应用在非主键上
        -->
        <id property="id" column="id"/>
        <result property="name" column="name"/>
        <result property="gender" column="gender"/>
        <result property="age" column="age"/>
        <result property="createTime" column="create_time"/>
    </resultMap>

    <sql id="baseColumn">
       select id,name,age,gender,create_time from student
    </sql>

    <select id="selectStudentById" resultMap="baseMap">
         <include refid="baseColumn"/> where id = #{id}
    </select>

    <select id="selectStudentById$" resultMap="baseMap">
         <include refid="baseColumn"/>  where id = ${id}
    </select>

    <select id="selectStudentOrderByAge" resultMap="baseMap">
            <include refid="baseColumn"/>  order by ${age}
    </select>



</mapper>

八、模糊查询

UserMapper.java

package com.bjpowernode.mapper;

import com.bjpowernode.domain.User;

import java.util.*;

public interface UserMapper {
    // 模糊查询
    List<User> selectUserByKeyword(String keyword);


}

UserMapper.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.bjpowernode.mapper.UserMapper">


    <select id="selectUserByKeyword" resultType="user">
        select * from user where name like concat('%',#{keyword},'%');
    </select>
</mapper>

测试类

@Test
public void selectByCondition(){
    SqlSession sqlSession = MyBatisUtil.openSession();
    UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
    System.out.println(userMapper);
    List<User> userList = userMapper.selectUserByKeyword("lili");
    userList.forEach(System.out::println);
}

九、多个参数问题

方案一:封装成对象

UserMapper.java中

  //多个参数封装
    // 方案一:封装成对象
    void insertByJavaBean(User user);

UserMapper.xml

   <insert id="insertByJavaBean">
        insert into  user(name,age,sex,address,birth) values (#{name},#{age},#{sex},#{address},#{birth});
    </insert>

测试类

@Test
public void insertByJavaBean(){
    SqlSession sqlSession = MyBatisUtil.openSession();
    UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
    System.out.println(userMapper);
    User user = new User();
    user.setSex(1);
    user.setAddress("武侯");
    user.setBirth(new Date());
    user.setAge(19);
    user.setName("武则天");
    userMapper.insertByJavaBean(user);
}

方案二:封装成map

UserMapper.java

// 方案二:封装成map #{变量} 这个变量必须是map中的key
    User selectUserByMap(Map map);

UserMapper.xml
– 封装成map #{变量} 这个变量必须是map中的key

   <select id="selectUserByMap" resultType="user">
        select * from user where name = #{userName} and address = #{userAddress}
    </select>

测试类

  @Test
    public void selectUserByMap(){
        SqlSession sqlSession = MyBatisUtil.openSession();
        UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
        System.out.println(userMapper);
        Map map = new HashMap<>();
        map.put("userName","tony");
        map.put("userAddress","成都");
        User user = userMapper.selectUserByMap(map);
        System.out.println("user = " + user);
        sqlSession.close();
    }

方案三:使用@Param注解

UserMapper.java

 /* 方案三:使用@Param注解 底层是map map.put("nameKey","nameValue");map.put("addressKey","addressValue")
    #{变量} 这个变量必须是@Param注解中的名称
    */
    User selectUserByParam(@Param("nameKey") String nameValue,@Param("addressKey")String addressValue);

UserMapper.xml

   <select id="selectUserByParam" resultType="user">
select * from user where name = #{nameKey} and address = #{addressKey}
</select>

测试类

@Test
public void selectUserByParam(){
    SqlSession sqlSession = MyBatisUtil.openSession();
    UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
    System.out.println(userMapper);
    User user = userMapper.selectUserByParam("lili","成都");
    System.out.println("user = " + user);
    sqlSession.close();
}

十、分页查询(PageHelper)

PageHelper(GitHub)https://pagehelper.github.io/
官方文档:https://pagehelper.github.io/docs/howtouse/

使用 Maven
在 pom.xml 中添加如下依赖:

<!-- 分页插件jar -->
<dependency>
    <groupId>com.github.pagehelper</groupId>
    <artifactId>pagehelper</artifactId>
    <version>5.2.0</version>
</dependency>

在mybatis-config.xml文件中typeAliases后面写分页插件的配置

<!--分页插件的 配置-->
<plugins>
    <plugin interceptor="com.github.pagehelper.PageInterceptor">
        <!--通过这个配置,来动态添加分页的功能-->
        <property name="helperDialect" value="mysql"/>
        <!--通过pageSizeZero属性可以灵活处理分页 当pageSize 设置为0就查询全部数据-->
        <property name="pageSizeZero" value="true"/>
        <!--通过reasonable 属性 可以合理化分页-->
        <property name="reasonable" value="true"/>
    </plugin>
</plugins>

UserMapper.java

List<User> selectAll();

UserMapper.xml

  <select id="selectAll" resultType="user">
        select * from user
    </select>

测试类

  @Test
    public void selectByPageHelper(){
        SqlSession sqlSession = MyBatisUtil.openSession();
        UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
        System.out.println(userMapper);
        // 分页代码
        //当pageSize = 0时,相当于没有分页,查询所有的数据
        PageHelper.startPage(2, 2);

        List<User> userList = userMapper.selectAll();
        for (User user : userList) {
            System.out.println("user = " + user);
        }
        // 封装一个pageInfo对象,就可以知道它的其他信息(上一页,下一页,总页数,总条数)
        PageInfo<User> userPageInfo = new PageInfo<>(userList);
        System.out.println("总页数:"+userPageInfo.getPages());
        System.out.println("下一页:"+userPageInfo.getNextPage());
        System.out.println("上一页:"+userPageInfo.getPrePage());
        System.out.println("总条数:"+userPageInfo.getTotal());
        System.out.println("当前页:"+userPageInfo.getPageNum());
        System.out.println("每页显示条数:"+userPageInfo.getPageSize());
        sqlSession.close();
    }

十一、新增自增长

Mybatis在insert指令中,提供了2个属性:useGeneratedKeys、keyProperty、keyColumn
useGeneratedKeys:表示使用数据库自增长
keyProperty:自增长的列对应的类中的属性
keyColumn:自增长的列
Mybatis会自动将增长的值,封装到传入参数的属性中。

UserMapper.xml

 <insert id="insertByJavaBean" useGeneratedKeys="true" keyProperty="id">
        insert into  user(name,age,sex,address,birth) values (#{name},#{age},#{sex},#{address},#{birth});
    </insert>

测试类

  @Test
    public void insertByJavaBean(){
        SqlSession sqlSession = MyBatisUtil.openSession();
        UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
        System.out.println(userMapper);
        User user = new User();
        user.setSex(1);
        user.setAddress("武侯");
        user.setBirth(new Date());
        user.setAge(19);
        user.setName("武则天");
        userMapper.insertByJavaBean(user);
        System.out.println("user.getId() = " + user.getId());
        sqlSession.close();
    }

十二、动态SQL

1.if标签

在if标签中,test属性是必须有,test属性值是一个表达式,如果表达式值为true,则if标签包裹的内容会拼接在当前sql上。
and 并且
or 或者
== 等于
!= 不等于

用户搜索模糊查询如果输入为null或空的字符串

   @Test
    public void selectUserByKeyword(){
        SqlSession sqlSession = MyBatisUtil.openSession();
        UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
        System.out.println(userMapper);
//        List<User> userList = userMapper.selectUserByKeyword("lili");
        List<User> userList = userMapper.selectUserByKeyword(null);
        userList.forEach(System.out::println);
    }
<select id="selectUserByKeyword" resultType="user">
        select * from user
        <if test="keyword!=null and keyword!='' ">
        where name like concat('%',#{keyword},'%');
        </if>
    </select>

查询多个条件的情况下
UserMapper.java

  List<User> selectByCondition(@Param("keyword") String keyword,
                                 @Param("birthday")Date birth);

UserMapper.xml

<select id="selectByCondition" resultType="user">
    select * from user
    <if test="keyword!=null and keyword!=''" >
        where name like concat('%',#{keyword},'%')
    </if>
    <if test="birthday!=null">
        and birth like concat ('%',year(#{birthday}),'%')
    </if>
</select>

测试类

  // 查询指定某一年的用户信息,并且支持名字模糊查询
    @Test
    public void selectByCondtion(){
        SqlSession sqlSession = MyBatisUtil.openSession();
        UserMapper userMapper = sqlSession.getMapper(UserMapper.class);

        List<User> userList = userMapper.selectByCondition("lili",new Date());
        userList.forEach(System.out::println);
    }

如果keyword为空字符串

 // 查询指定某一年的用户信息,并且支持名字模糊查询
    @Test
    public void selectByCondtion(){
        SqlSession sqlSession = MyBatisUtil.openSession();
        UserMapper userMapper = sqlSession.getMapper(UserMapper.class);

        List<User> userList = userMapper.selectByCondition("",new Date());
        userList.forEach(System.out::println);
    }

sql报错
在这里插入图片描述
如何改进?

<select id="selectByCondition" resultType="user">
    select * from user where 1=1
    <if test="keyword!=null and keyword!=''" >
        and name like concat('%',#{keyword},'%')
    </if>
    <if test="birthday!=null">
        and birth like concat ('%',year(#{birthday}),'%')
    </if>
</select>

产生的新的问题:where 1=1 会导致索引失效

引入where标签

2.where标签

在mybatis中,存在sql条件,当有多个sql条件时,需要处理and关键字问题,因为where后面的第一个条件不需要and,解决方案:
①在where后面 拼接 1=1 类似的条件,这样其他条件都不是第一个条件,都需要拼接and
②mybatis 提供了where标签,取代where关键字,默认去掉第一个条件 and

注意:
建议,只在查询语句中使用where标签,因为当where标签中的条件都不成立时,会没有where关键字。

 <!--  where 可以把第一个and 去掉  -->
    <select id="selectByCondition" resultType="user">
        select * from user
        <where>
            <if test="keyword!=null and keyword!=''">

                and name like concat('%',#{keyword},'%')
            </if>
            <if test="birthday!=null">
                and birth like concat ('%',year(#{birthday}),'%')
            </if>
        </where>
    </select>

3.Foreach标签

Select * from user where id in (1,2,3,4)
循环标签,循环标签多用于批量操作。
例如:批量新增,批量删除,批量查询等等
1.collection 待循环的容器 (容器为数组值为array,容器为集合值为list)
2.item 指代 每次循环容器中的元素
3.open 开始循环是拼接字符串
4.close 循环结束拼接字符串
5.separator 每次循环之间拼接的字符串
6.index 循环索引

3.1 批量查询

3.1.1 数组
① 普通数组

UserMapper.java

   /*
    * 批量查询
    * 需求:查询id1、2、3、4的用户信息
    * sql:select * from user where id in(1,2,3,4)
    */
    List<User> selectByIdsWithArray(Long[] ids);

UserMapper.xml

 <!--
      select * from user where id in 固定 动态拼接:(1,2,3,4)
      属性:
           collection 表示 传入参数的类型 是数组 就写 array 如果是集合,就写list
           open 表示 开始的部分 例如:小括号的左半边是开始的部分
           close 表示 结束的部分 例如:小括号的右半边是结束的部分
           item 表示 接收元素的变量,(用来接收遍历容器中的 每一个元素)
           separator 表示元素与元素之间的 分隔符号 例如:逗号
      -->
    <select id="selectByIdsWithArray" resultType="user">
        select * from user where id in
        <foreach collection="array" open="(" close=")" item="id" separator=",">
            #{id}
        </foreach>
    </select>

测试类

  @Test
    public void selectByIdsWithArray() {
        SqlSession sqlSession = MyBatisUtil.openSession();
        UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
        System.out.println(userMapper);
        Long[] ids = {2L,3L,4L};
        List<User> userList = userMapper.selectByIdsWithArray(ids);
        userList.forEach(System.out::println);

    }
② 数组+@Param注解

xml中的collection的值可以为@Param中的key

UserMapper.java
这里用了@Param注解

List<User> selectByIdsWithArrayAndParam(@Param("ids") Long[] ids);

UserMapper.xml
xml中collection的值可以为@Param中的key

<select id="selectByIdsWithArrayAndParam" resultType="user">
    select * from user where id in
    <foreach collection="ids" open="(" close=")" item="id" separator=",">
        #{id}
    </foreach>
</select>

测试类

@Test
public void selectByIdsWithArrayAndParam(){
    SqlSession sqlSession = MyBatisUtil.openSession();
    UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
    System.out.println(userMapper);
    Long[] ids = {2L,3L,4L};
    List<User> userList = userMapper.selectByIdsWithArrayAndParam(ids);
    userList.forEach(System.out::println);
}
3.1.2 集合
①普通集合

UserMapper.java

  List<User> selectByIdsWithList(List<Long> ids);\

UserMapper.xml

  <select id="selectByIdsWithList" resultType="user">
        select * from user where id in
        <foreach collection="list" open="(" close=")" item="id" separator=",">
            #{id}
        </foreach>
    </select>

测试类

 @Test
    public void selectByIdsWithList(){
        SqlSession sqlSession = MyBatisUtil.openSession();
        UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
        System.out.println(userMapper);
        List<Long> ids = Arrays.asList(2L,3L,4L);
        List<User> userList = userMapper.selectByIdsWithList(ids);
        userList.forEach(System.out::println);
    }
② 集合+@Param注解

xml中的collection的值可以为@Param中的key
UserMapper.java
这里用了@Param注解

 List<User> selectByIdsWithListAndParam(@Param("ids") List<Long> ids);

UserMapper.xml
xml中collection的值可以为@Param中的key

<select id="selectByIdsWithListAndParam" resultType="user">
    select * from user where id in
    <foreach collection="ids" open="(" close=")" item="id" separator=",">
        #{id}
    </foreach>
</select>

测试类

   @Test
    public void selectByIdsWithListAndParam(){
        SqlSession sqlSession = MyBatisUtil.openSession();
        UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
        System.out.println(userMapper);
        List<Long> ids = Arrays.asList(2L,3L,4L);
        List<User> userList = userMapper.selectByIdsWithListAndParam(ids);
        userList.forEach(System.out::println);
    }

3.2 批量新增

UserMapper.java

 //批量插入
    void insertBatchWithList(List<User> userList);

UserMapper.xml

    <!--
 insert into user (name,age,sex,address,birth) values
          (#{name},#{age},#{sex},#{address},#{birth}),
          (#{name},#{age},#{sex},#{address},#{birth}),
          (#{name},#{age},#{sex},#{address},#{birth})

-->
    <insert id="insertBatchWithList">
        insert into user (name,age,sex,address,birth) values
        <foreach collection="list" separator="," item="user">
            (#{user.name},#{user.age},#{user.sex},#{user.address},#{user.birth})
        </foreach>
    </insert>

测试类

  @Test
    public void insertBatchWithList() {
        SqlSession sqlSession = MyBatisUtil.openSession();
        UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
        System.out.println(userMapper);
        List<User> userList = Arrays.asList(new User(null,"股市",2,1,"广州",new Date()),new User(null,"顾问",2,1,"成都",new Date()));
        userMapper.insertBatchWithList(userList);
        sqlSession.close();
    }

4 choose标签

choose
多条件分支标签:choose.
在choose标签,自上而下执行when中表达式,如果表达式为true,则将相应的字符串拼接在sql后面,且终止判断。如果所有的表达式都为false,则将otherwise中字符串,拼接在sql后面

UserMapper.java

/*choose标签
    * 需求:根据年龄查询不同区间的用户信息
    * */
    List<User> selectByAge(int age);

UserMapper.xml

<!--
     choose 标签 配有两种子标签 一种是 <when> 一种是<otherwise>
     特点:<when>可以写多个 至少要提供一个
           test属性 它是boolean,如果表达式成立,则拼接when中的条件
           如果不成立,则拼接otherwise里面的条件
     -->
    <select id="selectByAge" resultType="user">
        select * from user where
        <choose>
            <when test="age>80">
                age &gt; 80
            </when>

            <when test="age>60 and age &lt;80">
                age &gt; 60 and age &lt;80
            </when>

            <when test="age> 20and age &lt; 60">
                age &gt; 20 and age &lt;60
            </when>

            <otherwise>
            age &lt; 20
            </otherwise>
        </choose>
    </select>

测试类

   @Test
    public void selectByAgeWithChoose() {
        SqlSession sqlSession = MyBatisUtil.openSession();
        UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
        System.out.println(userMapper);
        List<User> userList = userMapper.selectByAge(10);
        userList.forEach(System.out::println);
        sqlSession.close();
    }

5.set标签

set标签是取代sql语句中的set关键字。set表示后面数据的更新。各个字段,需要使用逗号分隔。
set标签可以去掉最后一个逗号。

UserMapper.java



 /*set标签
    * 需求:根据提供的数据进行相应的修改
    */
    void updateByCondition(User user);

UserMapper.xml

   <!-- set标签可以去掉默认的逗号   -->
    <update id="updateByCondition">
        update user
        <set>
            <if test="name!=null and name!=''">
                name = #{name},
            </if>
            <if test="age>0">
                age = #{age},
            </if>
            <if test="sex &lt; 2 and sex > -1">
                sex = #{sex},
            </if>
            <if test="address!=null and address!=''">
                address = #{address},
            </if>
            <if test="birth!=null">
                birth = #{birth}
            </if>
        </set>
        where id = #{id}
    </update>

测试类

   @Test
    public void updateByCondition() {
        SqlSession sqlSession = MyBatisUtil.openSession();
        UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
        System.out.println(userMapper);
        User user = new User();
        user.setName("嫦娥一号");
//        user.setAge(2);
//        user.setBirth(new Date());
//        user.setAddress("北京");
//        user.setSex(1);
        user.setId(3L);
        userMapper.updateByCondition(user);

十三、缓存

mybatis为了提高查询效率、性能。提供了缓存,缓存分为2类:
一级缓存
二级缓存
一级缓存:是指SqlSession级别的缓存,在同一个SqlSession,同样的SQL语句只会执行一次,不是第一次执行的SQL会从缓存中获取数据。
二级缓存: 是指SqlSessionFactory级别的缓存,在同一个SqlSessionFactory中,同样的SQL语句,只会执行一次,不是第一次执行的SQL会从缓存中获取数据。
注意:
不论一级缓存还是二级缓存,否是JVM中缓存。当服务器有多台时,缓存容易发生无效,数据发生了更新。缓存没有更新。在实际使用,如果数据可能发生比较频繁的更新不建议使用mybatis。

一级缓存

@Test
public void selectAllCache(){
    SqlSession sqlSession = MyBatisUtil.openSession();
    UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
    System.out.println(userMapper);
    List<User> userList = userMapper.selectAll();
    for (User user : userList) {
        System.out.println("user = " + user);
    }
    
    System.out.println("---------------------------------------------------");

    List<User> userList1 = userMapper.selectAll();
    for (User user : userList1) {
        System.out.println("user = " + user);
    }
    sqlSession.close();
}

发现只执行了一次SQL
在这里插入图片描述
多个sqlSession,就执行多次sql

 @Test
    public void selectAllCacheTwoSqlSession(){
        SqlSession sqlSession = MyBatisUtil.openSession();
        UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
        System.out.println(userMapper);
        List<User> userList = userMapper.selectAll();
        for (User user : userList) {
            System.out.println("user = " + user);
        }

        sqlSession.close();
        System.out.println("---------------------------------------------------");

        SqlSession sqlSession1 = MyBatisUtil.openSession();
        UserMapper userMapper1 = sqlSession1.getMapper(UserMapper.class);
        List<User> userList1 = userMapper1.selectAll();
        for (User user : userList1) {
            System.out.println("user = " + user);
        }
        sqlSession.close();
    }

多个sqlSession 执行多次sql
在这里插入图片描述

// 默认一级缓存是开启,那么意味者 在sqlSession 对象没有关闭之前
执行多次一样的查询,是不会多次发送sql语句的。
}

如果执行完查询之后,把sqlSession 对象关闭了,则意味者一级缓存释放了
则,再执行同样的查询,也需要发送sql 语句

二级缓存

二级缓存需要在映射的xml配置文件中,开启缓存:

并且被缓存的module数据需要支持,序列化

在UserMapper.java中开启二级缓存标签
在这里插入图片描述
module对象实现Serializable接口
在这里插入图片描述
再次执行测试类

@Test
public void selectAllCacheTwoSqlSession(){
    SqlSession sqlSession = MyBatisUtil.openSession();
    UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
    System.out.println(userMapper);
    List<User> userList = userMapper.selectAll();
    for (User user : userList) {
        System.out.println("user = " + user);
    }

    sqlSession.close();
    System.out.println("---------------------------------------------------");

    SqlSession sqlSession1 = MyBatisUtil.openSession();
    UserMapper userMapper1 = sqlSession1.getMapper(UserMapper.class);
    List<User> userList1 = userMapper1.selectAll();
    for (User user : userList1) {
        System.out.println("user = " + user);
    }
    sqlSession.close();
}

有50%的几率,只执行了一次Sql
在这里插入图片描述

十四、Mybatis注解

@Select
@Insert
@Delete
@Update

UserMapper.java

 @Select("select * from user")
    List<User> selectAllByAnno();

测试类

@Test
public void selectAllByAnno(){
    SqlSession sqlSession = MyBatisUtil.openSession();
    UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
    System.out.println(userMapper);
    List<User> userList = userMapper.selectAllByAnno();
    for (User user : userList) {
        System.out.println("user = " + user);
    }
}

相关文章:

  • nodejs+vue+elementui旅游资源网站python-java景点门票预订网站php
  • ArrayList 源码浅析
  • 毕业设计 基于单片机的智能音响设计与实现 -物联网 嵌入式 stm32
  • 【区块链】从社区平台MOJOR看,为何Web3需要原生?
  • 2022年 研究生数学建模题目
  • C# 算数运算符
  • TC8:TCP_HEADER_01-11
  • Mysql出现问题:慢查询日志失效解决方案
  • Unity接入TopOn聚合广告平台SDK【聚合了穿山甲,优量汇(腾讯广告),快手,Mintegral,sigmob等各大广告平台SDK】
  • 【leetcode】和最小的 k 个数对
  • Java 程序控制结构(4)
  • C++动态空间申请
  • WEB安全之javascript基础(一):js的引入方法注释变量数据类型
  • 【node进阶】深度解析Express框架--路由、中间件
  • 硬件设计基础----通信协议UART
  • 分享的文章《人生如棋》
  • [case10]使用RSQL实现端到端的动态查询
  • Bytom交易说明(账户管理模式)
  • C语言笔记(第一章:C语言编程)
  • MYSQL如何对数据进行自动化升级--以如果某数据表存在并且某字段不存在时则执行更新操作为例...
  • Promise面试题2实现异步串行执行
  • SQL 难点解决:记录的引用
  • 基于webpack 的 vue 多页架构
  • 快速构建spring-cloud+sleuth+rabbit+ zipkin+es+kibana+grafana日志跟踪平台
  • 罗辑思维在全链路压测方面的实践和工作笔记
  • 数组大概知多少
  • 一些关于Rust在2019年的思考
  • 优化 Vue 项目编译文件大小
  • 通过调用文摘列表API获取文摘
  • ​比特币大跌的 2 个原因
  • ​总结MySQL 的一些知识点:MySQL 选择数据库​
  • # Apache SeaTunnel 究竟是什么?
  • #快捷键# 大学四年我常用的软件快捷键大全,教你成为电脑高手!!
  • $$$$GB2312-80区位编码表$$$$
  • $.type 怎么精确判断对象类型的 --(源码学习2)
  • (Arcgis)Python编程批量将HDF5文件转换为TIFF格式并应用地理转换和投影信息
  • (第27天)Oracle 数据泵转换分区表
  • (二)fiber的基本认识
  • (附源码)springboot高校宿舍交电费系统 毕业设计031552
  • (个人笔记质量不佳)SQL 左连接、右连接、内连接的区别
  • (数据结构)顺序表的定义
  • (学习日记)2024.01.19
  • ****Linux下Mysql的安装和配置
  • .NET Core Web APi类库如何内嵌运行?
  • .NET 药厂业务系统 CPU爆高分析
  • .NET 中小心嵌套等待的 Task,它可能会耗尽你线程池的现有资源,出现类似死锁的情况
  • @DateTimeFormat 和 @JsonFormat 注解详解
  • @EnableConfigurationProperties注解使用
  • @RequestParam @RequestBody @PathVariable 等参数绑定注解详解
  • [2016.7 test.5] T1
  • [acwing周赛复盘] 第 69 场周赛20220917
  • [C++][数据结构][算法]单链式结构的深拷贝
  • [CF482B]Interesting Array
  • [C和指针].(美)Kenneth.A.Reek(ED2000.COM)pdf
  • [C语言]编译和链接