MyBatis简单入门

快速入门

一些pom.xml依赖

  <dependencies>

    <!-- 单元测试 -->
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>4.11</version>
      <scope>test</scope>
    </dependency>

    <!-- mybatis -->
    <dependency>
      <groupId>org.mybatis</groupId>
      <artifactId>mybatis</artifactId>
      <version>3.5.13</version>
    </dependency>

      <!-- mysql -->
    <dependency>
      <groupId>mysql</groupId>
      <artifactId>mysql-connector-java</artifactId>
      <version>8.0.30</version>
    </dependency>

    <!-- slf4j-api -->
    <dependency>
      <groupId>org.slf4j</groupId>
      <artifactId>slf4j-api</artifactId>
      <version>1.7.20</version>
    </dependency>

    <!-- logback-classic -->
    <dependency>
      <groupId>ch.qos.logback</groupId>
      <artifactId>logback-classic</artifactId>
      <version>1.2.3</version>
    </dependency>

    <!-- logback-core -->
    <dependency>
      <groupId>ch.qos.logback</groupId>
      <artifactId>logback-core</artifactId>
      <version>1.4.8</version>
    </dependency>

  </dependencies>

mybatis-config.xml配置文件

注意,这里由于xml语法,&是非法的,将其转换成&amp;

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
  PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
  "https://mybatis.org/dtd/mybatis-3-config.dtd">

  <!-- environments:配置数据库了环境信息,可以配置多个environment,通过defavlt属性切换不同的environment -->

<configuration>
  <environments default="development">
    <environment id="development">
      <transactionManager type="JDBC"/>
      <dataSource type="POOLED">
        <property name="driver" value="com.mysql.cj.jdbc.Driver"/>
        <property name="url" value="jdbc:mysql://localhost:3306/jdbc?useSSL=false&amp;allowPublicKeyRetrieval=true&amp;serverTimezone=UTC&amp;useOldAliasMetadataBehavior=true&amp;useServerPrepStmts=true"/>
        <property name="username" value="root"/>
        <property name="password" value="5508769123"/>
      </dataSource>
    </environment>

    <environment id="test">
      <transactionManager type="JDBCC"/>
      <dataSource type="POOLED">
        <property name="driver" value="com.mysql.cj.jdbc.Driver"/>
        <property name="url" value="jdbc:mysql://localhost:3306/jdbcc?useSSL=false&amp;allowPublicKeyRetrieval=true&amp;serverTimezone=UTC&amp;useOldAliasMetadataBehavior=true&amp;useServerPrepStmts=true"/>
        <property name="username" value="roottt"/>
        <property name="password" value="114514"/>
      </dataSource>
    </environment>

  </environments>
  <mappers>
    <!-- 加载sql映射文件 -->
    <mapper resource="StudentMapper.xml"/>
  </mappers>
</configuration>

注意:这里的加载sql映射文件:有下面两种方法:1.挨个挨个写;2.包扫描

  1. 挨个挨个写

    就是上面的写法,不过当有多个XXXMapper时需要将所有的都按照这个方法写出来

  2. 包扫描见下面的mapper代理开发部分

编写SQL映射文件

StudentMapper.xml

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
  PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
  "https://mybatis.org/dtd/mybatis-3-mapper.dtd">
 <!--
    namespace:名称空间
    id:sql语句唯一标识符(不能重复)
    resultType:返回结果的类型,将来需要返回什么包装结果类型就写什么
    -->
<mapper namespace="test">
  <select id="selectAll" resultType="pojo.Student">
    select * from student;
  </select>
</mapper>

使用相对路径

image-20230629212745405

一些测试类

Student.java

package pojo;

public class Student {
    private Integer id;
    private String name;
    private String sex;
    private Integer age;
    public Integer getId() {
        return id;
    }
    public void setId(Integer id) {
        this.id = id;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public String getSex() {
        return sex;
    }
    public void setSex(String sex) {
        this.sex = sex;
    }
    public Integer getAge() {
        return age;
    }
    public void setAge(Integer age) {
        this.age = age;
    }
    @Override
    public String toString() {
        return "Student [id=" + id + ", name=" + name + ", sex=" + sex + ", age=" + age + "]";
    }
}

MyBasitDemo.java

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

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 pojo.Student;

public class MyBasitDemo {
    public static void main(String[] args) throws IOException {
        // 1.加载mybatis的核心配置文件,获取SqlSessionFactory
        String resource = "config\\anyshare\\mybatis-config.xml";
        InputStream inputStream = Resources.getResourceAsStream(resource);
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);

        // 2.获取SqlSession对象,用它来执行sql
        SqlSession sqlSession = sqlSessionFactory.openSession();

