三、Mybatis(高级)

一.Mybatis注解开发单表操作

1.1 MyBatis的常用注解

这几年来注解开发越来越流行,Mybatis也可以使用注解开发方式,这样我们就可以减少编写Mapper

映射文件了。我们先围绕一些基本的CRUD来学习,再学习复杂映射多表操作。

@Insert(“新增的SQL语句”)∶执行新增操作注解

@Delete(“删除的SQL语句”)︰执行删除操作注解

@Update(“修改的SQL语句”)∶执行修改操作注解

@Select(“查询的SQL语句”)∶执行查询操作注解

@Result:实现结果集封装

@Results:可以与@Result 一起使用,封装多个结果集

@One:实现一对一结果集封装

@Many:实现一对多结果集封装

1.2 MyBatis的增删改查

注解开发实现查询操作

数据 库准备

CREATE DATABASE db25;
USE db25;

CREATE TABLE student(
	id INT PRIMARY KEY AUTO_INCREMENT,
	NAME VARCHAR(30),
	age INT
);

INSERT INTO student VALUES (NULL,'张三',17);
INSERT INTO student VALUES (NULL,'李四',18);
INSERT INTO student VALUES (NULL,'王五',19);
INSERT INTO student VALUES (NULL,'赵六',20);

maven引入坐标

<!--导包 以坐标的方式 -->
    <!--  dependencies 依赖包 -->
    <dependencies>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
            <scope>compile</scope>
        </dependency>
        <!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java -->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.37</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/org.mybatis/mybatis -->
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis</artifactId>
            <version>3.5.3</version>
        </dependency>
        <dependency>
            <groupId>org.junit.jupiter</groupId>
            <artifactId>junit-jupiter</artifactId>
            <version>RELEASE</version>
            <scope>compile</scope>
        </dependency>
        <!-- https://mvnrepository.com/artifact/log4j/log4j -->
        <dependency>
            <groupId>log4j</groupId>
            <artifactId>log4j</artifactId>
            <version>1.2.17</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/com.github.pagehelper/pagehelper -->
        <dependency>
            <groupId>com.github.pagehelper</groupId>
            <artifactId>pagehelper</artifactId>
            <version>5.1.10</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/com.github.jsqlparser/jsqlparser -->
        <dependency>
            <groupId>com.github.jsqlparser</groupId>
            <artifactId>jsqlparser</artifactId>
            <version>3.1</version>
        </dependency>
    </dependencies>

数据库连接配置文件

driver=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/db25
username=root
password=123456

日志配置文件

 # Global logging configuration
# ERROR 错误信息
# WARN 警告信息
# INFO 普通信息
# DEBUG
# stdout 信息输出到控制台
log4j.rootLogger=DEBUG, stdout
# Console output...
# 输出格式
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%5p [%t] - %m%n

创建接口和查询方法

package com.itss.mapper;


import com.itss.bean.Student;
import org.apache.ibatis.annotations.Select;

import java.util.List;

/**
 * @author IT苏苏
 * @className StudentMapper.java
 * @Form no
 * @Description ToDo
 * @createTime 2022 年 11 月 26 日 09  9:14:38
 **/
public interface StudentMapper {
    //    查询全部
    @Select("SELECT * FROM student")//通过注解来查询  省略了映射配置文件
    public abstract List<Student> selectAll();
}

在核心配置文件中配置映射关系

<?xml version="1.0" encoding="UTF-8" ?>
<!--MyBatis的DTD约束-->
<!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd">
<!--configuration 核心根标签-->
<configuration>
    <!--    <properties> :引入数据库连接配置文件标签。
        属性  resource:数据库连接配置文件路径-->
    <properties resource="jdbc.properties"/>

    <!--配置 log4j -->
    <settings>
        <setting name="logImpl" value="log4j"/>
    </settings>

    <!--<typeAliases>:为全类名起别名的父标签。-->
    <typeAliases>
        <!--通用方式  在bean包下所有的类一起 起别名
        别名就是类名 例如 bean包下的Card类 别名就为 card -->
        <package name="com.itss.bean"/>
    </typeAliases>

    <!--集成分页插件助手
    plugin指定集成第三方插件
    interceptor指定插件的全类名-->
    <plugins>
        <plugin interceptor="com.github.pagehelper.PageInterceptor"></plugin>
    </plugins>

    <!--environments配置数据库环境,环境可以有多个。default属性指定使用的是哪个-->
    <environments default="mysql">
        <!--environment配置数据库环境  id属性唯一标识-->
        <environment id="mysql"><!-- environments 要与 environment 一样  表示要使用哪一个 environment  就将environments 更改成一样-->
            <!-- transactionManager事务管理。  type属性,采用JDBC默认的事务-->
            <transactionManager type="JDBC"></transactionManager>
            <!-- dataSource数据源信息   type属性 连接池-->
            <dataSource type="POOLED">
                <!-- property获取数据库连接的配置信息  数据库连接配置文件引入后 -->
                <property name="driver" value="${driver}"/>
                <property name="url" value="${url}"/>
                <property name="username" value="${username}"/>
                <property name="password" value="${password}"/>

            </dataSource>
        </environment>
    </environments>
  <!--配置映射关系-->
    <mappers>
        <!--在核心配置文件中指定接口的包-->
        <!--指定接口包的路径-->
        <package name="com.itss.mapper"/>
    </mappers>
