摘要: 原创出处 http://www.iocoder.cn/Spring-Boot/MyBatis/ 「芋道源码」欢迎转载,保留摘要,谢谢!
本文,我们基于 Spring Boot 2.X 版本。
在 DAL 数据访问层,目前会有三种方向的解决方案:
艿艿自己在 知识星球 中,做过一个简单的调研,看看大家使用哪个为主。结果是 MyBatis > JPA > JDBC 。这个也符合在知乎上看到的两篇文章:
而每个团队使用 MyBatis 方式还有不同,主要是如下:
注意,几种方式可以组合使用。
艿艿的团队,最终我们使用 XML 的方式,因为 XML 便于可以看到每个表使用到的 SQL ,方便做优化和管理。 后来,考虑到提高开发效率,很多标准的数据库的 CRUD 操作,编写还是比较枯燥乏味浪费时间,所以使用 MyBatis-Plus 简化。当然,一些相对复杂的 SQL ,还是会考虑使用 XML 。
下面,我们上面列的四种方式,逐个来入门。
示例代码对应仓库:mybatis-xml 。
本小节,我们会使用 mybatis-spring-boot-starter
自动化配置 MyBatis 主要配置。同时,在 XML 中编写相应的 SQL 操作。
在 pom.xml
文件中,引入相关依赖。
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.3.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>lab-12-mybatis</artifactId>
<dependencies>
<!-- 实现对数据库连接池的自动化配置 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
<dependency> <!-- 本示例,我们使用 MySQL -->
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.48</version>
</dependency>
<!-- 实现对 MyBatis 的自动化配置 -->
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.1.1</version>
</dependency>
<!-- 方便等会写单元测试 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
</project>
具体每个依赖的作用,胖友自己认真看下艿艿添加的所有注释噢。
创建 Application.java
类,配置 @MapperScan
注解,扫描对应 Mapper 接口所在的包路径。代码如下:
// Application.java
@SpringBootApplication
@MapperScan(basePackages = "cn.iocoder.springboot.lab12.mybatis.mapper")
public class Application {
}
@MapperScan
注解添加到其上。在 resources
目录下,创建 application.yaml
配置文件。配置如下:
spring:
# datasource 数据源配置内容
datasource:
url: jdbc:mysql://47.112.193.81:3306/testb5f4?useSSL=false&useUnicode=true&characterEncoding=UTF-8
driver-class-name: com.mysql.jdbc.Driver
username: testb5f4
password: F4df4db0ed86@11
# mybatis 配置内容
mybatis:
config-location: classpath:mybatis-config.xml # 配置 MyBatis 配置文件路径
mapper-locations: classpath:mapper/*.xml # 配置 Mapper XML 地址
type-aliases-package: cn.iocoder.springboot.lab12.mybatis.dataobject # 配置数据库实体包路径
具体的每个配置项,胖友自己认真看下艿艿添加的所有注释噢。
在 resources
目录下,创建 mybatis-config.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="mapUnderscoreToCamelCase" value="true"/>
</settings>
<typeAliases>
<typeAlias alias="Integer" type="java.lang.Integer"/>
<typeAlias alias="Long" type="java.lang.Long"/>
<typeAlias alias="HashMap" type="java.util.HashMap"/>
<typeAlias alias="LinkedHashMap" type="java.util.LinkedHashMap"/>
<typeAlias alias="ArrayList" type="java.util.ArrayList"/>
<typeAlias alias="LinkedList" type="java.util.LinkedList"/>
</typeAliases>
</configuration>
因为在数据库中的表的字段,我们是使用下划线风格,而数据库实体的字段使用驼峰风格,所以通过 mapUnderscoreToCamelCase = true
来自动转换。
在 cn.iocoder.springboot.lab12.mybatis.dataobject
包路径下,创建 UserDO.java 类,用户 DO 。代码如下:
// UserDO.java
public class UserDO {
/**
* 用户编号
*/
private Integer id;
/**
* 账号
*/
private String username;
/**
* 密码(明文)
*
* ps:生产环境下,千万不要明文噢
*/
private String password;
/**
* 创建时间
*/
private Date createTime;
// ... 省略 setting/getting 方法
}
对应的创建表的 SQL 如下:
CREATE TABLE `users` (
`id` int(11) NOT NULL AUTO_INCREMENT COMMENT '用户编号',
`username` varchar(64) COLLATE utf8mb4_bin DEFAULT NULL COMMENT '账号',
`password` varchar(32) COLLATE utf8mb4_bin DEFAULT NULL COMMENT '密码',
`create_time` datetime DEFAULT NULL COMMENT '创建时间',
PRIMARY KEY (`id`),
UNIQUE KEY `idx_username` (`username`)
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin;
在 cn.iocoder.springboot.lab12.mybatis.mapper
包路径下,创建 UserMapper 接口。代码如下:
// UserMapper.java
@Repository
public interface UserMapper {
int insert(UserDO user);
int updateById(UserDO user);
int deleteById(@Param("id") Integer id); // 生产请使用标记删除,除非有点想不开,嘿嘿。
UserDO selectById(@Param("id") Integer id);
UserDO selectByUsername(@Param("username") String username);
List<UserDO> selectByIds(@Param("ids")Collection<Integer> ids);
}
@Repository
注解,用于标记是数据访问 Bean 对象。在 MyBatis 的接口,实际非必须,只是为了避免在 Service 中,@Autowired
注入时无需报警。@Param
注解,声明变量名。#selectByUsername(@Param("username") String username)
等方法,是使用 By 字段结尾,这是为什么呢?一般情况下,在 SQL 中的 WHERE
条件字段,我们建议能够带在方法名后。原因无它,简单明了。如果是多个字段,可以使用 AND 分隔。当然,如果查询字段比较多,可能方法名会比较长。在 resources/mapper
路径下,创建 UserMapper.xml
配置文件。代码如下:
<?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">
<mapper namespace="cn.iocoder.springboot.lab12.mybatis.mapper.UserMapper">
<sql id="FIELDS">
id, username, password, create_time
</sql>
<insert id="insert" parameterType="UserDO" useGeneratedKeys="true" keyProperty="id">
INSERT INTO users (
username, password, create_time
) VALUES (
#{username}, #{password}, #{createTime}
)
</insert>
<update id="updateById" parameterType="UserDO">
UPDATE users
<set>
<if test="username != null">
, username = #{username}
</if>
<if test="password != null">
, password = #{password}
</if>
</set>
WHERE id = #{id}
</update>
<delete id="deleteById" parameterType="Integer">
DELETE FROM users
WHERE id = #{id}
</delete>
<select id="selectById" parameterType="Integer" resultType="UserDO">
SELECT
<include refid="FIELDS" />
FROM users
WHERE id = #{id}
</select>
<select id="selectByUsername" parameterType="String" resultType="UserDO">
SELECT
<include refid="FIELDS" />
FROM users
WHERE username = #{username}
LIMIT 1
</select>
<select id="selectByIds" resultType="UserDO">
SELECT
<include refid="FIELDS" />
FROM users
WHERE id IN
<foreach item="id" collection="ids" separator="," open="(" close=")" index="">
#{id}
</foreach>
</select>
</mapper>
SELECT
、WHERE
等等。创建 UserMapperTest 测试类,我们来测试一下简单的 UserMapper 的每个操作。代码如下:
// UserMapperTest.java
@RunWith(SpringRunner.class)
@SpringBootTest(classes = Application.class)
public class UserMapperTest {
@Autowired
private UserMapper userMapper;
@Test
public void testInsert() {
UserDO user = new UserDO().setUsername(UUID.randomUUID().toString())
.setPassword("nicai").setCreateTime(new Date());
userMapper.insert(user);
}
@Test
public void testUpdateById() {
UserDO updateUser = new UserDO().setId(1)
.setPassword("wobucai");
userMapper.updateById(updateUser);
}
@Test
public void testDeleteById() {
userMapper.deleteById(2);
}
@Test
public void testSelectById() {
userMapper.selectById(1);
}
@Test
public void testSelectByUsername() {
userMapper.selectByUsername("yunai");
}
@Test
public void testSelectByIds() {
List<UserDO> users = userMapper.selectByIds(Arrays.asList(1, 3));
System.out.println("users:" + users.size());
}
}
具体的,胖友可以自己跑跑,妥妥的。
如果胖友嫌弃手写 MyBatis XML 很麻烦,可以看看 IDEA MyBatisCodeHelper-Pro 插件。在没有使用 MyBatis-Plus 插件之前,使用过蛮长一段时间,我以前的老大也在用。 当然,也可以考虑使用 MyBatis Generator (MBG) 。