芋道 Spring Boot MyBatis 入门(一)之 MyBatis + XML
1. 概述
2. MyBatis + XML
2.1 引入依赖
2.2 Application
2.3 应用配置文件
2.4 MyBatis 配置文件
2.5 UserDO
2.6 UserMapper
2.7 简单测试
3. MyBatis + 注解
3.1 差异部分
3.2 UserMapper
3.3 简单测试
4. MyBatis-Plus
4.1 引入依赖
4.2 Application
4.3 应用配置文件
4.4 UserDO
4.5 UserMapper
4.6 简单测试
5. tkmybatis
5.1 引入依赖
5.2 Application
5.3 应用配置文件
5.4 MyBatis 配置文件
5.5 UserDO
5.6 UserMapper
5.7 简单测试
666. 彩蛋
本文,我们基于 Spring Boot 2.X 版本。
1. 概述
在 DAL 数据访问层,目前会有三种方向的解决方案:
JDBC
MyBatis
JPA
艿艿自己在 知识星球 中,做过一个简单的调研,看看大家使用哪个为主。结果是 MyBatis > JPA > JDBC 。这个也符合在知乎上看到的两篇文章:
《MyBatis 为什么在国内相当流行?》
《为什么阿里巴巴的持久层采用 iBatis 框架,而不使用 hibernate 框架呢?感觉 hibernate 更厉害的样子?》
而每个团队使用 MyBatis 方式还有不同,主要是如下:
注意,几种方式可以组合使用。
MyBatis + XML
MyBatis + 注解
MyBatis-Plus
tkmybatis
艿艿的团队,最终我们使用 XML 的方式,因为 XML 便于可以看到每个表使用到的 SQL ,方便做优化和管理。
后来,考虑到提高开发效率,很多标准的数据库的 CRUD 操作,编写还是比较枯燥乏味浪费时间,所以使用 MyBatis-Plus 简化。当然,一些相对复杂的 SQL ,还是会考虑使用 XML 。
下面,我们上面列的四种方式,逐个来入门。
2. MyBatis + XML
示例代码对应仓库:mybatis-xml 。
本小节,我们会使用 mybatis-spring-boot-starter
自动化配置 MyBatis 主要配置。同时,在 XML 中编写相应的 SQL 操作。
2.1 引入依赖
在 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>
具体每个依赖的作用,胖友自己认真看下艿艿添加的所有注释噢。
2.2 Application
创建 Application.java
类,配置 @MapperScan
注解,扫描对应 Mapper 接口所在的包路径。代码如下:
// Application.java
@SpringBootApplication
@MapperScan(basePackages = "cn.iocoder.springboot.lab12.mybatis.mapper")
public class Application {
}
`cn.iocoder.springboot.lab12.mybatis.mapper` 包路径下,就是我们 Mapper 接口所在的包路径。
建议 1 :因为这里是做示例。实际项目中,可以考虑创建一个 MyBatisConfig 配置类,将
@MapperScan
注解添加到其上。
2.3 应用配置文件
在 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 # 配置数据库实体包路径
具体的每个配置项,胖友自己认真看下艿艿添加的所有注释噢。
2.4 MyBatis 配置文件
在 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
来自动转换。
2.5 UserDO
在 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;
2.6 UserMapper
在 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
注解,声明变量名。在方法为单参数时,非必须。
在方法为多参数时,必须。艿艿自己的编程习惯,禁止使用 Map 作为查询参数,因为无法通过方法的定义,很直观的看懂具体的用途。
细心的胖友,肯定会发现例如说
#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>
建议 1 :对于绝大多数查询,我们是返回统一字段,所以可以使用 标签,定义 SQL 段。对于性能或者查询字段比较大的查询,按需要的字段查询。
建议 2 :对于数据库的关键字,使用大写。例如说,
SELECT
、WHERE
等等。建议 3 :基本是每“块”数据库关键字占用一行,胖友可以看看艿艿写的每一行示例。一定要排版干净,毕竟我们是有代码洁癖的男孩子。
2.7 简单测试
创建 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());
}
}
具体的,胖友可以自己跑跑,妥妥的。
更多相关文章
- 云原生 DevOps 的 5 步升级路径
- Python+Kepler.gl轻松制作酷炫路径动画
- 对比Excel学习SQL(4):计算字段
- Java 类路径(学习 Java 编程语言 036)
- LeetCode 实战:「图解」二叉树中的最大路径和
- 动画:面试必刷之二叉树中和为某一值的路径
- 使用位运算处理一道难题:获取所有钥匙的最短路径
- 数据结构与算法——图最短路径
- mysql正则匹配模糊查询某个字段