</configuration>

编写测试类

package com.itss.test;


import com.itss.bean.Student;
import com.itss.mapper.StudentMapper;
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.InputStream;
import java.util.List;

/**
 * @author IT苏苏
 * @className Test01.java
 * @Form no
 * @Description ToDo
 * @createTime 2022 年 11 月 26 日 09  9:22:09
 **/
/*
* //1.加载核心配置文件
//2.获取Sq1Session工厂对象
//3.通过工厂对象获取Sq1Session对象
//4.获取StudentMapper接口的实现类对象
//5.调用实现类对象中的方法,接收结果
//6.处理结果
//7.释放资源*/
public class Test01 {
    @Test
    public void selectAll() throws Exception {
//1.加载核心配置文件
        InputStream is = Resources.getResourceAsStream("MyBatisConfig.xml");
//2.获取Sq1Session工厂对象
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(is);
//3.通过工厂对象获取Sq1Session对象
        SqlSession sqlSession = sqlSessionFactory.openSession(true);
//4.获取StudentMapper接口的实现类对象
        StudentMapper mapper = sqlSession.getMapper(StudentMapper.class);
//5.调用实现类对象中的方法,接收结果
        List<Student> list = mapper.selectAll();
//6.处理结果
        for (Student student : list
        ) {
            System.out.println(student);
        }
//7.释放资源
        sqlSession.close();
        is.close();
    }

}

运行结果

img

注解实现新增操作

创建新增方法 在接口内新增 新增方法

    //    新增操作
    @Insert("INSERT INTO student VALUES (#{id},#{name},#{age})")
    public abstract Integer insert(Student student);

编写测试类

    @Test
    public void insert() throws Exception {
//1.加载核心配置文件
        InputStream is = Resources.getResourceAsStream("MyBatisConfig.xml");
//2.获取Sq1Session工厂对象
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(is);
//3.通过工厂对象获取Sq1Session对象
        SqlSession sqlSession = sqlSessionFactory.openSession(true);
//4.获取StudentMapper接口的实现类对象
        StudentMapper mapper = sqlSession.getMapper(StudentMapper.class);
//5.调用实现类对象中的方法,接收结果
        Student stu = new Student(5, "新增的学生姓名", 18);
        Integer result = mapper.insert(stu);
//6.处理结果
        System.out.println("影响行数:" + result);
//7.释放资源
        sqlSession.close();
        is.close();
    }

运行结果

img

注解实现修改操作

创建修改方法

    //    修改操作
    @Update("UPDATE student SET name=#{name},age=#{age} WHERE id=#{id}")
    public abstract Integer update(Student student);

编写测试类

    @Test
    public void update() throws Exception {
//1.加载核心配置文件
        InputStream is = Resources.getResourceAsStream("MyBatisConfig.xml");
//2.获取Sq1Session工厂对象
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(is);
//3.通过工厂对象获取Sq1Session对象
        SqlSession sqlSession = sqlSessionFactory.openSession(true);
//4.获取StudentMapper接口的实现类对象
        StudentMapper mapper = sqlSession.getMapper(StudentMapper.class);
//5.调用实现类对象中的方法,接收结果
        Student stu = new Student(5, "新增的学生姓名", 99);
        Integer result = mapper.update(stu);
//6.处理结果
        System.out.println("影响行数:" + result);
//7.释放资源
        sqlSession.close();
        is.close();
    }

运行结果

img

注解实现删除操作

创建删除方法

    //    删除操作
    @Delete("DELETE FROM student WHERE id=#{id}")
    public abstract Integer delete(Integer id);

编写测试类

    @Test
    public void delete() throws Exception {
//1.加载核心配置文件
        InputStream is = Resources.getResourceAsStream("MyBatisConfig.xml");
//2.获取Sq1Session工厂对象
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(is);
//3.通过工厂对象获取Sq1Session对象
        SqlSession sqlSession = sqlSessionFactory.openSession(true);
//4.获取StudentMapper接口的实现类对象
        StudentMapper mapper = sqlSession.getMapper(StudentMapper.class);
//5.调用实现类对象中的方法,接收结果
        Integer result = mapper.delete(6);
//6.处理结果
        System.out.println("影响行数:" + result);
//7.释放资源
        sqlSession.close();
        is.close();
    }