        // 3.执行sql
        List<Student> users = sqlSession.selectList("test.selectAll");
        System.out.println(users);

        // 4.释放资源
        sqlSession.close();
    }
}

注意

        List<Student> users = sqlSession.selectList("test.selectAll");

中的test.selectAllStudentMapper.xml 中的指定的部分namespace.select id

Mapper代理开发

具体步骤

image-20230629220303053

对于第一步,先了解maven打包之后的框架。

image-20230629221726864

可以发现,在源文件中StudentMapper.xml是放在resources文件夹中,但是打包成target之后StudentMapper.xml就没有resource目录了,因此若要想StudentMapper.java打包之后与StudentMapper.xml同一个同一文件夹下,可以将源文件中StudentMaper.xml放在与StudentMapper.java同一个结构之下(不是复制放在一起而是新创路径),这样打包之后StudentMapper.xml将会被自动塞进与StudentMapper.java同一文件夹。如下:

  1. 定义与SQL映射文件同名的Mapper接口,并且将Mapper接口和SQL映射文件放置同一目录之下

image-20230629222628450

因此,配置文件mybatis-config.xml也要随之改变

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
  PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
  "https://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.cj.jdbc.Driver"/>
        <property name="url" value="jdbc:mysql://localhost:3306/jdbc?useSSL=false&amp;allowPublicKeyRetrieval=true&amp;serverTimezone=UTC&amp;useOldAliasMetadataBehavior=true&amp;useServerPrepStmts=true"/>
        <property name="username" value="root"/>
        <property name="password" value="5508769123"/>
      </dataSource>
    </environment>
  </environments>
  <mappers>
    <!-- 加载sql映射文件 -->
    <mapper resource="mapper\StudentMapper.xml"/>
  </mappers>
</configuration>

StudentMapper.java

package mapper;

import java.util.List;

import pojo.Student;

public interface StudentMapper {
    List<Student> selectAll();
}
  1. 设置SQL映射文件的namespace属性为Mapper接口全限定名称,如下面的mapper.StudentMapper

    StudentMapper.xml

    <?xml version="1.0" encoding="UTF-8" ?>
    <!DOCTYPE mapper
      PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
      "https://mybatis.org/dtd/mybatis-3-mapper.dtd">
     <!--
        namespace:名称空间
        id:sql语句唯一标识符(不能重复)
        resultType:返回结果的类型,将来需要返回什么包装结果类型就写什么
        -->
    <!-- 使用mapper代理 -->
    <mapper namespace="mapper.StudentMapper">
      <select id="selectAll" resultType="pojo.Student">
        select * from student;
      </select>
    </mapper>
    
  2. 在Mapper接口中定义方法,方法名就是SQL映射文件中sql语句的id,并保持参数类型和返回类型一致

    StudentMapper.java

    package mapper;
    
    import java.util.List;
    
    import pojo.Student;
    
    public interface StudentMapper {
        List<Student> selectAll();
    }
    

使用mapper代理中的包扫描

如果Mapper接口名称和SQL映射文件名称相同,并且放在同一目录下,则可以使用包扫描的方式简化SQL映射文件的加载

上述代理中,有一个StudentMapper文件就要在mybatis-config.xml添加一行映射

<mapper resource="mapper\StudentMapper.xml"/>

这样当映射多了的时候添加起来很麻烦,就干脆直接添加映射文件的文件夹,到时候直接扫描该文件夹下的映射文件

mybatis-config.xml修改如下:

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
  PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
  "https://mybatis.org/dtd/mybatis-3-config.dtd">

  <!-- environments:配置数据库了环境信息,可以配置多个environment,通过defavlt属性匹配不同的id值来切换不同的environment -->

<configuration>
  <environments default="development">
    <environment id="development">
      <transactionManager type="JDBC"/>
      <dataSource type="POOLED">
        <property name="driver" value="com.mysql.cj.jdbc.Driver"/>
        <property name="url" value="jdbc:mysql://localhost:3306/jdbc?useSSL=false&amp;allowPublicKeyRetrieval=true&amp;serverTimezone=UTC&amp;useOldAliasMetadataBehavior=true&amp;useServerPrepStmts=true"/>
        <property name="username" value="root"/>
        <property name="password" value="5508769123"/>
      </dataSource>
    </environment>
  <mappers>
    <!-- Mapper 代理方法:包扫描 -->
    <!-- 注意,格式不是路径格式那般,例如文件目录:com/mapper对应的应该写为:com.mapper
    因为这里没有上级目录,所以特此说明 -->
    <package name="mapper"/>
  </mappers>
