目录
1、mybatis简介
MyBatis 是一款优秀的持久层框架,它支持自定义 SQL、存储过程以及高级映射。MyBatis 免除了几乎所有的 JDBC 代码以及设置参数和获取结果集的工作。MyBatis 可以通过简单的 XML 或注解来配置和映射原始类型、接口和 Java POJO(Plain Old Java Objects,普通老式 Java 对象)为数据库中的记录
mybatis官方文档:MyBatis中文网
mybatis特点
- 简单易学:MyBatis 本身比较小且简单。学习成本低,容易上手。
- 灵活:MyBatis 不会对应用程序或者数据库的现有设计强加任何影响。SQL 写在 XML 里,从 Java 代码中彻底分离,便于统一管理和优化,并可以很方便地使用任何数据库。
- 解除 SQL 与程序代码的耦合:通过提供映射器(Mapper)XML 文件或注解的方式将接口和 Java 的 POJOs 与 SQL 语句关联起来,实现了 SQL 与 Java 代码的解耦。
- 动态 SQL:MyBatis 提供了强大的动态 SQL 能力,可以通过简单的 XML 或注解来配置动态 SQL 语句,比如条件查询、循环插入等。
- 防止 SQL 注入:MyBatis 提供了参数绑定功能,能够自动将输入的参数转换为 SQL 语句中的占位符,有效防止 SQL 注入攻击。
- 结果映射:MyBatis 支持复杂的查询结果映射,包括一对一、一对多、多对多等复杂关系映射。
mybatis快速入门案例
第一步:新建数据库
CREATE DATABASE `mybatis-example`;
USE `mybatis-example`;
CREATE TABLE `t_emp`(
emp_id INT AUTO_INCREMENT,
emp_name CHAR(100),
emp_salary DOUBLE(10,5),
PRIMARY KEY(emp_id)
);
INSERT INTO `t_emp`(emp_name,emp_salary) VALUES("tom",200.33);
INSERT INTO `t_emp`(emp_name,emp_salary) VALUES("jerry",666.66);
INSERT INTO `t_emp`(emp_name,emp_salary) VALUES("andy",777.77);
第二步:新建项目,导入依赖
<dependencies>
<!-- mybatis依赖 -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.11</version>
</dependency>
<!-- MySQL驱动 mybatis底层依赖jdbc驱动实现,本次不需要导入连接池,mybatis自带! -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.25</version>
</dependency>
<!--junit5测试-->
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-api</artifactId>
<version>5.3.1</version>
</dependency>
</dependencies>
第三步:准备一个实体类
package com.swift.pojo;
public class Employee {
private Integer empId;
private String empName;
private Double empSalary;
//getter | setter
@Override
public String toString() {
return "Employee{" +
"empId=" + empId +
", empName='" + empName + '\'' +
", empSalary=" + empSalary +
'}';
}
public Integer getEmpId() {
return empId;
}
public void setEmpId(Integer empId) {
this.empId = empId;
}
public String getEmpName() {
return empName;
}
public void setEmpName(String empName) {
this.empName = empName;
}
public Double getEmpSalary() {
return empSalary;
}
public void setEmpSalary(Double empSalary) {
this.empSalary = empSalary;
}
}
第四步:准备mapper接口
public interface EmployeeMapper {
//根据id查询员工信息
Employee selectEmployee(Integer empId);
}
第五步:准备MapperXML文件
Mybatis 中的 Mapper 接口相当于以前的 Dao。但是区别在于,Mapper 仅仅只是建接口即可,我们不需要提供实现类,具体的SQL写到对应的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">
<!-- namespace等于mapper接口类的全限定名,这样实现对应 -->
<mapper namespace="com.swift.mapper.EmployeeMapper">
<!-- 查询使用 select标签
id = 方法名
resultType = 返回值类型
标签内编写SQL语句
-->
<select id="selectEmployee" resultType="com.swift.pojo.Employee">
select emp_id empId,emp_name empName, emp_salary empSalary from
t_emp where emp_id = #{empId}
</select>
</mapper>
第六步:准备mybatis配置文件
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<!-- environments表示配置Mybatis的开发环境,可以配置多个环境,在众多具体环境中,使用default属性指定实际运行时使用的环境。default属性的取值是environment标签的id属性的值。 -->
<environments default="development">
<!-- environment表示配置Mybatis的一个具体的环境 -->
<environment id="development">
<!-- Mybatis的内置的事务管理器 -->
<transactionManager type="JDBC"/>
<!-- 配置数据源 -->
<dataSource type="POOLED">
<!-- 建立数据库连接的具体信息 -->
<property name="driver" value="com.mysql.cj.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/mybatis-example"/>
<property name="username" value="root"/>
<property name="password" value="123456"/>
</dataSource>
</environment>
</environments>
<mappers>
<!-- Mapper注册:指定Mybatis映射文件的具体位置 -->
<!-- mapper标签:配置一个具体的Mapper映射文件 -->
<!-- resource属性:指定Mapper映射文件的实际存储位置,这里需要使用一个以类路径根目录为基准的相对路径 -->
<!-- 对Maven工程的目录结构来说,resources目录下的内容会直接放入类路径,所以这里我们可以以resources目录为基准 -->
<mapper resource="mappers/EmployeeMapper.xml"/>
</mappers>
</configuration>
第七步:启动测试运行
import com.swift.mapper.EmployeeMapper;
import com.swift.pojo.Employee;
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.jupiter.api.Test;
import java.io.IOException;
import java.io.InputStream;
/**
* projectName: com.atguigu.test
*
* description: 测试类
*/
public class mybatistest {
@Test
public void testSelectEmployee() throws IOException {
// 1.创建SqlSessionFactory对象
// ①声明Mybatis全局配置文件的路径
String mybatisConfigFilePath = "mybatis.xml";
// ②以输入流的形式加载Mybatis配置文件
InputStream inputStream = Resources.getResourceAsStream(mybatisConfigFilePath);
// ③基于读取Mybatis配置文件的输入流创建SqlSessionFactory对象
SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
// 2.使用SqlSessionFactory对象开启一个会话
SqlSession session = sessionFactory.openSession();
// 3.根据EmployeeMapper接口的Class对象获取Mapper接口类型的对象(动态代理技术)
EmployeeMapper employeeMapper = session.getMapper(EmployeeMapper.class);
// 4. 调用代理类方法既可以触发对应的SQL语句
Employee employee = employeeMapper.selectEmployee(2);
System.out.println("employee = " + employee);
// 4.关闭SqlSession
session.commit(); //提交事务 [DQL不需要,其他需要]
session.close(); //关闭会话
}
}
运行结果
2、mybatis日志设置
我们可以在mybatis的配置文件使用settings标签设置,输出运过程SQL日志!
通过查看日志,我们可以判定#{} 和 ${}的输出效果
value值是设置日志类型,我们可以选
SLF4J | LOG4J | LOG4J2 | JDK_LOGGING | COMMONS_LOGGING | STDOUT_LOGGING | NO_LOGGING这些日志
<settings>
<!-- SLF4J 选择slf4j输出! -->
<setting name="logImpl" value="SLF4J"/>
</settings>
3、取值符号#{}和${}的区别
#{}:Mybatis会将SQL语句中的#{}转换为问号占位符。由于使用了预编译语句和参数化查询,#{}可以很大程度上防止SQL注入攻击,提高了数据库操作的安全性。
${}:${}形式传参,底层Mybatis做的是字符串拼接操作。在动态SQL解析阶段将会进行变量替换。它直接将参数值嵌入到SQL语句中,不会进行预编译或转义。因此,使用${}时需要特别小心,以避免SQL注入等安全问题。
4、mybatis数据传入
这里数据传入具体是指上层方法(例如Service方法)调用Mapper接口时,数据传入的形式。
传入类型分为两种,一种是简单类型,另一种是复杂类型
简单类型:只包含一个值的数据类型
- 基本数据类型:int、byte、short、double
- 基本数据类型的包装类型:Integer、Character、Double
- 字符串类型:String
复杂类型:包含多个值的数据类型
- 实体类类型:Employee、Department
- 集合类型:List、Set、Map
- 数组类型:int[]、String[]
- 复合类型:List<Employee>、实体类中包含集合
4.1传入单个简单类型
key随便写,一般情况推荐使用参数名
4.2传入实体对象
key只能写传入对象属性名
4.3传入多个简单类型参数
用@Param指定参数名称
除此之外,还可以用mybatis自带的arg0,arg1,param1,param2传入
4.4传入Map类型参数
key就等于Map的key
5、mybatis数据返回
数据返回总体上有两种形式:
- 增删改操作返回的受影响行数:直接使用 int 或 long 类型接收即可
- 查询操作的查询结果
我们需要做的是,指定查询的输出数据类型即可!
并且插入场景下,实现主键数据回显示!
5.1返回单个简单类型
可以写类的全限定符或者别名
Mybatis 内部给常用的数据类型设定了很多别名。 以 int 类型为例,可以写的名称有:int、double、integer、Integer、java.lang.Integer、Int、INT、INTEGER 等等
如果是返回我们自己定义的类,我们也可以去xml上配置我们的别名,当这样配置时,Blog 可以用在任何使用 domain.blog.Blog 的地方。
<typeAliases>
<typeAlias alias="Author" type="domain.blog.Author"/>
<typeAlias alias="Blog" type="domain.blog.Blog"/>
</typeAliases>
也可以指定一个包名,MyBatis 会在包名下面搜索需要的 Java Bean,比如:
<typeAliases> <package name="domain.blog"/> </typeAliases>
每一个在包 domain.blog 中的 Java Bean,在没有注解的情况下,会使用 Bean 的首字母小写的非限定类名来作为它的别名。 比如 domain.blog.Author 的别名为 author;若有注解,则别名为其注解值。见下面的例子:
5.2返回单个自定义实体类型
可以写类的全限定符,或者别名
类的全限定符
起别名
5.3返回Map类型
适用于SQL查询返回的各个字段综合起来并不和任何一个现有的实体类对应,没法封装到实体类对象中。能够封装成实体类类型的,就不使用Map类型。
5.4返回list类型
查询结果返回多个实体类对象,希望把多个实体类对象放在List集合中返回。此时不需要任何特殊处理,在resultType属性中还是设置实体类类型即可。
5.5返回主键值
useGeneratedKeys属性字面意思就是“使用生成的主键”
keyProperty属性可以指定主键在实体类对象中对应的属性名
Mybatis会将拿到的主键值存入这个属性
Mybatis是将自增主键的值设置到实体类对象中,而不是以Mapper接口方法返回值的形式返回