运行结果 删除 id为6 的学生信息

img

1.3 注解开发总结

注解可以简化开发操作,省略映射配置文件的编写。

  • 常用注解 @Select(“查询的 SQL 语句”):执行查询操作注解 @Insert(“查询的 SQL 语句”):执行新增操作注解 @Update(“查询的 SQL 语句”):执行修改操作注解 @Delete(“查询的 SQL 语句”):执行删除操作注解
  • 配置映射关系
<mappers> <package name="接口所在包"/> </mappers>   

二.MyBatis注解开发的多表操作

2.1 MyBatis的注解实现复杂映射开发

实现复杂关系映射之前我们可以在映射文件中通过配置来实现,使用注解开发后,我们可以使用@Results注解,@Result注解,@One注解,@Many注解组合完成复杂关系的配置

img

编辑切换为居中

添加图片注释,不超过 140 字(可选)

img

2.2 一对一查询

2.2.1 一对一查询的模型

一对一查询的需求:查询一个用户信息,与此同时查询出该用户对应的身份证信息

img

数据库 表准备

img

创建Card类

package com.itss.bean;

/**
 * @author IT苏苏
 * @className Card.java
 * @Form no
 * @Description ToDo
 * @createTime 2022 年 11 月 24 日 20  20:22:58
 **/
public class Card {
    private Integer id;//主键id
    private String number;//身份证号

    private Person p;//所属人的对象

    public Card() {
    }

    public Card(Integer id, String number, Person p) {
        this.id = id;
        this.number = number;
        this.p = p;
    }

    @Override
    public String toString() {
        return "Card{" +
                "id=" + id +
                ", number='" + number + '\'' +
                ", p=" + p +
                '}';
    }

    public Integer getId() {
        return id;
    }

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

    public String getNumber() {
        return number;
    }

    public void setNumber(String number) {
        this.number = number;
    }

    public Person getP() {
        return p;
    }

    public void setP(Person p) {
        this.p = p;
    }
}

创建Person类

package com.itss.bean;

/**
 * @author IT苏苏
 * @className Person.java
 * @Form no
 * @Description ToDo
 * @createTime 2022 年 11 月 24 日 20  20:20:06
 **/
public class Person {
    private Integer id;//主键id
    private String name;//人的姓名
    private Integer age;//人的年龄

    public Person() {
    }

    public Person(Integer id, String name, Integer age) {
        this.id = id;
        this.name = name;
        this.age = age;
    }