</configuration>

  1. 测试编码:

    MyBasitDemo.java

    import java.io.IOException;
    import java.io.InputStream;
    import java.util.List;
    
    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 mapper.StudentMapper;
    import pojo.Student;
    
    // mapper代理开发
    
    public class MyBasitDemo {
        public static void main(String[] args) throws IOException {
            // 1.加载mybatis的核心配置文件,获取SqlSessionFactory
            String resource = "config\\anyshare\\mybatis-config.xml";
            InputStream inputStream = Resources.getResourceAsStream(resource);
            SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
    
            // 2.获取SqlSession对象,用它来执行sql
            SqlSession sqlSession = sqlSessionFactory.openSession();
    
            // 3.获取StudentMapper接口的代理对象
            StudentMapper studentMapper = sqlSession.getMapper(StudentMapper.class);
            
            //4.执行
            List<Student> students = studentMapper.selectAll();
            System.out.println(students);
    
            // 5.释放资源
            sqlSession.close();
        }
    }
    
    

查询

字段名称不一致问题

由于查询时要求类中的成员字段(Java采用驼峰命名)要与数据库中的标段相同(采用下划线),因此若不大同则会出现查询结果某成员为null的情况

​ 数据库:image-20230630232400635

​ Java:image-20230630231746128

可以发现,nameCh,nameEn均与数据库中字段不一致

查询方法采用上面Mapper代理中的MyBasitDemo.java类方法

将会得到下面的结果:

方法一:对SQL语句起别名

StudentMapper.xml文件中的SQL语句中不对应的列名采用起与StudentMapper.java中一致的别名。

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
  PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
  "https://mybatis.org/dtd/mybatis-3-mapper.dtd">

 <!--
    namespace:名称空间
    id:sql语句唯一标识符(不能重复)
    resultType:返回结果的类型,将来需要返回什么包装结果类型就写什么
    -->
<!-- 使用mapper代理 -->
<mapper namespace="mapper.StudentMapper">
  <sql id = "student_column">
    id,name_ch as nameCh,sex,age,name_en as nameEn
  </sql>
  <select id="selectAll" resultType="pojo.Student">
    select
      <include refid = "student_column" />
     from student;
  </select>
</mapper>

再次执行查询语句:

image-20230630233828769

方法二: 采用resultMap映射

sql相关知识可知,若要取别名则需要列出所有的列名(尽管不需要),这样是十分繁琐的。因此可以采用更为灵活的方法来映射

StudentMapper.xml进行修改

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
  PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
  "https://mybatis.org/dtd/mybatis-3-mapper.dtd">

  <!-- 使用resultMap方法解决:列名与数据库为标段不一致问题 -->
<mapper namespace="mapper.StudentMapper">
    
  <resultMap id = "studentResultMap" type = "pojo.Student">
	<!-- 需要定义别名的放在这里面
			id:完成主键字段映射
				column:表的列名
				property:实体类的属性名
			result:完成一般字段的映射
				column:表的列名
				property:实体类的属性名
 	-->
    <result column = "name_ch" property = "nameCh"/>
    <result column = "name_en" property = "nameEn"/>
  </resultMap>

  <select id = "selectAll" resultMap = "studentResultMap">
    select * from student;
  </select>
    
</mapper>

条件查询

单条件查询

StudentMapper.xml

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
  PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
  "https://mybatis.org/dtd/mybatis-3-mapper.dtd">

  <!-- 使用resultMap方法解决:列名与数据库为标段不一致问题 -->
<mapper namespace="mapper.StudentMapper">
    
  <!-- 不一致且需要起别名的字段放这里 -->
  <resultMap id = "studentResultMap" type = "pojo.Student">
    <result column = "name_ch" property = "nameCh"/>
    <result column = "name_en" property = "nameEn"/>
  </resultMap>

  <!--
    参数占位符:
      1. #{}:会将其替换为 ? ,为了防止SQL注入
      2.${}:拼sql,会存在SQL注入问题
      3.使用时机:
        参数传递的时候:#{}
        表名或者列名不固定的情况:${} 但会存在SQL注入问题
    参数类型:parameterType:可以省略
   -->
  <select id = "selectById" parameterType = "int" resultMap = "studentResultMap">
    <!-- #{一般与接口中方法参数名称一样} -->
    select * from student where id = #{id}; 
  </select>
</mapper>

StudentMapper.java中添加相应的接口方法Student selectById(int id);

package mapper;

import java.util.List;

import pojo.Student;

public interface StudentMapper {
    List<Student> selectAll();

    Student selectById(int id);
}

编写测试代码 MyBasitDemo.java

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

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 mapper.StudentMapper;
import pojo.Student;

// mapper代理开发

