MyBatis 入门

MyBatis 入门

概述

MyBatis 是一款优秀的半自动化的持久层框架,支持定制化 SQL、存储过程以及高级映射,避免了几乎所有 JDBC 代码和手动设置参数以及获取结果集,MyBatis 可以使用简单的 xml 或注解用于配置映射,将接口和 Java 的 POJO(Plain Old Java Object,普通 Java 对象)映射成数据库中的记录。

MyBatis 将 SQL 与 Java 代码解耦,写在 映射文件中,而不是硬编码在 Java 代码中,功能边界清晰,维护方便,利于 SQL 的修改与优化

使用 MyBatis

1. 导入依赖

使用 MyBatis 需要两个核心依赖

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

<!-- mysql 连接驱动 -->
<dependency>
	<groupId>mysql</groupId>
	<artifactId>mysql-connector-java</artifactId>
	<version>5.1.47</version>
</dependency>

2. 创建表以及对应的实体类

在 MySQL 中建一张用于测试用的 User

CREATE DATABASE mybatis CHARSET utf8;

USE mybatis;

CREATE TABLE USER (
	id INT PRIMARY KEY AUTO_INCREMENT,
	username VARCHAR(11),
	PASSWORD VARCHAR(11)
)

对应实体类

package cool.yzt.entity;

public class User {
    private int id;
    private String username;
    private String password;
	/*
	setter、getter、toString
	*/
}

3. 主配置文件

MyBatis 的主配置文件或称全局配置文件,主要是设置 MyBatis 的属性信息,例如运行环境、事务管理、数据库连接池等,指导 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>
    <!--运行环境配置-->
    <!--配置默认运行环境为dev-->
    <environments default="dev">
        <!--环境之一-->
        <environment id="dev">
            <!--事务管理器:选择JDBC-->
            <transactionManager type="JDBC"/>
            <!--数据库连接池,type选择pooled即选择池化-->
            <dataSource type="POOLED">
                <!--连接池基本信息-->
                <property name="driver" value="com.mysql.jdbc.Driver"/>
                <property name="url" value="jdbc:mysql://127.0.0.1:3306/mybatis?useUnicode=true&amp;characterEncoding=utf-8&amp;serverTimezone=Asia/Shanghai"/>
                <property name="username" value="root"/>
                <property name="password" value="root"/>
            </dataSource>
        </environment>
    </environments>

    <!--SQL 映射配置-->
    <mappers>
        <mapper resource="cool/yzt/mapper/UserMapper.xml"/>
    </mappers>
</configuration>

4. 映射文件

SQL 映射文件的作用就是相当于定义 DAO 接口的实现类中的代码,一张表对应一个 Mapper 文件,其中定义了对于这张表的增删改查操作,并且 MyBatis 会自动完成数据封装

首先引入约束

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

作为配置文件,在开发时应该放置在 resources 目录下,并且独立设置一个包,一般命名为 mapper,mapper 包的目录应与 dao 包同级,编译后,mapper 包就会原封不动放置在项目 classes 目录下,与 dao 包同级,下面编写映射文件