    @Override
    public String toString() {
        return "Person{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", age=" + 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 Integer getAge() {
        return age;
    }

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

img

2.2.2 一对一查询的语句

对应的sql语句:

SELECT * FROM card;

SELECT * FROM person WHERE id=#{id};

2.2.3 创建PersonMapper接口

package com.itss.one_to_one;

import com.itss.bean.Person;
import org.apache.ibatis.annotations.Select;

/**
 * @author IT苏苏
 * @className PersonMapper.java
 * @Form no
 * @Description ToDo
 * @createTime 2022 年 11 月 26 日 15  15:11:01
 **/
public interface PersonMapper {
    //    根据id查询
    @Select("SELECT * FROM person WHERE id=#{id}")
    public abstract Person selectById(Integer id);

}

2.2.4 创建CardMapper接口 使用注解配置Mapper

img

package com.itss.one_to_one;

import com.itss.bean.Card;
import com.itss.bean.Person;
import org.apache.ibatis.annotations.One;
import org.apache.ibatis.annotations.Result;
import org.apache.ibatis.annotations.Results;
import org.apache.ibatis.annotations.Select;

import java.util.List;

/**
 * @author IT苏苏
 * @className CardMapper.java
 * @Form no
 * @Description ToDo
 * @createTime 2022 年 11 月 26 日 15  15:10:41
 **/
public interface CardMapper {
    //    查询全部
    @Select("SELECT * FROM card")
    @Results({
            @Result(column ="id", property = "id"),
            @Result(column = "number",property = "number"),
            @Result(
                    property = "p",//被包含对象的变量
                    javaType = Person.class,//被包含对象的实际数据类型
                    column = "pid",//根据查询出的card表中低端pid字段来查询person表
                    /*
                    * One @One 一对一固定写法
                    * select属性:指定调用哪个接口中的哪个方法*/
                    one = @One(select = "com.itss.one_to_one.PersonMapper.selectById")
            )
    })
    public abstract List<Card> selectAll();
}

配置核心配置文件

img

2.2.5 测试类

package com.itss.one_to_one;

import com.itss.bean.Card;
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.InputStream;
import java.util.List;

/**
 * @author IT苏苏
 * @className Test01.java
 * @Form no
 * @Description ToDo
 * @createTime 2022 年 11 月 26 日 15  15:15:09
 **/
public class Test01 {
    @Test
    public void selectAll() throws Exception {
//1.加载核心配置文件
        InputStream is = Resources.getResourceAsStream("MyBatisConfig.xml");
//2.获取Sq1Session工厂对象
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(is);
//3.通过工厂对象获取Sq1Session对象
        SqlSession sqlSession = sqlSessionFactory.openSession(true);
//4.获取StudentMapper接口的实现类对象
        CardMapper mapper = sqlSession.getMapper(CardMapper.class);
//5.调用实现类对象中的方法,接收结果
        List<Card> list = mapper.selectAll();
//6.处理结果
        for (Card card : list
        ) {
            System.out.println(card);
        }
//7.释放资源
        sqlSession.close();
        is.close();
    }
}

2.2.6 一对一配置总结

@Results:封装映射关系的父注解。
	Result[] value():定义了 Result 数组
@Result:封装映射关系的子注解。
	column 属性:查询出的表中字段名称
	property 属性:实体对象中的属性名称
	javaType 属性:被包含对象的数据类型
	one 属性:一对一查询固定属性
 @One:一对一查询的注解。
	select 属性:指定调用某个接口中的方法

2.3 一对多查询

2.3.1 一对多查询的模型

一对多查询的需求:查询一个课程,与此同时查询出该该课程对应的学生信息

img

2.3.3 创建StudentMapper接口

public interface StudentMapper {
    //根据cid查询student表
    @Select("SELECT * FROM student WHERE cid=#{cid}")
    public abstract List<Student> selectByCid(Integer cid);
}

2.3.4 使用注解配置Mapper

public interface ClassesMapper {
    //查询全部
    @Select("SELECT * FROM classes")
    @Results({
            @Result(column = "id",property = "id"),
            @Result(column = "name",property = "name"),
            @Result(
                    property = "students",  // 被包含对象的变量名
                    javaType = List.class,  // 被包含对象的实际数据类型
                    column = "id",          // 根据查询出的classes表的id字段来查询student表
                    /*
                        many、@Many 一对多查询的固定写法
                        select属性:指定调用哪个接口中的哪个查询方法
                     */java
                    many = @Many(select = "com.itss.one_to_many.StudentMapper.selectByCid")
            )
    })
    public abstract List<Classes> selectAll();
}

2.3.5 测试类

public class Test01 {
    @Test
    public void selectAll() throws Exception{
        //1.加载核心配置文件
        InputStream is = Resources.getResourceAsStream("MyBatisConfig.xml");

        //2.获取SqlSession工厂对象
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(is);

        //3.通过工厂对象获取SqlSession对象
        SqlSession sqlSession = sqlSessionFactory.openSession(true);

        //4.获取ClassesMapper接口的实现类对象
        ClassesMapper mapper = sqlSession.getMapper(ClassesMapper.class);

        //5.调用实现类对象中的方法,接收结果
        List<Classes> list = mapper.selectAll();

        //6.处理结果
        for (Classes cls : list) {
            System.out.println(cls.getId() + "," + cls.getName());
            List<Student> students = cls.getStudents();
            for (Student student : students) {
                System.out.println("\t" + student);
            }
        }

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

}

2.3.6 一对多配置总结

@Results:封装映射关系的父注解。
	Result[] value():定义了 Result 数组
@Result:封装映射关系的子注解。
	column 属性:查询出的表中字段名称
	property 属性:实体对象中的属性名称
	javaType 属性:被包含对象的数据类型
	many 属性:一对多查询固定属性
@Many:一对多查询的注解。
	select 属性:指定调用某个接口中的方法

2.4 多对多查询

2.4.1 多对多查询的模型

多对多查询的需求:查询学生以及所对应的课程信息

img

2.4.2 多对多查询的语句

对应的sql语句:

SELECT DISTINCT s.id,s.name,s.age FROM student s,stu_cr sc WHERE sc.sid=s.id
SELECT c.id,c.name FROM stu_cr sc,course c WHERE sc.cid=c.id AND sc.sid=#{id}

2.4.3 添加CourseMapper 接口方法

public interface CourseMapper {
    //根据学生id查询所选课程
    @Select("SELECT c.id,c.name FROM stu_cr sc,course c WHERE sc.cid=c.id AND sc.sid=#{id}")
    public abstract List<Course> selectBySid(Integer id);
}

2.4.4 使用注解配置Mapper

public interface StudentMapper {
    //查询全部
    @Select("SELECT DISTINCT s.id,s.name,s.age FROM student s,stu_cr sc WHERE sc.sid=s.id")
    @Results({
            @Result(column = "id",property = "id"),
            @Result(column = "name",property = "name"),
            @Result(column = "age",property = "age"),
            @Result(
                    property = "courses",   // 被包含对象的变量名
                    javaType = List.class,  // 被包含对象的实际数据类型
                    column = "id",          // 根据查询出student表的id来作为关联条件,去查询中间表和课程表
                    /*
                        many、@Many 一对多查询的固定写法
                        select属性:指定调用哪个接口中的哪个查询方法
                     */
                    many = @Many(select = "com.itss.many_to_many.CourseMapper.selectBySid")
            )
    })
    public abstract List<Student> selectAll();
}

2.4.5 测试类

public class Test01 {
    @Test
    public void selectAll() throws Exception{
        //1.加载核心配置文件
        InputStream is = Resources.getResourceAsStream("MyBatisConfig.xml");

        //2.获取SqlSession工厂对象
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(is);

        //3.通过工厂对象获取SqlSession对象
        SqlSession sqlSession = sqlSessionFactory.openSession(true);

        //4.获取StudentMapper接口的实现类对象
        StudentMapper mapper = sqlSession.getMapper(StudentMapper.class);

        //5.调用实现类对象中的方法,接收结果
        List<Student> list = mapper.selectAll();

        //6.处理结果
        for (Student student : list) {
            System.out.println(student.getId() + "," + student.getName() + "," + student.getAge());
            List<Course> courses = student.getCourses();
            for (Course cours : courses) {
                System.out.println("\t" + cours);
            }
        }

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

}

2.4.6 多对多配置总结

@Results:封装映射关系的父注解。
	Result[] value():定义了 Result 数组
@Result:封装映射关系的子注解。
	column 属性:查询出的表中字段名称
	property 属性:实体对象中的属性名称
	javaType 属性:被包含对象的数据类型
	many 属性:一对多查询固定属性
@Many:一对多查询的注解。
	select 属性:指定调用某个接口中的方法

三.构建sql

3.1 SQL 构建对象介绍