public class MyBasitDemo {
    public static void main(String[] args) throws IOException {
        // selectAll();
        selectById(2);
    }

    public static void selectAll() throws IOException {
        // 1.加载mybatis的核心配置文件,获取SqlSessionFactory
        String resource = "config\\anyshare\\mybatis-config.xml";
        InputStream inputStream = Resources.getResourceAsStream(resource);
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);

        // 2.获取SqlSession对象,用它来执行sql
        SqlSession sqlSession = sqlSessionFactory.openSession();

        // 3.获取StudentMapper接口的代理对象
        StudentMapper studentMapper = sqlSession.getMapper(StudentMapper.class);
        List<Student> students = studentMapper.selectAll();
        System.out.println(students);

        // 4.释放资源
        sqlSession.close();
    }

    public static void selectById(int id) throws IOException {
        // 1.加载mybatis的核心配置文件,获取SqlSessionFactory
        String resource = "config\\anyshare\\mybatis-config.xml";
        InputStream inputStream = Resources.getResourceAsStream(resource);
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);

        // 2.获取SqlSession对象,用它来执行sql
        SqlSession sqlSession = sqlSessionFactory.openSession();

        // 3.获取StudentMapper接口的代理对象
        StudentMapper studentMapper = sqlSession.getMapper(StudentMapper.class);

        // 4.执行
        Student student = studentMapper.selectById(id);
        System.out.println(student);

        // 5.释放资源
        sqlSession.close();
    }
}
SQL中特殊字符的处理

在xml与语句中<为标记符号,因此例如语句 select * from student where id < #{id}; 是非法的。

处理方法:1.将非法符号转译;2.使用CDATA空间

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
  PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
  "https://mybatis.org/dtd/mybatis-3-mapper.dtd">
<!-- 使用mapper代理 -->
  <!-- 使用resultMap方法解决:列名与数据库为标段不一致问题 -->
<mapper namespace="mapper.StudentMapper">
  <!-- 不一致且需要起别名的字段放这里 -->
  <resultMap id = "studentResultMap" type = "pojo.Student">
    <result column = "name_ch" property = "nameCh"/>
    <result column = "name_en" property = "nameEn"/>
  </resultMap>

  <select id = "selectAll" resultMap = "studentResultMap">
    select * from student;
  </select>

  <!--
    参数占位符:
      1. #{}:会将其替换为 ? ,为了防止SQL注入
      2.${}:拼sql,会存在SQL注入问题
      3.使用时机:
        参数传递的时候:#{}
        表名或者列名不固定的情况:${} 但会存在SQL注入问题
    参数类型:parameterType:可以省略
   -->
  <select id = "selectById" parameterType = "int" resultMap = "studentResultMap">
    <!-- #{一般与接口中方法参数名称一样} -->
    <!-- select * from student where id = #{id}; -->
    <!-- xml表示符号,<为xml的表示符号,不可写在sql中(小于号) -->
    <!-- 解决方法: -->
      <!-- 1.转义字符 -->
      <!-- select * from student where id &lt; 2; -->
      <!-- 2. 使用CDATA空间 将其识别为普通文本而非xml-->
      select * from student where id
      <![CDATA[
        <
      ]]>
       2;
  </select>
</mapper>
多条件查询

多条件查询

参数接受

​ 1.散装参数:如果方法中有多个参数,需要使用@Param("SQL参数占位符名称")

​ 2.对象参数:对象的属性名称要和参数占位符名称一致

​ 3.map集合参数:键的名称要和参数占位符名称一致

三种方式,StudentMapper.xml均不用修改

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
  PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
  "https://mybatis.org/dtd/mybatis-3-mapper.dtd">

  <!-- 使用resultMap方法解决:列名与数据库为标段不一致问题 -->
<mapper namespace="mapper.StudentMapper">
  <!-- 不一致且需要起别名的字段放这里 -->
  <resultMap id = "studentResultMap" type = "pojo.Student">
    <result column = "name_ch" property = "nameCh"/>
    <result column = "name_en" property = "nameEn"/>
  </resultMap>

  <!-- 多条件查询 -->
  <!-- 一般#{}里面的除了要与传入参数名称相同之外还要与类的属性名称一致 -->
  <select id = "selectByConditions" resultMap = "studentResultMap">
    select * from student where age &lt; #{age}
      and name_en like #{nameEn};
  </select>
</mapper>
方式一:散装参数

StudentMapper.java

package mapper;

import java.util.List;

import org.apache.ibatis.annotations.Param;

import pojo.Student;

public interface StudentMapper {
    // 1.散装参数
    // 当存在多个参数时,需要使用Param来区分传给xml的参数
    List<Student> selectByConditions(@Param("age") int age, @Param("nameEn") String nameEn);
}