<!--插入记录,标签名:insert,id是此sql的标识,可以看做方法名-->
<!--parameterType是sql的入参-->
<!--标签体内部编写sql,使用#{}作为占位符-->
<insert id="save" parameterType="cool.yzt.entity.User">
	insert into User (username,password) value(#{username},#{password})
</insert>

<!--查询,标签名:select-->
<!--查询返回一个集合,resultType是查询结果集中的值的类型-->
<select id="findAll" resultType="cool.yzt.entity.User">
	select * from user
</select>

<!--修改,标签名:update-->
<update id="update" parameterType="cool.yzt.entity.User">
	update user set password=#{password} where username=#{username}
</update>

<!--删除,标签名:delete-->
<delete id="deleteById" parameterType="java.lang.Integer">
	delete from user where id=#{id}
</delete>

注意

  1. 如果入参是一个自定义的 POJO,例如 cool.yzt.entity.User,则在 sql 中占位符 #{} 中的参数可以直接填写该 POJO 中的属性名
  2. 如果入参是 Java 原生类型,例如 java.lang.Integer,则在 sql 中占位符 #{} 中的参数名可以是任意字符,只要保证唯一即可

5. 主配置文件中注册 Mapper

在主配置文件中,添加 <mappers> 标签,注册响应的映射文件,注意,此处因为要写 xml 文件的后缀名,所以前面包名之间使用 / 隔开

<mappers>
	<mapper resource="cool/yzt/mapper/UserMapper.xml"/>
</mappers>

6. 调用 MyBtis 的原生 API,测试使用

为简单,这里直接使用单元测试,且使用 MyBtis 的原生 API,而不是编写相应的 dao 接口,使用 MyBatis 完成对数据库的增删改查,需要以下几步

  1. 创建 SqlSessionFactoryBuilder 对象
SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
  1. 通过 SqlSessionFactoryBuilderbuild() 方法创建 SqlSessionFactory,并以流的形式传入配置文件
InputStream is = MyBatisTest.class.getClassLoader().getResourceAsStream("mybatis.xml");
SqlSessionFactory factory = builder.build(is);
  1. 通过 SqlSessionFactory 获取 SqlSession 对象,一个 SqlSession 对象代表与数据库的一次会话
SqlSession sqlSession = factory.openSession();
  1. 调用 SqlSession 的相应方法,完成增删改查,注意,MyBatis 要手动提交事务(增删改)
// 插入数据,第一个参数是Mapper文件的namespace + 相应的sql的id标识,第二个参数就是 parameterType中的参数类型
sqlSession.insert("UserMapper.save",new User());
sqlSession.commit();
// 查找数据,使用 List 接收返回参数
List<User> list = sqlSession.selectList("UserMapper.findAll");
// 修改数据
sqlSession.update("UserMapper.update",user);
sqlSession.commit(); 
// 删除数据
sqlSession.delete("UserMapper.deleteById",3);
sqlSession.commit();
  1. 关闭 SqlSession,非常重要的一步,不可缺少
sqlSession.close();

MyBtis 面向接口编程

以上使用 MyBtis 原生 API 是 MyBtis 老版本完成增删改查的方式,现在 MyBtis 推荐使用接口的方式,即编写一个 DAO 接口,并且在 Mapper 文件中与相应的接口进行绑定,具体实现如下

  1. 编写一个 UserMapper 接口
package cool.yzt.dao;

import cool.yzt.entity.User;
import java.util.List;

public interface UserMapper {
    public void save(User user);
    public List<User> findAll();
    public void changePassword(User user);
    public void delete(Integer id);
}
  1. 修改对应的 Mapper 文件,其中 Mapper 的 namespace 为对应接口的全类名,Statement 的 id 为对应接口中对应方法的方法名,parameterTyperesultType 的类型都与接口的参数和返回值类型相同,如此便可将一个 DAO 层的接口与一个映射文件中的 Statement(定义了具体的 sql)进行绑定
<mapper namespace="cool.yzt.dao.UserMapper">

<insert id="save" parameterType="cool.yzt.entity.User">
	insert into User (username,password) value(#{username},#{password})
</insert>

<select id="findAll" resultType="cool.yzt.entity.User">
        select * from user
    </select>

<update id="changePassword" parameterType="cool.yzt.entity.User">
        update user set password=#{password} where username=#{username}
    </update>

<delete id="deleteById" parameterType="java.lang.Integer">
        delete from user where id=#{id}
    </delete>
</mapper>
  1. 通过 SqlSession 获取 MyBatis 为该 DAO 接口创建的代理实现类对象,如此,Service 层就可以通过该实现类的对象调用接口中的方法完成增删改查
@Test
public void test() {
	// 获取 SqlSession
	InputStream is = MyBatisTest.class.getClassLoader().getResourceAsStream("mybatis.xml");
	SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(is);
	SqlSession session = factory.openSession();

	// 获取接口的实现类对象,这个对象是 MyBatis 通过动态代理生成的实现类的对象
	UserDao mapper = session.getMapper(UserMapper.class);

	// 通过实现类对象调用接口的方法
	try {
		List<User> users = mapper.findAll();
		for(User user : users) {
			System.out.println(user);
		}
	} finally {
		session.close();
	}
}

注意

  1. 我们并没有手动为 DAO 接口写一个实现类,而是由 MyBatis 框架自动生成一个代理实现类对象
  2. 这种面向接口的方式使用 MyBatis,可以建立一种 DAO 层的规范,屏蔽具体实现,也就是说,DAO 接口的实现可以使用 MyBatis,也可以使用其他 DAO 层框架或原生 JDBC,对 sql 的优化也是在映射文件中修改,无需修改代码,方便维护
  3. Service 层调用的方法都来自 DAO 接口中规定好的,可以更安全的对参数和返回值进行类型检查
  4. SqlSession 是非线程安全的,相当于 Connection,对于数据库的每一次访问都需要创建新的 SqlSession,且最后必须正确关闭
  5. SqlSessionFactory 对象是一个重量级对象,一个应用只需创建一次

参考

尚硅谷 MyBatis 教程

Copyright: 采用 知识共享署名4.0 国际许可协议进行许可

Links: https://yzt.cool/archives/mybatis入门