  • 我们之前通过注解开发时,相关 SQL 语句都是自己直接拼写的。一些关键字写起来比较麻烦、而且容易出错。
  • MyBatis 给我们提供了 org.apache.ibatis.jdbc.SQL 功能类,专门用于构建 SQL 语句

img

手动编sql与利用sql功能类编写sql语句对比

package com.itss.sql;

import org.apache.ibatis.jdbc.SQL;

public class sqlTest {
    public static void main(String[] args) {
        String sql = getSql();
        System.out.println("手动编写的sql:" + sql);
        System.out.println("----------------------");
        String toSql = getToSql();
        System.out.println("利用sql功能类编写的sql:" + toSql);
    }

    private static String getSql() {
        String sql = "SELECT * FROM student";
        return sql;
    }

    private static String getToSql() {
        String sql = new SQL() {
            {
                SELECT("*");
                FROM("student");
            }
        }.toString();
        return sql;
    }
}

img

运行结果一样 但是用sql功能类编写可以减小代码的出错率

3.2 查询功能的实现

  • 定义功能类并提供获取查询的 SQL 语句的方法。
public class ReturnSql {
    //    定义方法,返回查询的sql语句
    public String getSelectAll() {
        return new SQL() {
            {
                SELECT("*");
                FROM("student");
            }
        }.toString();
    }
}
  • @SelectProvider:生成查询用的 SQL 语句注解。 type 属性:生成 SQL 语句功能类对象 method 属性:指定调用方法
    //    查询全部
//    @Select("SELECT * FROM student")//通过注解来查询  省略了映射配置文件
//    type:功能类对象  method:具体调用的方法
    @SelectProvider(type = ReturnSql.class, method = "getSelectAll")
    public abstract List<Student> selectAll();

测试方法

    @Test
    public void selectAll() throws Exception {
//1.加载核心配置文件
        InputStream is = Resources.getResourceAsStream("MyBatisConfig.xml");
//2.获取Sq1Session工厂对象
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(is);
//3.通过工厂对象获取Sq1Session对象
        SqlSession sqlSession = sqlSessionFactory.openSession(true);
//4.获取StudentMapper接口的实现类对象
        StudentMapper mapper = sqlSession.getMapper(StudentMapper.class);
//5.调用实现类对象中的方法,接收结果
        List<Student> list = mapper.selectAll();
//6.处理结果
        for (Student student : list
        ) {
            System.out.println(student);
        }
//7.释放资源
        sqlSession.close();
        is.close();
    }

3.3 新增功能的实现