MyBasitDemo.java

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

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 mapper.StudentMapper;
import pojo.Student;

// mapper代理开发

public class MyBasitDemo2 {
    public static void main(String[] args) throws IOException {
        selectByConditions(25, "a");
    }

    // 1.散装参数
    public static void selectByConditions(int age,String nameEn) throws IOException {
        // 1.加载mybatis的核心配置文件,获取SqlSessionFactory
        String resource = "config\\anyshare\\mybatis-config.xml";
        InputStream inputStream = Resources.getResourceAsStream(resource);
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);

        // 2.获取SqlSession对象,用它来执行sql
        SqlSession sqlSession = sqlSessionFactory.openSession();

        // 3.获取StudentMapper接口的代理对象
        StudentMapper studentMapper = sqlSession.getMapper(StudentMapper.class);

        // 4.执行
        // 参数处理
        nameEn = "%" + nameEn + "%";
        List<Student> students = studentMapper.selectByConditions(age, nameEn);
        System.out.println(students);

        // 5.释放资源
        sqlSession.close();
    }
}
方式二:对象参数

StudentMapper.java

package mapper;

import java.util.List;

import pojo.Student;

public interface StudentMapper {
    // 2.对象参数
     List<Student> selectByConditions(Student student);nameEn);
}

MyBasitDemo.java

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

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 mapper.StudentMapper;
import pojo.Student;

// mapper代理开发

public class MyBasitDemo2 {
    public static void main(String[] args) throws IOException {
        selectByConditions(25, "a");
    }

    // 2.对象参数
    public static void selectByConditions(int age, String nameEn) throws IOException {
        // 1.加载mybatis的核心配置文件,获取SqlSessionFactory
        String resource = "config\\anyshare\\mybatis-config.xml";
        InputStream inputStream = Resources.getResourceAsStream(resource);
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);

        // 2.获取SqlSession对象,用它来执行sql
        SqlSession sqlSession = sqlSessionFactory.openSession();

        // 3.获取StudentMapper接口的代理对象
        StudentMapper studentMapper = sqlSession.getMapper(StudentMapper.class);

        // 4.执行
        // 参数处理
        nameEn = "%" + nameEn + "%";
        // 封装对象
        Student student = new Student();
        student.setAge(age);
        student.setNameEn(nameEn);
        List<Student> students = studentMapper.selectByConditions(student);
        System.out.println(students);

        // 5.释放资源
        sqlSession.close();
    }
}
方式三:map集合参数

StudentMapper.java

package mapper;

import java.util.List;
import java.util.Map;

import pojo.Student;

public interface StudentMapper {
    // 3.map集合参数
    List<Student> selectByConditions(Map map);
}

MyBasitDemo.java

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

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 mapper.StudentMapper;
import pojo.Student;

// mapper代理开发

public class MyBasitDemo2 {
    public static void main(String[] args) throws IOException {
        selectByConditions(25, "a");
    }

    // 3.map集合参数
    public static void selectByConditions(int age,String nameEn) throws IOException {
        // 1.加载mybatis的核心配置文件,获取SqlSessionFactory
        String resource = "config\\anyshare\\mybatis-config.xml";
        InputStream inputStream = Resources.getResourceAsStream(resource);
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);

        // 2.获取SqlSession对象,用它来执行sql
        SqlSession sqlSession = sqlSessionFactory.openSession();

        // 3.获取StudentMapper接口的代理对象
        StudentMapper studentMapper = sqlSession.getMapper(StudentMapper.class);

        // 4.执行
        // 参数处理
        nameEn = "%" + nameEn + "%";
        // 封装对象
        HashMap<String, Object> hashMap = new HashMap<>();
        hashMap.put("age", age);
        hashMap.put("nameEn", nameEn);
        List<Student> students = studentMapper.selectByConditions(hashMap);
        System.out.println(students);

        // 5.释放资源
        sqlSession.close();
    }
}
动态多条件查询

在上面使用的条件查询语句存在问题,当三种方式中MyBasitDemo.java中的selectByConditions方法参数age、nameEn没有值即为null时SQL语句将查询不出结果(正常情况应该是返回该表的所有数据)。

使用逻辑判断:

StudentMapper.xml

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
  PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
  "https://mybatis.org/dtd/mybatis-3-mapper.dtd">

  <!-- 使用resultMap方法解决:列名与数据库为标段不一致问题 -->
