三、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();
}
}
运行结果
注解实现新增操作
创建新增方法 在接口内新增 新增方法
// 新增操作
@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();
}
运行结果
注解实现修改操作
创建修改方法
// 修改操作
@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();
}
运行结果
注解实现删除操作
创建删除方法
// 删除操作
@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 的学生信息
1.3 注解开发总结
注解可以简化开发操作,省略映射配置文件的编写。
- 常用注解 @Select(“查询的 SQL 语句”):执行查询操作注解 @Insert(“查询的 SQL 语句”):执行新增操作注解 @Update(“查询的 SQL 语句”):执行修改操作注解 @Delete(“查询的 SQL 语句”):执行删除操作注解
- 配置映射关系
<mappers> <package name="接口所在包"/> </mappers>
二.MyBatis注解开发的多表操作
2.1 MyBatis的注解实现复杂映射开发
实现复杂关系映射之前我们可以在映射文件中通过配置
编辑切换为居中
添加图片注释,不超过 140 字(可选)
2.2 一对一查询
2.2.1 一对一查询的模型
一对一查询的需求:查询一个用户信息,与此同时查询出该用户对应的身份证信息
数据库 表准备
创建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;
}
}
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
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();
}
配置核心配置文件
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 一对多查询的模型
一对多查询的需求:查询一个课程,与此同时查询出该该课程对应的学生信息
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 多对多查询的模型
多对多查询的需求:查询学生以及所对应的课程信息
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 语句
手动编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;
}
}
运行结果一样 但是用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();
}
}
}
}
}