  • 定义功能类并提供获取新增的 SQL 语句的方法。
    //    定义方法,返回新增的sql语句
    public String getInsert(Student student) {
        return new SQL() {{
            INSERT_INTO("student");
            INTO_VALUES("#{id},#{name},#{age}");
        }}.toString();
    }
  • @InsertProvider:生成新增用的 SQL 语句注解。 type 属性:生成 SQL 语句功能类对象 method 属性:指定调用方法
    //    新增操作
//    @Insert("INSERT INTO student VALUES (#{id},#{name},#{age})")
    @InsertProvider(type = ReturnSql.class, method = "getInsert")
    public abstract Integer insert(Student student);

测试方法

    @Test
    public void insert() throws Exception {
//1.加载核心配置文件
        InputStream is = Resources.getResourceAsStream("MyBatisConfig.xml");
//2.获取Sq1Session工厂对象
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(is);
//3.通过工厂对象获取Sq1Session对象
        SqlSession sqlSession = sqlSessionFactory.openSession(true);
//4.获取StudentMapper接口的实现类对象
        StudentMapper mapper = sqlSession.getMapper(StudentMapper.class);
//5.调用实现类对象中的方法,接收结果
        Student stu = new Student(5, "新增的学生姓名", 18);
        Integer result = mapper.insert(stu);
//6.处理结果
        System.out.println("影响行数:" + result);
//7.释放资源
        sqlSession.close();
        is.close();
    }

3.4 修改功能的实现

  • 定义功能类并提供获取修改的 SQL 语句的方法。
    //    定义方法,返回修改的sql语句
    public String getUpdate(Student student) {
        return new SQL() {
            {
                UPDATE("student");
                SET("name=#{name}","age=#{age}");
                WHERE("id=#{id}");
            }
        }.toString();
    }
  • @UpdateProvider:生成修改用的 SQL 语句注解。 type 属性:生成 SQL 语句功能类对象 method 属性:指定调用方法
    //    修改操作
//    @Update("UPDATE student SET name=#{name},age=#{age} WHERE id=#{id}")
    @UpdateProvider(type = ReturnSql.class, method = "getUpdate")
    public abstract Integer update(Student student);

测试方法

    @Test
    public void update() throws Exception {
//1.加载核心配置文件
        InputStream is = Resources.getResourceAsStream("MyBatisConfig.xml");
//2.获取Sq1Session工厂对象
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(is);
//3.通过工厂对象获取Sq1Session对象
        SqlSession sqlSession = sqlSessionFactory.openSession(true);
//4.获取StudentMapper接口的实现类对象
        StudentMapper mapper = sqlSession.getMapper(StudentMapper.class);
//5.调用实现类对象中的方法,接收结果
        Student stu = new Student(5, "新增的学生姓名", 99);
        Integer result = mapper.update(stu);
//6.处理结果
        System.out.println("影响行数:" + result);
//7.释放资源
        sqlSession.close();
        is.close();
    }

3.5 删除功能的实现

  • 定义功能类并提供获取删除的 SQL 语句的方法。
    //    定义方法,返回删除的sql语句
    public String getDelete(Integer id) {
        return new SQL() {
            {
                DELETE_FROM("student");
                WHERE("id=#{id}");
            }
        }.toString();
    }
  • @DeleteProvider:生成删除用的 SQL 语句注解。 type 属性:生成 SQL 语句功能类对象 method 属性:指定调用方法
    //    删除操作
//    @Delete("DELETE FROM student WHERE id=#{id}")
    @DeleteProvider(type = ReturnSql.class, method = "getDelete")
    public abstract Integer delete(Integer id);

测试方法