<mapper namespace="mapper.StudentMapper">
  <!-- 不一致且需要起别名的字段放这里 -->
  <resultMap id = "studentResultMap" type = "pojo.Student">
    <result column = "name_ch" property = "nameCh"/>
    <result column = "name_en" property = "nameEn"/>
  </resultMap>

  <!--
    动态多条件查询
      if:条件判断
        test:逻辑表达式
  -->
  <select id = "selectByConditions" resultMap = "studentResultMap">
    select * from student where
    <if test = "age != null">
      age &lt; #{age}
    </if>
    <if test = "nameEn != null and nameEn !=''">
      <!-- nameEn不为空且不为空字符串 -->
      and name_en like #{nameEn};
    </if>
  </select>
</mapper>
  • 当age !=null且nameEn==null时,SQL语句为:

    select * from student where age < age;
    

但是这样也同样存在问题:不符合SQL规范

  • 当agenull且nameEnnull时,SQL语句为:

    select * from student where
    
  • 当age==null且nameEn!=null时,SQL语句为:

    select * from student where and name_en like nameEn;
    

解决方式:

一、用恒等式使其达到语法要求 1 = 1 ,让所有条件格式都一样

  <select id = "selectByConditionsDynamic" resultMap = "studentResultMap">
    select * from student where 1 = 1
    <if test = "age != null">
      and age &lt; #{age}
    </if>
    <if test = "nameEn != null and nameEn !=''">
      <!-- nameEn不为空且不为空字符串 -->
      and name_en like #{nameEn};
    </if>
  </select>

二、用 代替where

    <select id = "selectByConditionsDynamic" resultMap = "studentResultMap">
    select * from student
    <where>
      <if test = "age != null">
        and age &lt; #{age}
      </if>
      <if test = "nameEn != null and nameEn !=''">
        <!-- nameEn不为空且不为空字符串 -->
        and name_en like #{nameEn};
      </if>
    </where>
  </select>
单条件动态查询

从多个条件中选择一个

与上面动态多条件查询的不同是:if条件可以满足多个并执行相应SQL语句,而单条件只能执行一个

  • choose(when,otherwise):选择,类似于Java中switch语句

StudentMapper.java

package mapper;

import java.util.List;

import org.apache.ibatis.annotations.Param;

import pojo.Student;

public interface StudentMapper {
    // 单条件动态查询
    List<Student> selectByConditionDynamic(Student student);
}

MyBasitDemo.java

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

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 mapper.StudentMapper;
import pojo.Student;

// mapper代理开发
public class MyBasitDemo2 {
    public static void main(String[] args) throws IOException {
        selectByConditionDynamic("小","a");
    }

    public static void selectByConditionDynamic(String nameCh,String nameEn) throws IOException {
        // 1.加载mybatis的核心配置文件,获取SqlSessionFactory
        String resource = "config\\anyshare\\mybatis-config.xml";
        InputStream inputStream = Resources.getResourceAsStream(resource);
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);

        // 2.获取SqlSession对象,用它来执行sql
        SqlSession sqlSession = sqlSessionFactory.openSession();

        // 3.获取StudentMapper接口的代理对象
        StudentMapper studentMapper = sqlSession.getMapper(StudentMapper.class);

        // 4.执行
        // 参数处理
        nameEn = "%" + nameEn + "%";
        nameCh = "%" + nameCh + "%";
        // 封装对象
        Student student = new Student();
        student.setNameCh(null);
        student.setNameEn(null);
        List<Student> students = studentMapper.selectByConditionDynamic(student);
        System.out.println(students);

        // 5.释放资源
        sqlSession.close();
    }
}

StudentMapper.xml可以写成两种

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
  PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
  "https://mybatis.org/dtd/mybatis-3-mapper.dtd">

  <!-- 使用resultMap方法解决:列名与数据库为标段不一致问题 -->
<mapper namespace="mapper.StudentMapper">
  <!-- 不一致且需要起别名的字段放这里 -->
  <resultMap id = "studentResultMap" type = "pojo.Student">
    <result column = "name_ch" property = "nameCh"/>
    <result column = "name_en" property = "nameEn"/>
  </resultMap>

  <select id = "selectAll" resultMap = "studentResultMap">
    select * from student;
  </select>

  <select id = "selectByConditionDynamic" resultMap = "studentResultMap">
    select * from student
    <where>
      <!-- 相当于switch -->
      <choose>
        <!-- 相当于case -->
        <when test = "nameCh != null">
          name_ch like #{nameCh};
        </when>
        <!-- 相当于case -->
        <when test = "nameEn != null">
          name_en like #{nameEn};
        </when>
      </choose>
    </where>
  </select>

</mapper>

或者

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
  PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
  "https://mybatis.org/dtd/mybatis-3-mapper.dtd">

 <!-- 使用resultMap方法解决:列名与数据库为标段不一致问题 -->
