Java基础之Mybatis框架

简介

  1. mybatis 是一个优秀的基于 java 的持久层框架,它内部封装了 jdbc,使开发者只需要关注 sql 语句本身,而不需要花费精力去处理加载驱动、创建连接、创建 statement 等繁杂的过程。

  2. mybatis 通过 xml 或注解的方式将要执行的各种 statement 配置起来,并通过 java 对象和 statement 中sql 的动态参数进行映射生成最终执行的 sql 语句,最后由 mybatis 框架执行 sql 并将结果映射为 java 对象并返回。

  3. 采用 ORM 思想解决了实体和数据库映射的问题,对 jdbc 进行了封装,屏蔽了 jdbc api 底层访问细节,使我们不用与 jdbc api 打交道,就可以完成对数据库的持久化操作。

MyBatis中文网

快速使用

使用步骤

  1. 创建Maven工程,导入坐标
  2. 创建实体类和接口
  3. 创建Mybatis核心配置文件
  4. 创建SQL映射文件
  5. 编码
    • 加载核心配置文件,获取SqlSessionFactory对象
    • 获取SqlSession对象,执行SQL语句
    • 释放资源

例子

  1. 前提

    创建test数据库,在数据库中创建表并添加数据

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    create database if not exists test;

    create table tb_user (
    id int primary key auto_increment,
    username varchar(20),
    password varchar(20),
    age int,
    address varchar(100)
    );

    insert into tb_user values (1, 'zhangsan', '123', 23, 'Beijing');
    insert into tb_user values (2, 'lisi', '456', 24, 'Hangzhou');
    insert into tb_user values (3, 'wangwu', '789', 25, 'Guangzhou');
  2. 创建maven工程,并配置pom.xml

    添加mybatis包依赖和对应的jdbc驱动依赖

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    <dependencies>
    <dependency>
    <groupId>junit</groupId>
    <artifactId>junit</artifactId>
    <version>4.11</version>
    <scope>test</scope>
    </dependency>
    <dependency>
    <groupId>org.mybatis</groupId>
    <artifactId>mybatis</artifactId>
    <version>3.4.5</version>
    </dependency>
    <dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <version>8.0.32</version>
    </dependency>
    </dependencies>
  3. 创建一个Mybatis配置文件mybatis-config.xml,包含数据库配置信息

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    <?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">
    <!-- mybatis的主配置文件 -->
    <configuration>
    <!-- 配置环境 -->
    <environments default="development">
    <!-- 配置mysql的环境 -->
    <environment id="development">
    <!-- 配置事务的类型 -->
    <transactionManager type="JDBC"/>
    <!-- 配置数据源(连接池) -->
    <dataSource type="POOLED">
    <!-- 配置连接数据库的四个基本信息 -->
    <property name="driver" value="com.mysql.jdbc.Driver"/>
    <property name="url" value="jdbc:mysql://localhost:3306/test?useSSL=false"/>
    <property name="username" value="root"/>
    <property name="password" value="root"/>
    </dataSource>
    </environment>
    </environments>
    <mappers>
    <!-- 指定映射配置文件的位置 -->
    <mapper resource="UserMapper.xml"/>
    </mappers>
    </configuration>
  4. 创建User类对象和SQL映射文件UserMapper.xml

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    package org.example;

    public class User {
    private Integer id;
    private String username;
    private String password;
    private Integer age;
    private String address;

    public Integer getId() {
    return id;
    }

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

    public String getUsername() {
    return username;
    }

    public void setUsername(String username) {
    this.username = username;
    }

    public String getPassword() {
    return password;
    }

    public void setPassword(String password) {
    this.password = password;
    }

    public Integer getAge() {
    return age;
    }

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

    public String getAddress() {
    return address;
    }

    public void setAddress(String address) {
    this.address = address;
    }

    @Override
    public String toString() {
    return "User{" +
    "id=" + id +
    ", username='" + username + '\'' +
    ", password='" + password + '\'' +
    ", age=" + age +
    ", address='" + address + '\'' +
    '}';
    }
    }

    UserMapper.xml

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    <?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">
    <!-- 名称空间,可区分不同mapping文件中的id标识 -->
    <mapper namespace="test">
    <select id="selectAll" resultType="org.example.User">
    select * from tb_user;
    </select>
    </mapper>
  5. 编写代码MybatisDemo

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    package org.example;

    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.List;

    public class MybatisDemo {
    public static void main(String[] args) throws IOException {
    // 1.读取配置文件
    InputStream in = Resources.getResourceAsStream("mybatis-config.xml");
    // 2.创建SqlSessionFactory工厂
    SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(in);
    // 3.使用工厂生产SqlSession对象
    SqlSession sqlSession = sqlSessionFactory.openSession();

    // 4.执行sql
    List<User> users = sqlSession.selectList("test.selectAll");
    System.out.print(users);

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

Mapper代理开发

上面代码中List<User> users = sqlSession.selectList("test.selectAll");硬编码依旧存在

遵循规则

  1. 定义与SQL映射文件同名的Mapper接口,并且将Mapper接口和SQL映射文件放置在同一目录下
  2. 设置SQL映射文件的namespace属性为Mapper接口全限定名
  3. 在Mapper接口中定义方法,方法名就是SQL映射文件中的SQL语句的id,并保持参数类型和返回值类型一致
  4. 编码
    • 通过SqlSession的getMapper方法获取Mapper接口的代理对象
    • 调用对应方法完成SQL的执行

例子

  1. 定义一个UserMapper接口,将之前的UserMapper.xml映射文件放在同一目录下

  2. 修改映射文件的namespace

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    <?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">
    <!-- 名称空间,可区分不同mapping文件中的id标识 -->
    <mapper namespace="org.example.mapper.UserMapper">
    <select id="selectAll" resultType="org.example.User">
    select * from tb_user;
    </select>
    </mapper>
  3. 在Mapper接口中定义方法,UserMapper接口文件中

    1
    2
    3
    4
    5
    6
    7
    8
    9
    package org.example.mapper;

    import org.example.User;

    import java.util.List;

    public interface UserMapper {
    List<User> selectAll();
    }
  4. Mybatis配置文件mybatis-config.xml需要修改下面地方

    1
    2
    3
    4
    <mappers>
    <!-- 指定映射配置文件的位置 -->
    <mapper resource="org/example/mapper/UserMapper.xml"/>
    </mappers>

    注:如果Mapper接口名称和SQL映射文件名称相同,并且在同一目录下,则可以使用包扫描的方式简化SQL映射文件的加载

    1
    2
    3
    4
    5
    6
    7
    8
    <mappers>
    <!-- 两种方式二选一 -->
    <!-- 指定映射配置文件的位置 -->
    <mapper resource="org/example/mapper/UserMapper.xml"/>

    <!-- Mapper代理方式 -->
    <package name="org.example.mapper"/>
    </mappers>
  5. 编码MybatisDemo2

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    package org.example;

    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.example.mapper.UserMapper;

    import java.io.IOException;
    import java.io.InputStream;
    import java.util.List;

    public class MybatisDemo2 {
    public static void main(String[] args) throws IOException {
    // 1.读取配置文件
    InputStream in = Resources.getResourceAsStream("mybatis-config.xml");
    // 2.创建SqlSessionFactory工厂
    SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(in);
    // 3.使用工厂生产SqlSession对象
    SqlSession sqlSession = sqlSessionFactory.openSession();
    // 4.执行sql
    // List<User> users = sqlSession.selectList("test.selectAll");
    // 4.1 获取UserMapper接口的代理对象
    UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
    List<User> users = userMapper.selectAll();
    System.out.print(users);

    // 5.释放资源
    sqlSession.close();

    }
    }

查询

查询所有

3.2中的例子已经展示

查询单个

根据用户id查询对应的User

UserMapper.xml中添加SQL语句

1
2
3
<select id="selectById" resultType="org.example.User">
select * from tb_user where id=#{id};
</select>

UserMapper接口中添加方法

1
User selectById(int id);

测试方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
@Test
public void selectById() throws IOException {
// 获取请求参数对象
int id = 1;

// 1.读取配置文件
InputStream in = Resources.getResourceAsStream("mybatis-config.xml");
// 2.创建SqlSessionFactory工厂
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(in);
// 3.使用工厂生产SqlSession对象
SqlSession sqlSession = sqlSessionFactory.openSession();
// 4.1 获取UserMapper接口的代理对象
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
// 4.2 执行SQL语句
User user = userMapper.selectById(id);
System.out.print(user);
// 5.释放资源
sqlSession.close();
}

多条件查询

根据年龄和地址查询用户

UserMapper.xml中添加SQL语句

1
2
3
<select id="selectByCondition" resultType="org.example.User">
select * from tb_user where age=#{age} and address like #{address};
</select>

UserMapper接口中添加方法,存在3种方法

1
2
3
4
5
6
7
8
// 方法1:直接传参
// List<User> selectByCondition(@Param("age") int age, @Param("address") String address);

// 方法2:传递对象
// List<User> selectByCondition(User user);

// 方法2:传递Map
List<User> selectByCondition(Map map);

测试方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
@Test
public void selectByConditicon() throws IOException {
// 获取请求参数对象
int age = 23;
String address = "Beijing";

// 处理参数
address = "%" + address + "%";

// 封装对象
// User user = new User();
// user.setAge(age);
// user.setAddress(address);

// 构造map
Map map = new HashMap();
map.put("age",age);
map.put("address",address);

// 1.读取配置文件
InputStream in = Resources.getResourceAsStream("mybatis-config.xml");
// 2.创建SqlSessionFactory工厂
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(in);
// 3.使用工厂生产SqlSession对象
SqlSession sqlSession = sqlSessionFactory.openSession();
// 4.1 获取UserMapper接口的代理对象
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
// 4.2 执行SQL语句
// 使用UserMapper接口方法1
// List<User> users = userMapper.selectByCondition(age, address);
// 使用UserMapper接口方法2
// List<User> users = userMapper.selectByCondition(user);
// 使用UserMapper接口方法3
List<User> users = userMapper.selectByCondition(map);
System.out.print(users);
// 5.释放资源
sqlSession.close();
}

多条件-动态条件查询

在多条件查询的时候,也许某个参数的值为空,则上面sql语句会查询失败,使用动态查询

UserMapper.xml中修改SQL语句

1
2
3
4
5
6
7
8
9
10
11
12
<select id="selectByCondition" resultType="org.example.User">
select *
from tb_user
<where>
<if test="age != null">
and age = #{age}
</if>
<if test="address != null and address != ''">
and address like #{address}
</if>
</where>
</select>

单条件-动态条件查询

从age或者address中选一个参数或者两个都不选进行查询

UserMapper.xml中添加SQL语句

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<select id="selectByConditionSingle" resultType="org.example.User">
select *
from tb_user
<where>
<choose>
<when test="age != null">
age = #{age}
</when>
<when test="address != null and address != ''">
address like #{address}
</when>
</choose>
</where>
</select>

UserMapper接口中添加方法

1
List<User> selectByConditionSingle(User user);

测试方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
@Test
public void selectByConditiconSingle() throws IOException {
// 获取请求参数对象
int age = 23;
String address = "Beijing";

// 处理参数
// address = "%" + address + "%";

// 封装对象
User user = new User();
user.setAge(age);
// user.setAddress(address);

// 1.读取配置文件
InputStream in = Resources.getResourceAsStream("mybatis-config.xml");
// 2.创建SqlSessionFactory工厂
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(in);
// 3.使用工厂生产SqlSession对象
SqlSession sqlSession = sqlSessionFactory.openSession();
// 4.1 获取UserMapper接口的代理对象
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
// 4.2 执行SQL语句
// 使用UserMapper接口方法2
List<User> users = userMapper.selectByConditionSingle(user);
System.out.print(users);
// 5.释放资源
sqlSession.close();
}

添加

添加

添加一个用户

UserMapper.xml中添加SQL语句

1
2
3
4
<insert id="add">
insert into tb_user (username, password, age, address)
values (#{username},#{password},#{age},#{address});
</insert>

UserMapper接口中添加方法

1
2
// 添加用户
void add(User user);

测试方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
@Test
public void Add() throws IOException {
// 获取请求参数对象
String username = "liliu";
String password = "111";
int age = 23;
String address = "Beijing";

// 封装对象
User user = new User();
user.setUsername(username);
user.setPassword(password);
user.setAge(age);
user.setAddress(address);

// 1.读取配置文件
InputStream in = Resources.getResourceAsStream("mybatis-config.xml");
// 2.创建SqlSessionFactory工厂
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(in);
// 3.使用工厂生产SqlSession对象
SqlSession sqlSession = sqlSessionFactory.openSession();
// 4.1 获取UserMapper接口的代理对象
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
// 4.2 执行SQL语句
userMapper.add(user);
// 提交事务
sqlSession.commit();
// 5.释放资源
sqlSession.close();
}

:在设置自动提交后SqlSession sqlSession = sqlSessionFactory.openSession(true);,就不需要手动提交事务了sqlSession.commit();

添加-主键返回

UserMapper.xml中修改SQL语句

1
2
3
4
<insert id="add" useGeneratedKeys="true" keyProperty="id">
insert into tb_user (username, password, age, address)
values (#{username},#{password},#{age},#{address});
</insert>

这样就将添加数后的id值绑定到了对象中,通过对象的getid方法就可获取主键的返回

修改

修改全部属性

选择一个用户ID,修改其全部字段数据

UserMapper.xml中添加SQL语句

1
2
3
4
5
6
7
8
9
<update id="update">
update tb_user
set
username = #{username},
password = #{password},
age = #{age},
address = #{address}
where id = #{id};
</update>

UserMapper接口中添加方法

1
2
// 修改
void update(User user);

返回值可以是int类型,这样返回的就是影响的行数

测试方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
@Test
public void Update() throws IOException {
// 获取请求参数对象
int id = 4;
String username = "liliu11";
String password = "11111";
int age = 23;
String address = "Beijing";

// 封装对象
User user = new User();
user.setId(id);
user.setUsername(username);
user.setPassword(password);
user.setAge(age);
user.setAddress(address);

// 1.读取配置文件
InputStream in = Resources.getResourceAsStream("mybatis-config.xml");
// 2.创建SqlSessionFactory工厂
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(in);
// 3.使用工厂生产SqlSession对象
SqlSession sqlSession = sqlSessionFactory.openSession();
// 4.1 获取UserMapper接口的代理对象
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
// 4.2 执行SQL语句
userMapper.update(user);
// 提交事务
sqlSession.commit();
// 5.释放资源
sqlSession.close();
}

修改动态字段

只需要修改属性中的部分字段

UserMapper.xml中修改SQL语句

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<update id="update">
update tb_user
<set>
<if test="username != null and username != ''">
username = #{username},
</if>
<if test="password != null and password != ''">
password = #{password},
</if>
<if test="age != null">
age = #{age},
</if>
<if test="address != null and address != ''">
address = #{address}
</if>
</set>
where id = #{id};
</update>

删除

删除一个

删除一个对应id的记录

UserMapper.xml中添加SQL语句

1
2
3
<delete id="deleteById">
delete from tb_user where id = #{id};
</delete>

UserMapper接口中添加方法

1
void deleteById(int id);

批量删除

接收的是一个id数组,删除对应id的所有记录

UserMapper.xml中添加SQL语句

1
2
3
4
5
6
7
8
<delete id="deleteByIds">
delete from tb_user where id
in
<foreach collection="ids" item="id" separator="," open="(" close=")">
#{id}
</foreach>
;
</delete>

UserMapper接口中添加方法

1
void deleteByIds(@Param("ids") int[] ids);

参数传递

Mybatis接口方法中可以接收各种各样的参数,Mybatis底层对于这些参数进行不同的封装处理方式

单个参数:

  1. POJO类型:直接使用,实体类属性名和参数占位符名称一致

  2. Map集合:直接使用,键名和参数占位符名称一致

  3. Collection:封装为Map集合

    map.put(“collection”, collection集合)

    map.put(“arg0”, collection集合)

  4. List:封装为Map集合

    map.put(“collection”, list集合)

    map.put(“list”, list集合)

    map.put(“arg0”, list集合)

  5. Array:封装为Map集合

    map.put(“array”, 数组)

    map.put(“arg0”, 数组)

  6. 其他类型:直接使用

多个参数:封装为Map集合

map.put(“arg0”, 参数值1)

map.put(“param1”, 参数值1)

map.put(“arg1”, 参数值2)

map.put(“param2”, 参数值2)

注解完成增删改查

  • 查询:@Select
  • 添加:@Insert
  • 修改:@Update
  • 删除:@Delete
1
2
@Select("select * from tb_user where id = #{id}")
public User selectById(int id);

注:

  • 注解一般完成功能简单的SQL语句
  • 配置文件完成复杂功能

参考

MyBatis中文网

Java学习之Mybatis框架入门篇 - nice_0e3 - 博客园 (cnblogs.com)

Java学习之Mybatis框架基础篇 - nice_0e3 - 博客园 (cnblogs.com)

MyBatis——MyBatis开发流程 - 城北有个混子 - 博客园 (cnblogs.com)

视频

mysql表:

1
2
3
4
5
6
7
8
9
10
11
12
create database if not exists test;
create table tb_user (
id int primary key auto_increment,
username varchar(20),
password varchar(20),
age int,
address varchar(100)
);

insert into tb_user values (1, 'zhangsan', '123', 23, 'Beijing');
insert into tb_user values (2, 'lisi', '456', 24, 'Hangzhou');
insert into tb_user values (3, 'wangwu', '789', 25, 'Guangzhou');