    @Test
    public void delete() throws Exception {
//1.加载核心配置文件
        InputStream is = Resources.getResourceAsStream("MyBatisConfig.xml");
//2.获取Sq1Session工厂对象
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(is);
//3.通过工厂对象获取Sq1Session对象
        SqlSession sqlSession = sqlSessionFactory.openSession(true);
//4.获取StudentMapper接口的实现类对象
        StudentMapper mapper = sqlSession.getMapper(StudentMapper.class);
//5.调用实现类对象中的方法,接收结果
        Integer result = mapper.delete(5);
//6.处理结果
        System.out.println("影响行数:" + result);
//7.释放资源
        sqlSession.close();
        is.close();
    }

构建SQL语句小结

org.apache.ibatis.jdbc.SQL:构建SQL语句的功能类。通过一些方法来代替SQL语句的关键字。

SELECT()

FROM()

WHERE()

INSERT_INT()

VALUES()

UPDATE()

DELETE_FROM()

@SelectProvider :生成查询用的SQL语句注解。

@lnsertProvider:生成新增用的SQL语句注解。

@UpdateProvider:生成修改用的SQL语句注解。

@DeleteProvider :生成删除用的SQL语句注解。

type属性︰生成SQL语句功能类对象

method属性:指定调用方法

四.综合案例

4.1 系统介绍

​ 我们之前在做学生管理系统时,使用的是原始JDBC操作数据库的,操作非常麻烦,现在我们使用MyBatis操作数据库,简化Dao的开发。

4.2 环境搭建(略)

数据库

-- 创建db26数据库
CREATE DATABASE db26;

-- 使用db26数据库
USE db26;

-- 创建用户表
CREATE TABLE USER(
	uid VARCHAR(50) PRIMARY KEY,	-- 用户id
	ucode VARCHAR(50),		-- 用户标识
	loginname VARCHAR(100),		-- 登录用户名
	PASSWORD VARCHAR(100),		-- 登录密码
	username VARCHAR(100),		-- 用户名
	gender VARCHAR(10),		-- 用户性别
	birthday DATE,			-- 出生日期
	dutydate DATE                   -- 入职日期
);

-- 添加一条测试数据
INSERT INTO USER VALUES ('11111111', 'zhangsan001', 'zhangsan', '1234', '张三', '男', '2008-10-28', '2018-10-28');


-- 创建student表
CREATE TABLE student(
	sid INT PRIMARY KEY AUTO_INCREMENT,	-- 学生id
	NAME VARCHAR(20),			-- 学生姓名
	age INT,				-- 学生年龄
	birthday DATE				-- 学生生日
);

-- 添加数据
INSERT INTO student VALUES (NULL,'张三',23,'1999-09-23'),(NULL,'李四',24,'1998-08-10'),
(NULL,'王五',25,'1996-06-06'),(NULL,'赵六',26,'1994-10-20');

4.3 代码改造

  • 步骤一:新增MyBatis配置文件 MyBatisConfig.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!--MyBatis的DTD约束-->
<!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd">

<!--configuration 核心根标签-->
<configuration>

    <!--引入数据库连接的配置文件-->
    <properties resource="config.properties"/>

    <!--配置LOG4J-->
    <settings>
        <setting name="logImpl" value="log4j"/>
    </settings>

    <!--environments配置数据库环境,环境可以有多个。default属性指定使用的是哪个-->
    <environments default="mysql">
        <!--environment配置数据库环境  id属性唯一标识-->
        <environment id="mysql">
            <!-- transactionManager事务管理。  type属性,采用JDBC默认的事务-->
            <transactionManager type="JDBC"></transactionManager>
            <!-- dataSource数据源信息   type属性 连接池-->
            <dataSource type="POOLED">
                <!-- property获取数据库连接的配置信息 -->
                <property name="driver" value="${driver}" />
                <property name="url" value="${url}" />
                <property name="username" value="${username}" />
                <property name="password" value="${password}" />
            </dataSource>
        </environment>
    </environments>

    <!--配置映射关系-->
    <mappers>
        <package name="com.itss"/>
    </mappers>
</configuration>

步骤二: 删除StudentDaoImpl,修改StudentDao

package com.itheima.dao;

          import com.itheima.domain.Student;
          import org.apache.ibatis.annotations.Delete;
          import org.apache.ibatis.annotations.Insert;
          import org.apache.ibatis.annotations.Select;
          import org.apache.ibatis.annotations.Update;

          import java.util.ArrayList;

/*
    Dao层接口
 */
public interface StudentDao {
    //查询所有学生信息
    @Select("SELECT * FROM student")
    public abstract ArrayList<Student> findAll();

    //条件查询,根据id获取学生信息
    @Select("SELECT * FROM student WHERE sid=#{sid}")
    public abstract Student findById(Integer sid);

    //新增学生信息
    @Insert("INSERT INTO student VALUES (#{sid},#{name},#{age},#{birthday})")
    public abstract int insert(Student stu);

    //修改学生信息
    @Update("UPDATE student SET name=#{name},age=#{age},birthday=#{birthday} WHERE sid=#{sid}")
    public abstract int update(Student stu);

    //删除学生信息
    @Delete("DELETE FROM student WHERE sid=#{sid}")
    public abstract int delete(Integer sid);
}

步骤三:修改StudentServiceImpl

* 步骤三:修改`StudentServiceImpl`

  ~~~java
  package com.itheima.service.impl;
  
  import com.itheima.dao.StudentDao;
  import com.itheima.domain.Student;
  import com.itheima.service.StudentService;
  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;
  import java.util.ArrayList;
  import java.util.List;
  
  /**
   * 学生的业务层实现类
   */
  public class StudentServiceImpl implements StudentService {
  