<mapper namespace="mapper.StudentMapper">
  <!-- 不一致且需要起别名的字段放这里 -->
  <resultMap id = "studentResultMap" type = "pojo.Student">
    <result column = "name_ch" property = "nameCh"/>
    <result column = "name_en" property = "nameEn"/>
  </resultMap>

  <select id = "selectByConditionDynamic" resultMap = "studentResultMap">
    select * from student
    <where>
      <!-- 相当于switch -->
      <choose>
        <!-- 相当于case -->
        <when test = "nameCh != null">
          name_ch like #{nameCh};
        </when>
        <!-- 相当于case -->
        <when test = "nameEn != null">
          name_en like #{nameEn};
        </when>
      </choose>
    </where>
  </select>
    
</mapper>

添加

StudentMapper.xml

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
  PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
  "https://mybatis.org/dtd/mybatis-3-mapper.dtd">


<mapper namespace="mapper.StudentMapper">
  <!--
    keyProperty=的值为主键对应实体类属性的名称
    useGeneratedKeys= "true",获取返回主键
  -->
  <insert id = "add" useGeneratedKeys= "true" keyProperty = "id">
    insert into student(name_ch,sex,age,name_en)
    values(#{nameCh},#{sex},#{age},#{nameEn});
  </insert>

</mapper>

StudentMapper.java

package mapper;

import pojo.Student;

public interface StudentMapper {
    // 添加
    void add(Student student);
}

MyBasitDemo2.java

import java.io.IOException;
import java.io.InputStream;


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 mapper.StudentMapper;
import pojo.Student;

// mapper代理开发

public class MyBasitDemo2 {
    public static void main(String[] args) throws IOException {
        add("小李","男",16,"xiaoli");
    }

    public static void add(String nameCh,String sex,int age,String nameEn) throws IOException {
        // 1.加载mybatis的核心配置文件,获取SqlSessionFactory
        String resource = "config\\anyshare\\mybatis-config.xml";
        InputStream inputStream = Resources.getResourceAsStream(resource);
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);

        // 2.获取SqlSession对象,用它来执行sql
        SqlSession sqlSession = sqlSessionFactory.openSession();

        // 3.获取StudentMapper接口的代理对象
        StudentMapper studentMapper = sqlSession.getMapper(StudentMapper.class);

        // 封装对象
        Student student = new Student();
        student.setNameCh(nameCh);
        student.setSex(sex);
        student.setAge(age);
        student.setNameEn(nameEn);

        // 4.执行
        studentMapper.add(student);
        // 提交事务
        sqlSession.commit();
        //获取主键
        System.out.println(student.getId());

        // 5.释放资源
        sqlSession.close();
    }
}

更新

修改全部字段

StudentMapper.xml

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
  PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
  "https://mybatis.org/dtd/mybatis-3-mapper.dtd">

<mapper namespace="mapper.StudentMapper">

  <!-- 更新语句 -->
  <update id = "update">
    update student set
      name_ch = #{nameCh},
      name_en = #{nameEn},
      sex = #{sex},
      age = #{age}
    where id = #{id};
  </update>

</mapper>

StudentMapper.java

package mapper;

import pojo.Student;

public interface StudentMapper {
    // 修改更新
    int update(Student student);
}

MyBasitDemo.java

import java.io.IOException;
import java.io.InputStream;

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 mapper.StudentMapper;
import pojo.Student;

// mapper代理开发

public class MyBasitDemo {
    public static void main(String[] args) throws IOException {
        update(10,"大红","男",25,"dahong");
    }
    
    public static void update(int id,String nameCh,String sex,int age,String nameEn) throws IOException {
        // 1.加载mybatis的核心配置文件,获取SqlSessionFactory
        String resource = "config\\anyshare\\mybatis-config.xml";
        InputStream inputStream = Resources.getResourceAsStream(resource);
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);

        // 2.获取SqlSession对象,用它来执行sql
        SqlSession sqlSession = sqlSessionFactory.openSession();

        // 3.获取StudentMapper接口的代理对象
        StudentMapper studentMapper = sqlSession.getMapper(StudentMapper.class);

        // 封装对象
        Student student = new Student();
        student.setId(id);
        student.setNameCh(nameCh);
        student.setSex(sex);
        student.setAge(age);
        student.setNameEn(nameEn);

        // 4.执行
        // 获取影响行数看是否成功更新
        int count = studentMapper.update(student);
        System.out.println(count);
        // 提交事务
        sqlSession.commit();

        // 5.释放资源
        sqlSession.close();
    }
}

修改动态字段

当上面的修改全部字段中的传入参数存在null时,SQL语句将会报错,因此我们需要做到:当传入的某个参数为null时,需要在SQL语句中将其忽视。这就要在xml中使用set标签来代替set。

