简介
什么是 MyBatis?
MyBatis 是一款优秀的持久层框架,它支持自定义 SQL、存储过程以及高级映射。MyBatis 免除了几乎所有的 JDBC 代码以及设置参数和获取结果集的工作。MyBatis 可以通过简单的 XML 或注解来配置和映射原始类型、接口和 Java POJO(Plain Old Java Objects,普通老式 Java 对象)为数据库中的记录。
以上内容摘自于MyBatis中文官网:MyBatis中文官网
历史
mybatis原本是apache的一个开源项目ibatis, 2010迁移至谷歌, 改名为 Mybatis, 版本升级为3.0
特点
①Mybatis 是一款优秀的持久层框架
②Mybatis 对 jdbc 进行封装, 简化了操作
③Mybatis 使用 xml 或注解方式, 将数据库记录映射到 java 对象中,
④是一种 orm(Object Relational Mapping 对象关系映射) 实现
⑤它支持动态 SQL 以及数据缓存
搭建
1.先在数据库创建一张表,在创建一个 maven 项目,创建一个实体类(应该于数据库中的表对应)
2.导入 MyBatis 和 mysql 的 jar 包,创建 MyBatis 核心配置文件其中步骤 2 为使用MyBatis框架所要用到的操作
mysql相关操作
-- 创建数据库 ssmdb
CREATE DATABASE ssmdb CHARSET utf8
-- 创建表
-- 管理员表
CREATE TABLE admin(
id INT PRIMARY KEY AUTO_INCREMENT,
account VARCHAR(12) UNIQUE NOT NULL,
`password` VARCHAR(32) NOT NULL,
`name` VARCHAR(20) NOT NULL,
gender CHAR(1)
)
-- 添加测试用例
INSERT INTO admin (account, `password`, `name`, gender)
VALUES
('000000', '000000', 'JSON', '男'),
('000001', '000000', '张三', '男')
-- 查询 admin 表中所有数据
SELECT * FROM admin
项目选择
创建Admin类
package com.flash.mybatis.model;
/**
* @author flash
* @date 2024/06/01 14:34
* 功能描述:Admin类
*/
public class Admin {
private int id;
private String name;
private String account;
private String password;
private char gender;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getAccount() {
return account;
}
public void setAccount(String account) {
this.account = account;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public char getGender() {
return gender;
}
public void setGender(char gender) {
this.gender = gender;
}
@Override
public String toString() {
return "Admin{" +
"id=" + id +
", name='" + name + '\'' +
", account='" + account + '\'' +
", password='" + password + '\'' +
", gender=" + gender +
'}';
}
}
其中get, set方法不可缺, 底层会使用到
导入 MyBatis 和 mysql 的jar包
所需依赖,在 pom.xml 文件中完成配置即可
<dependencies>
<!-- MyBtais -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.4.2</version>
</dependency>
<!-- mysql -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.16</version>
</dependency>
</dependencies>
创建 MyBatis 核心配置文件
在resources目录中创建一个xml配置文件,如图所示
该配置文件编写内容
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<settings>
<!-- 打印日志,添加此设置,会在运行时打印出此次操作的日志 -->
<setting name="logImpl" value="STDOUT_LOGGING"/>
</settings>
<typeAliases>
<!-- 指定到某一个目录下,如果没有此配置,需要在配置sql管理文件时,填入完整的类地址,
如:com.flash.mybatis.model.Admin -->
<package name="com.flash.mybatis.model"/>
</typeAliases>
<environments default="development">
<environment id="development">
<!-- 事物管理方式:就是一次对数据库操作过程中, 执行多条sql的管理
转账:
从A账户向B账户转钱
A-500
代码, 异常
B+500
把所有的操作都成功执行后, 再提交事务, 让数据库最终执行本次提交的所有sql
-->
<transactionManager type="JDBC"/><!-- 使用jdbc事务管理 -->
<!-- 数据库链接池配置
频繁的创建与校徽数据库的连接对象比较浪费时间,
可以在池子中默认创建若干个连接对象, 有请求使用时, 直接从连接池中取出一个对象,
用完还回去但不销毁, 减少了创建和销毁的时间开销
如果连接个数不够用时仍然需要创建连接对象,数据库连接池中有一个下限和一个上线,默认最多为10,最少为5个
-->
<dataSource type="POOLED">
<!-- 数据库链接 -->
<property name="driver" value="com.mysql.cj.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://127.0.0.1:3306/ssmdb?serverTimezone=Asia/Shanghai"/>
<property name="username" value="root"/>
<property name="password" value="root"/>
</dataSource>
</environment>
</environments>
<!-- 配置SQL管理文件 -->
<mappers>
<mapper resource="mappers/AdminMapper.xml"/>
</mappers>
</configuration>
创建与数据库交互所需的接口
package com.flash.mybatis.dao;
import com.flash.mybatis.model.Admin;
import java.util.List;
// 定义功能
public interface AdminDao {
/*
根据id查询管理员对象
*/
Admin findAdminById(int id);
List<Admin> findAdmins();
int addAdmin(Admin admin);
}
创建xml文件管理sql
如图所示
该文件内容如下
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.jorg//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.flash.mybatis.dao.AdminDao">
<insert id="addAdmin" parameterType="Admin">
INSERT INTO admin (account, `password`, `name`, gender)
VALUE
(#{account}, #{password}, #{name}, #{gender})
</insert>
<!--
id必须与方法名一致
parameterType 接口中定义的方法所需要的参数类型
resultType 查询结果返回类型
#{account} 相当于调用 Admin 对象的 account 变量
-->
<select id="findAdminById" parameterType="int" resultType="Admin">
select * from admin where id = #{id}
</select>
<select id="findAdmins" resultType="Admin">
select * from admin
</select>
</mapper>
测试类
package com.flash.mybatis.test;
import com.flash.mybatis.dao.AdminDao;
import com.flash.mybatis.model.Admin;
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.Reader;
import java.util.List;
/**
* @author flash
* @date 2024/06/01 17:35
* 功能描述:测试类
*/
public class Test {
public static void main(String[] args) throws IOException {
// 读入 mybatis 核心配置文件
Reader reader = Resources.getResourceAsReader("mybatis.xml");
// 创建 SqlSessionFactory 对象
// sqlSessionFactory 是用来创建 sqlSession的, 由于 sqlSessionFactory 对象创建的开销较大,
// 所以一个项目只创建一个 sqlSessionFactory 对象, 不用关闭
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(reader);
// 创建SqlSession对象
// sqlSession 对象与数据库交互的, 每次与数据库交互, 都需要一个新的连接对象
// 用完关闭即可
SqlSession sqlSession = sqlSessionFactory.openSession();
// 为接口创建一个代理对象
// 由代理对象调用接口中对应的方法
AdminDao adminDao = sqlSession.getMapper(AdminDao.class);
Admin admin = adminDao.findAdminById(1);
System.out.println(admin);
List<Admin> admins = adminDao.findAdmins();
for (Admin admin1 : admins) {
System.out.println(admin1);
}
admin = new Admin();
admin.setAccount("000002");
admin.setPassword("000000");
admin.setName("李四");
admin.setGender('女');
System.out.println("count = " + adminDao.addAdmin(admin));
sqlSession.commit();// 提交数据库事物, 事物只针对 增删改, 查询不需要提交事务
// 关闭与数据库的会话对象
sqlSession.close();
}
}
sqlSession.commit();特别说明
如果对数据库进行查询操作,那么对数据库不会产生任何影响。如果是增删改操作,会对数据库中的数据进行一定改动。
试想一种场景:A 给 B 转账 200 元,我们需要对数据库执行两部操作,A 中减去 200,B中增加 200,如果 两步中如有一步发生错误那么都会产生数据错误。解决方法,A 给 B 转账 200 元作为事件,java代码执行无误,将整个事件提交再来完成转账的操作,如果某一步发生错误将不会执行对应的sql语句。
总结:由于查询操作不会对数据库数据产生影响,直接查询即可,不需要提交;如果是增删改操作,则需要将事务提交后参会执行对应的sql语句
简化测试
上面提到有些对象之需要创建一次, 那么我们就可以把他装入到一个工具类中来让我们每一次使用时直接调用即可, 但是由于要创建一个对象, 所以将他设置为静态对象, 并在static静态代码块中完成初始化, 见代码:
工具类:
package com.flash.mybatis.util;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import java.io.IOException;
import java.io.Reader;
/**
* @author flash
* @date 2024/06/01 17:32
* 功能描述:
*/
public class MybatisUtil {
private static Reader reader;
public static SqlSessionFactory sqlSessionFactory;
static {
// 读入 mybatis 核心配置文件
try {
reader = Resources.getResourceAsReader("mybatis.xml");
} catch (IOException e) {
e.printStackTrace();
}
// 创建 SqlSessionFactory 对象
sqlSessionFactory = new SqlSessionFactoryBuilder().build(reader);
}
}
测试类:
package com.flash.mybatis.test;
import com.flash.mybatis.dao.AdminDao;
import com.flash.mybatis.model.Admin;
import com.flash.mybatis.util.MybatisUtil;
import org.apache.ibatis.session.SqlSession;
import java.io.IOException;
import java.util.List;
/**
* @author flash
* @date 2024/06/01 15:23
* 功能描述:将一些重复的代码封装后使用的案例
*/
public class Test2 {
public static void main(String[] args) throws IOException {
SqlSession sqlSession = MybatisUtil.sqlSessionFactory.openSession();
// 为接口创建一个代理对象
// 由代理对象调用接口中对应的方法
AdminDao adminDao = sqlSession.getMapper(AdminDao.class);
Admin admin = adminDao.findAdminById(1);
System.out.println(admin);
List<Admin> admins = adminDao.findAdmins();
for (Admin admin1 : admins) {
System.out.println(admin1);
}
admin = new Admin();
admin.setAccount("000002");
admin.setPassword("000000");
admin.setName("李四");
admin.setGender('女');
adminDao.addAdmin(admin);
sqlSession.commit();// 提交数据库事物, 事物只针对 增删改, 查询不需要提交事务
// 关闭与数据库的会话对象
sqlSession.close();
}
}