      @Override
      public List<Student> findAll() {
          ArrayList<Student> list = null;
          SqlSession sqlSession = null;
          InputStream is = null;
          try{
              //1.加载核心配置文件
              is = Resources.getResourceAsStream("MyBatisConfig.xml");
  
              //2.获取SqlSession工厂对象
              SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(is);
  
              //3.通过工厂对象获取SqlSession对象
              sqlSession = sqlSessionFactory.openSession(true);
  
              //4.获取StudentDao接口的实现类对象
              StudentDao mapper = sqlSession.getMapper(StudentDao.class);
  
              //5.调用实现类对象的方法,接收结果
              list = mapper.findAll();
  
          } catch (Exception e) {
              e.printStackTrace();
          } finally {
              //6.释放资源
              if(sqlSession != null) {
                  sqlSession.close();
              }
              if(is != null) {
                  try {
                      is.close();
                  } catch (IOException e) {
                      e.printStackTrace();
                  }
              }
          }
  
          //7.返回结果
          return list;
      }
  
      @Override
      public Student findById(Integer sid) {
          Student stu = null;
          SqlSession sqlSession = null;
          InputStream is = null;
          try{
              //1.加载核心配置文件
              is = Resources.getResourceAsStream("MyBatisConfig.xml");
  
              //2.获取SqlSession工厂对象
              SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(is);
  
              //3.通过工厂对象获取SqlSession对象
              sqlSession = sqlSessionFactory.openSession(true);
  
              //4.获取StudentDao接口的实现类对象
              StudentDao mapper = sqlSession.getMapper(StudentDao.class);
  
              //5.调用实现类对象的方法,接收结果
              stu = mapper.findById(sid);
  
          } catch (Exception e) {
              e.printStackTrace();
          } finally {
              //6.释放资源
              if(sqlSession != null) {
                  sqlSession.close();
              }
              if(is != null) {
                  try {
                      is.close();
                  } catch (IOException e) {
                      e.printStackTrace();
                  }
              }
          }
  
          //7.返回结果
          return stu;
      }
  
      @Override
      public void save(Student student) {
          SqlSession sqlSession = null;
          InputStream is = null;
          try{
              //1.加载核心配置文件
              is = Resources.getResourceAsStream("MyBatisConfig.xml");
  
              //2.获取SqlSession工厂对象
              SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(is);
  
              //3.通过工厂对象获取SqlSession对象
              sqlSession = sqlSessionFactory.openSession(true);
  
              //4.获取StudentDao接口的实现类对象
              StudentDao mapper = sqlSession.getMapper(StudentDao.class);
  
              //5.调用实现类对象的方法,接收结果
              mapper.insert(student);
  
          } catch (Exception e) {
              e.printStackTrace();
          } finally {
              //6.释放资源
              if(sqlSession != null) {
                  sqlSession.close();
              }
              if(is != null) {
                  try {
                      is.close();
                  } catch (IOException e) {
                      e.printStackTrace();
                  }
              }
          }
      }
  
      @Override
      public void update(Student student) {
          SqlSession sqlSession = null;
          InputStream is = null;
          try{
              //1.加载核心配置文件
              is = Resources.getResourceAsStream("MyBatisConfig.xml");
  
              //2.获取SqlSession工厂对象
              SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(is);
  
              //3.通过工厂对象获取SqlSession对象
              sqlSession = sqlSessionFactory.openSession(true);
  
              //4.获取StudentDao接口的实现类对象
              StudentDao mapper = sqlSession.getMapper(StudentDao.class);
  
              //5.调用实现类对象的方法,接收结果
              mapper.update(student);
  
          } catch (Exception e) {
              e.printStackTrace();
          } finally {
              //6.释放资源
              if(sqlSession != null) {
                  sqlSession.close();
              }
              if(is != null) {
                  try {
                      is.close();
                  } catch (IOException e) {
                      e.printStackTrace();
                  }
              }
          }
      }
  
      @Override
      public void delete(Integer sid) {
          SqlSession sqlSession = null;
          InputStream is = null;
          try{
              //1.加载核心配置文件
              is = Resources.getResourceAsStream("MyBatisConfig.xml");
  
              //2.获取SqlSession工厂对象
              SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(is);
  
              //3.通过工厂对象获取SqlSession对象
              sqlSession = sqlSessionFactory.openSession(true);
  
              //4.获取StudentDao接口的实现类对象
              StudentDao mapper = sqlSession.getMapper(StudentDao.class);
  
              //5.调用实现类对象的方法,接收结果
              mapper.delete(sid);
  
          } catch (Exception e) {
              e.printStackTrace();
          } finally {
              //6.释放资源
              if(sqlSession != null) {
                  sqlSession.close();
              }
              if(is != null) {
                  try {
                      is.close();
                  } catch (IOException e) {
                      e.printStackTrace();
                  }
              }
          }
      }
  }
  
posted @ 2022-11-27 11:45  苏倩梁  阅读(15)  评论(0编辑  收藏  举报