StudentMapper.xml

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
  PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
  "https://mybatis.org/dtd/mybatis-3-mapper.dtd">

<mapper namespace="mapper.StudentMapper">
  <!-- 动态条件更新 -->
  <update id = "update">
    update student
    <set>
      <if test = "nameCh != null and nameCh != ''">
        name_ch = #{nameCh},
      </if>
      <if test = "nameEn != null and nameEn != ''">
        name_en = #{nameEn},
      </if>
      <if test = "sex != null and sex != ''">
        sex = #{sex},
      </if>
      <if test = "age != null">
        age = #{age}
      </if>
    </set>
    where id = #{id}
  </update>

</mapper>

StudentMapper.java接口声明 与MyBasitDemo.java方法实现无需改变

删除

根据指定值删除

StudentMapper.xml

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
  PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
  "https://mybatis.org/dtd/mybatis-3-mapper.dtd">

<mapper namespace="mapper.StudentMapper">
  <!-- 删除 -->
  <delete id = "deleteById">
    delete from student where id = #{id};
  </delete>

</mapper>

StudentMapper.java

package mapper;

import org.apache.ibatis.annotations.Param;

import pojo.Student;

public interface StudentMapper {
    // 根据id删除
    int deleteById(int id);
}

MyBasitDemo.java

import java.io.IOException;
import java.io.InputStream;

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 mapper.StudentMapper;
import pojo.Student;

// mapper代理开发

public class MyBasitDemo2 {
    public static void main(String[] args) throws IOException {
        deleteById(1);
    }

    public static void deleteById(int id) throws IOException {
        // 1.加载mybatis的核心配置文件,获取SqlSessionFactory
        String resource = "config\\anyshare\\mybatis-config.xml";
        InputStream inputStream = Resources.getResourceAsStream(resource);
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);

        // 2.获取SqlSession对象,用它来执行sql
        SqlSession sqlSession = sqlSessionFactory.openSession();

        // 3.获取StudentMapper接口的代理对象
        StudentMapper studentMapper = sqlSession.getMapper(StudentMapper.class);

        // 4.执行
        // 获取影响行数看是否成功删除
        int count = studentMapper.deleteById(id);
        System.out.println(count);
        // 提交事务
        sqlSession.commit();

        // 5.释放资源
        sqlSession.close();
    }
}

动态批量删除

相当于一次性执行多次上面的根据指定值删除

StudentMapper.xml

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
  PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
  "https://mybatis.org/dtd/mybatis-3-mapper.dtd">

<mapper namespace="mapper.StudentMapper">
  <!-- 动态批量删除 -->
  <!--
    mybatis 会将数组参数封装为一个Map集合,
      * 默认key值为:array => 数组,即写为:
      <foreach collection = "array" item = "id" separator=",">
      * 可以使用@Param注解改变map集合的默认key的名称,即现在下面用的
  -->
  <delete id = "deleteByIds">
    delete from student where id in (
      <foreach collection = "ids" item = "id" separator=",">
        #{id}
      </foreach>
    );
  </delete>

</mapper>

StudentMapper.java

package mapper;

import org.apache.ibatis.annotations.Param;

import pojo.Student;

public interface StudentMapper {
    // 批量删除
    int deleteByIds(@Param("ids") int[] ids);
}

MyBasitDemo.java

import java.io.IOException;
import java.io.InputStream;

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 mapper.StudentMapper;
import pojo.Student;

// mapper代理开发

public class MyBasitDemo2 {
    public static void main(String[] args) throws IOException {
        deleteByIds(new int[]{1,2});
    }

    public static void deleteByIds(int[] ids) throws IOException {
        // 1.加载mybatis的核心配置文件,获取SqlSessionFactory
        String resource = "config\\anyshare\\mybatis-config.xml";
        InputStream inputStream = Resources.getResourceAsStream(resource);
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);

        // 2.获取SqlSession对象,用它来执行sql
        SqlSession sqlSession = sqlSessionFactory.openSession();

        // 3.获取StudentMapper接口的代理对象
        StudentMapper studentMapper = sqlSession.getMapper(StudentMapper.class);

        // 4.执行
        // 获取影响行数看是否成功删除
        int count = studentMapper.deleteByIds(ids);
        System.out.println(count);
        // 提交事务
        sqlSession.commit();

        // 5.释放资源
        sqlSession.close();
    }
}
posted @   Mercurows  阅读(16)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 单元测试从入门到精通
· 上周热点回顾(3.3-3.9)
· Vue3状态管理终极指南:Pinia保姆级教程
点击右上角即可分享
微信分享提示