MyBatis 是一款优秀的持久层框架,它支持定制化 SQL、存储过程以及高级映射。MyBatis 避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集。MyBatis 可以使用简单的 XML 或注解来配置和映射原生信息,将接口和 Java 的 POJOs(Plain Old Java Objects,普通的 Java对象)映射成数据库中的记录。由于使用方便,效率高等特性,Mybatis成为实际开发中最常用的ORM框架之一。本文将简单介绍一下Spring Boot + Mybatis实现数据库的增删该查操作。
1. 项目结构
| pom.xml
| springboot-05-mybatis-curd.iml
|
+---src
| +---main
| | +---java
| | | \---com
| | | \---zhuoli
| | | \---service
| | | \---springboot
| | | \---mybatis
| | | \---curd
| | | | SpringBootMybatisCurdApplicationContext.java
| | | |
| | | +---controller
| | | | UserController.java
| | | |
| | | +---repository
| | | | +---conf
| | | | | DataSourceConfig.java
| | | | |
| | | | +---mapper
| | | | | UserMapper.java
| | | | |
| | | | +---model
| | | | | User.java
| | | | |
| | | | \---service
| | | | | UserRepository.java
| | | | |
| | | | \---impl
| | | | UserRepositoryImpl.java
| | | |
| | | \---service
| | | | UserControllerService.java
| | | |
| | | \---impl
| | | UserControllerServiceImpl.java
| | |
| | \---resources
| | | application.properties
| | |
| | \---base
| | \---com
| | \---zhuoli
| | \---service
| | \---springboot
| | \---mybatis
| | \---curd
| | \---repository
| | \---mapper
| | UserMapper.xml
| |
| \---test
| \---java
2. 新建user表
CREATE TABLE `user` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT COMMENT '用户编号',
`user_name` varchar(25) DEFAULT NULL COMMENT '用户名称',
`description` varchar(25) DEFAULT NULL COMMENT '描述',
`is_deleted` tinyint(3) DEFAULT NULL COMMENT '是否删除',
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8
3. pom.xml添加Mybatis依赖
<?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">
<modelVersion>4.0.0</modelVersion>
<groupId>com.zhuoli.service</groupId>
<artifactId>springboot-05-mybatis-curd</artifactId>
<version>1.0-SNAPSHOT</version>
<!-- Spring Boot 启动父依赖 -->
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.3.RELEASE</version>
</parent>
<dependencies>
<!-- Exclude Spring Boot's Default Logging -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>1.3.2</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<!-- https://mvnrepository.com/artifact/org.projectlombok/lombok -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.2</version>
<scope>provided</scope>
</dependency>
</dependencies>
</project>
4. application.properties数据源配置
##数据源配置
test.datasource.url=jdbc:mysql://115.47.149.48:3306/zhuoli_test?useUnicode=true&characterEncoding=UTF-8&zeroDateTimeBehavior=convertToNull&allowMultiQueries=true&useSSL=false
test.datasource.username=zhuoli
test.datasource.password=zhuoli
test.datasource.driverClassName=com.mysql.jdbc.Driver
比较一下上节使用jdbcTemplate可以发现,上节application.properties配置都是spring打头的。区别在于本节test打头的propertity是不能被Spring Boot识别并进行数据源默认配置的,相应的本节将使用Java Config的方式进行手动配置(就是手动配置dataSource、transactionManager、sqlSessionFactory),就是接下来将提到的DataSourceConfig。
5. 编码实现
controller层和service层跟上节使用jdbcTemplate相同,这里具体讲一下使用Mybatis进行crud操作的实现。
5.1 Datasource config:
@Configuration
public class DataSourceConfig {
@Value("${test.datasource.url}")
private String url;
@Value("${test.datasource.username}")
private String user;
@Value("${test.datasource.password}")
private String password;
@Value("${test.datasource.driverClassName}")
private String driverClass;
@Bean(name = "dataSource")
public DataSource dataSource() {
PooledDataSource dataSource = new PooledDataSource();
dataSource.setDriver(driverClass);
dataSource.setUrl(url);
dataSource.setUsername(user);
dataSource.setPassword(password);
return dataSource;
}
@Bean(name = "transactionManager")
public DataSourceTransactionManager dataSourceTransactionManager() {
return new DataSourceTransactionManager(dataSource());
}
@Bean(name = "sqlSessionFactory")
public SqlSessionFactory sqlSessionFactory(@Qualifier("dataSource") DataSource dataSource) throws Exception {
final SqlSessionFactoryBean sessionFactory = new SqlSessionFactoryBean();
sessionFactory.setDataSource(dataSource);
/*设置mapper文件位置*/
sessionFactory.setMapperLocations(new PathMatchingResourcePatternResolver()
.getResources("classpath:base/com/zhuoli/service/springboot/mybatis/curd/repository/mapper/*.xml"));
/*设置实体类映射规则: 下划线 -> 驼峰*/
org.apache.ibatis.session.Configuration configuration = new org.apache.ibatis.session.Configuration();
configuration.setMapUnderscoreToCamelCase(true);
sessionFactory.setConfiguration(configuration);
return sessionFactory.getObject();
}
}
5.2 User实体类定义:
@Getter
@Setter
public class User {
private Long id;
private String userName;
private String description;
private Integer isDeleted;
}
5.3 Mapper类定义:
@Mapper
public interface UserMapper {
@Select("SELECT * FROM user WHERE id = #{id}")
List<User> findById(@Param("id") Long id);
@Select("SELECT * FROM user")
List<User> getAllUsers();
int createUser(User user);
@Insert("INSERT INTO user(user_name,description, is_deleted) VALUES (#{userName},#{description},0)")
int createUseByAnnotation(User user);
/*软删除*/
@Update("UPDATE user SET is_deleted = 1 WHERE id = #{id}")
int deleteUserById(@Param("id") Long id);
/*彻底删除*/
@Delete("DELETE from user WHERE id = #{id}")
int deleteUserComplete(@Param("id") Long id);
int updateUser(User user);
}
Mapper类用来提供sql查询,从上述Mapper类可以看出,Mapper方法实现分为两种,一种是使用注解(@Select、@Update、@Insert、@Delete),另一种是使用**Mapper.xml中定义sql语句。
5.4 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="com.zhuoli.service.springboot.mybatis.curd.repository.mapper.UserMapper">
<insert id="createUser" parameterType="com.zhuoli.service.springboot.mybatis.curd.repository.model.User">
INSERT INTO user(user_name,description, is_deleted) VALUES (#{userName},#{description},0)
</insert>
<update id="updateUser" parameterType="com.zhuoli.service.springboot.mybatis.curd.repository.model.User">
update user set user_name=#{userName},description=#{description} where id=#{id}
</update>
</mapper>
UserMapper.xml定义在resources/base/com/zhuoli/service/springboot/mybatis/curd/repository/mapper/文件夹下,之所以没有将xml文件定义在src/main/java中,是因为src/main/java文件夹下的xml文件不会被编译到classes目标目录。
如果执意要将xml文件定义在src/main/java下,要在pom.xml添加过滤器,将src/main/java下的xml文件编译到classes目标目录,如下:
<build>
<resources>
<resource>
<directory>src/main/resources</directory>
</resource>
<resource>
<directory>src/main/java</directory>
<includes>
<include>**/*.xml</include>
</includes>
<filtering>true</filtering>
</resource>
</resources>
</build>
关于resource配置原理,参考这篇文章maven的resources介绍
6. 测试
使用postman进行接口测试,由于controller方法参数使用的是@RequestParam接收的,所以测试时,请求头要设置为x-www-form-urlencoded,否则会报“HTTP Status 400 – Required String parameter ‘xx’ is not present”错,具体请查看
7. 总结
通过上述示例,可以看出Mybatis的优缺点:
优点:
- 简单易学:本身就很小且简单。没有任何第三方依赖,最简单安装只要两个jar文件+配置几个sql映射文件易于学习,易于使用
- 灵活:mybatis不会对应用程序或者数据库的现有设计强加任何影响。 sql写在xml里,便于统一管理和优化。通过sql基本上可以实现我们不使用数据访问框架可以实现的所有功能,或许更多
- 解除sql与程序代码的耦合:通过提供DAL层,将业务逻辑和数据访问逻辑分离,使系统的设计更清晰,更易维护,更易单元测试。sql和代码的分离,提高了可维护性
- 提供映射标签,支持对象与数据库的orm字段关系映射
- 提供对象关系映射标签,支持对象关系组建维护
- 提供xml标签,支持编写动态sql(后续文章讲解)
缺点:
- 编写SQL语句时工作量很大,尤其是字段多、关联表多时,更是如此
- SQL语句依赖于数据库,导致数据库移植性差,不能更换数据库
其实,实际开发中,往往可以通过Mybatis Generator插件,自动生成Model、Example、Mapper、Mapper.xml文件,做到完全不用手写sql,我会在接下来的文章讲解。
示例代码:码云 – 卓立 – Spring Boot + Mybatis CRUD操作