看过前几篇关于Mybatis的文章可以发现,在DAO层做数据库交互时,存在两中方式。一种为使用注解手写mapper.xml,这种方式比较复杂,手写xml文件相当麻烦。另一种较手写mapper.xml文件简单一些,就是使用注解(@Select、@Update、@Insert、@Delete)的方式,但是手写sql也经常会带来一些隐式错误,并切也要手写sql,而Mybatis Generator的出现很好解决了这个痛点,Mybatis Generator可以自动生成dao层接口、pojo以及mapper.xml。DAO层可以使用Mybatis Generator自动生成的接口的现有功能,来完成具体业务需求。本篇文章将讲述一下Mybatis Generator插件的配置,及具体使用方法。
1. 项目结构
| pom.xml
| springboot-07-mybatis-generator.iml
|
+---src
| +---main
| | +---java
| | | \---com
| | | \---zhuoli
| | | \---service
| | | \---springboot
| | | \---mybatis
| | | \---generator
| | | | SpringBootMybatisGeneratorApplicationContext.java
| | | |
| | | +---controller
| | | | UserController.java
| | | |
| | | +---repository
| | | | +---conf
| | | | | DataSourceConfig.java
| | | | |
| | | | +---mapper
| | | | | UserMapper.java
| | | | |
| | | | +---model
| | | | | User.java
| | | | | UserExample.java
| | | | |
| | | | \---service
| | | | | UserRepository.java
| | | | |
| | | | \---impl
| | | | UserRepositoryImpl.java
| | | |
| | | \---service
| | | | UserControllerService.java
| | | |
| | | \---impl
| | | UserControllerServiceImpl.java
| | |
| | \---resources
| | | application.properties
| | |
| | +---autogen
| | | generatorConfig_zhuoli.xml
| | |
| | \---base
| | \---com
| | \---zhuoli
| | \---service
| | \---springboot
| | \---mybatis
| | \---generator
| | \---repository
| | \---mapper
| | UserMapper.xml
| |
| \---test
| \---java
其中generatorConfig_zhuoli.xml文件就是Mybatis Generator的配置文件。
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-Generator插件依赖
<?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-07-mybatis-generator</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>
<build>
<plugins>
<plugin>
<groupId>org.mybatis.generator</groupId>
<artifactId>mybatis-generator-maven-plugin</artifactId>
<version>1.3.5</version>
<!--如果不配置configuration节点,Mybatis Generator配置文件名字必须为generatorConfig.xml-->
<configuration>
<!--可以自定义generatorConfig文件名-->
<configurationFile>src/main/resources/autogen/generatorConfig_zhuoli.xml</configurationFile>
<verbose>true</verbose>
<overwrite>true</overwrite>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
</plugins>
</build>
<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配置
本文示例,数据源采用上篇文章介绍的Java Config配置数据源,application.properties文件中定义数据库信息,用于在Java Config中使用,如下:
##数据源配置
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
5. 数据源配置
@Configuration
@MapperScan(basePackages = "com.zhuoli.service.springboot.mybatis.generator.repository.mapper", sqlSessionFactoryRef = "sqlSessionFactory")
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/generator/repository/mapper/*.xml"));
return sessionFactory.getObject();
}
}
注意一定要添加@MapperScan注解,否则因为Mybatis Generator生成的Mapper类并没有@Mapper注解,在Repository层无法Autowired。
6. Mybatis Generator插件配置文件
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE generatorConfiguration
PUBLIC "-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN"
"http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd">
<generatorConfiguration>
<!--注意:本地需要有mysql-connector-java-5.1.45-bin.jar-->
<classPathEntry location="D:\\mysql-connector-java-5.1.45-bin.jar"/>
<context id="DB2Tables" targetRuntime="MyBatis3">
<property name="javaFileEncoding" value="UTF-8"/>
<property name="javaFormatter" value="org.mybatis.generator.api.dom.DefaultJavaFormatter"/>
<property name="xmlFormatter" value="org.mybatis.generator.api.dom.DefaultXmlFormatter"/>
<property name="beginningDelimiter" value="`"/>
<property name="endingDelimiter" value="`"/>
<plugin type="org.mybatis.generator.plugins.RowBoundsPlugin"/>
<plugin type="org.mybatis.generator.plugins.SerializablePlugin"/>
<commentGenerator>
<property name="suppressDate" value="true"/>
<property name="suppressAllComments" value="true"/>
</commentGenerator>
<!--数据源-->
<jdbcConnection driverClass="com.mysql.jdbc.Driver"
connectionURL="jdbc:mysql://115.47.149.48:3306/zhuoli_test?zeroDateTimeBehavior=convertToNull&useSSL=false&useUnicode=true&characterEncoding=UTF-8"
userId="zhuoli"
password="zhuoli">
</jdbcConnection>
<javaTypeResolver>
<property name="forceBigDecimals" value="false"/>
</javaTypeResolver>
<!--Model & Example文件-->
<javaModelGenerator targetPackage="com.zhuoli.service.springboot.mybatis.generator.repository.model"
targetProject="src/main/java">
<property name="enableSubPackages" value="true"/>
<property name="trimStrings" value="true"/>
</javaModelGenerator>
<!--Mapper.xml文件-->
<sqlMapGenerator targetPackage="com.zhuoli.service.springboot.mybatis.generator.repository.mapper"
targetProject="src/main/resources/base">
<property name="enableSubPackages" value="true"/>
</sqlMapGenerator>
<!--Mapper文件-->
<javaClientGenerator type="XMLMAPPER"
targetPackage="com.zhuoli.service.springboot.mybatis.generator.repository.mapper"
targetProject="src/main/java">
<property name="enableSubPackages" value="true"/>
</javaClientGenerator>
<!--表映射-->
<table tableName="user" domainObjectName="User">
<generatedKey column="id" sqlStatement="JDBC" identity="true"/>
<columnOverride column="id" javaType="Long"/>
<columnOverride column="is_deleted" javaType="Integer"/>
</table>
</context>
</generatorConfiguration>
7. Mybatis Generator插件使用
对于Idea用户,可以使用Ide集成的Maven插件运行Mybatis Generator,操作方法为:Maven Projects -> Plugins->mybatis-generator->mybatis-generator:generate->右键 Run Maven Build
看到console提示SUCCESS的时候,就表明Mybatis Generator已经运行成功,代码已经自动生成了。如果本地装了maven,还可以使用命令行方式运行,在Terminal运行命令”mvn mybatis-generator:generate”。
不知道是Mybatis Generator的bug还是其他原因,如果之前运行过Mybatis Generator插件并且已经生成POJO、Mapper、Mapper.xml文件,如果再次执行时,第二次生成的Mapper.xml文件并不会替换之前生成的文件,而是会去追加,POJO和Mapper类都是替换的。所以重新运行Mybatis Generator时,要先删除之前生成的Mapper.xml文件。
8. Mybatis Generator自动生成的代码介绍
对于一张表,Mybatis Generator生成的文件有四个,以本文的user表为例,我再配置文件中generatorConfig_zhuoli.xml中配置了user表的映射,所以生成的文件有以下四个:
8.1 POJO实体类
public class User implements Serializable {
private Long id;
private String userName;
private String description;
private Integer isDeleted;
private static final long serialVersionUID = 1L;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName == null ? null : userName.trim();
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description == null ? null : description.trim();
}
public Integer getIsDeleted() {
return isDeleted;
}
public void setIsDeleted(Integer isDeleted) {
this.isDeleted = isDeleted;
}
}
8.2 Example类
Example类主要用做查询、更新、删除时的条件定义,通俗的讲就是用来定义where后面的条件,底层通过一个Criteria静态内部类实现条件定义的,对于这个自动生成的类不用太多研究,结合使用场景,就能很好理解了,篇幅原因这里也不粘代码了,建议具体去操作一下。使用方法如下:
xxxExample example = new xxxExample();
UserExample.Criteria criteria = example.createCriteria();
方法 | 说明 |
---|---|
example.setOrderByClause(“字段名 ASC”); | 添加升序排列条件,DESC为降序 |
example.setDistinct(false) | 去除重复,boolean型,true为选择不重复的记录。 |
criteria.andXxxIsNull | 添加字段xxx为null的条件 |
criteria.andXxxIsNotNull | 添加字段xxx不为null的条件 |
criteria.andXxxEqualTo(value) | 添加xxx字段等于value条件 |
criteria.andXxxNotEqualTo(value) | 添加xxx字段不等于value条件 |
criteria.andXxxGreaterThan(value) | 添加xxx字段大于value条件 |
criteria.andXxxGreaterThanOrEqualTo(value) | 添加xxx字段大于等于value条件 |
criteria.andXxxLessThan(value) | 添加xxx字段小于value条件 |
criteria.andXxxLessThanOrEqualTo(value) | 添加xxx字段小于等于value条件 |
criteria.andXxxIn(List<?>) | 添加xxx字段值在List<?>条件 |
criteria.andXxxNotIn(List<?>) | 添加xxx字段值不在List<?>条件 |
criteria.andXxxLike(“%”+value+”%”) | 添加xxx字段值为value的模糊查询条件 |
criteria.andXxxNotLike(“%”+value+”%”) | 添加xxx字段值不为value的模糊查询条件 |
criteria.andXxxBetween(value1,value2) | 添加xxx字段值在value1和value2之间条件 |
criteria.andXxxNotBetween(value1,value2) | 添加xxx字段值不在value1和value2之间条件 |
8.3 DAO接口Mapper
其实这个Mapper跟之前我手写的mapper类是一个概念,都是定义接口,底层依赖mapper.xml文件实现具体sql操作。Mybatis Generator对生成的Mapper做了抽象,即每一张表生成的mapper类方法名都是一样的,使用这些方法,可以满足绝大多数简单sql操作,省去了我们手写sql的麻烦。
public interface UserMapper {
long countByExample(UserExample example);
int deleteByExample(UserExample example);
int deleteByPrimaryKey(Long id);
int insert(User record);
int insertSelective(User record);
List<User> selectByExampleWithRowbounds(UserExample example, RowBounds rowBounds);
List<User> selectByExample(UserExample example);
User selectByPrimaryKey(Long id);
int updateByExampleSelective(@Param("record") User record, @Param("example") UserExample example);
int updateByExample(@Param("record") User record, @Param("example") UserExample example);
int updateByPrimaryKeySelective(User record);
int updateByPrimaryKey(User record);
}
方法说明:
方法 | 功能说明 |
---|---|
int countByExample(UserExample example) thorws SQLException | 按条件计数 |
int deleteByPrimaryKey(Integer id) thorws SQLException | 按主键删除 |
int deleteByExample(UserExample example) thorws SQLException | 按条件查询 |
String/Integer insert(User record) thorws SQLException | 插入数据(返回值为ID) |
User selectByPrimaryKey(Integer id) thorws SQLException | 按主键查询 |
ListselectByExample(UserExample example) thorws SQLException | 按条件查询 |
ListselectByExampleWithBLOGs(UserExample example) thorws SQLException | 按条件查询(包括BLOB字段)。只有当数据表中的字段类型有为二进制的才会产生。 |
int updateByPrimaryKey(User record) thorws SQLException | 按主键更新 |
int updateByPrimaryKeySelective(User record) thorws SQLException | 按主键更新值不为null的字段 |
int updateByExample(User record, UserExample example) thorws SQLException | 按条件更新 |
int updateByExampleSelective(User record, UserExample example) thorws SQLException | 按条件更新值不为null的字段 |
8.4 Mapper.xml文件
与之前文章手写的mapper.xml文件一样,Mybatis Generator插件生成的mapper.xml文件同样用来定义sql语句(支持动态查询)。
9. 使用生成的DAO接口实特定功能
代码中我定义了一个UserRepository接口,用于给Service层调用。
public interface UserRepository {
List<User> getAllUsers();
List<User> getUserByCondition(String userName, String description);
User getUserById(Long id);
int delUserById(Long id);
int createUser(User user);
int updateUser(User user);
}
实现类如下:
@Repository
@AllArgsConstructor
public class UserRepositoryImpl implements UserRepository {
private UserMapper userMapper;
@Override
public List<User> getAllUsers() {
UserExample example = new UserExample();
return userMapper.selectByExample(example);
}
@Override
public List<User> getUserByCondition(String userName, String description) {
UserExample example = new UserExample();
/*动态sql,userName和description不为null,则作为查询条件查询*/
UserExample.Criteria criteria = example.createCriteria();
if (!StringUtils.isNullOrEmpty(userName)) {
criteria.andUserNameEqualTo(userName);
}
if (!StringUtils.isNullOrEmpty(description)) {
criteria.andDescriptionEqualTo(description);
}
return userMapper.selectByExample(example);
}
@Override
public User getUserById(Long id) {
return userMapper.selectByPrimaryKey(id);
}
@Override
public int delUserById(Long id) {
UserExample example = new UserExample();
example.createCriteria().andIdEqualTo(id);
return userMapper.deleteByExample(example);
/*等价于
return userMapper.deleteByPrimaryKey(id);
*/
}
@Override
public int createUser(User user) {
return userMapper.insertSelective(user);
}
@Override
public int updateUser(User user) {
return userMapper.updateByPrimaryKey(user);
}
}
10. Service层定义
public interface UserControllerService {
List<User> getAllUsers();
List<User> getByCondition(String userName, String description);
User getUserById(Long id);
int delUserById(Long id);
int createUser(User user);
int updateUser(User user);
}
实现这里不粘了,就是调用UserRepository交互数据库。
11. Controller层定义
@RestController
@AllArgsConstructor
@RequestMapping(value = "/user")
@Slf4j
public class UserController {
private UserControllerService userControllerService;
@RequestMapping(value = "/get_all", method = RequestMethod.POST)
public ResponseEntity getAllUser() {
return ResponseEntity.status(HttpStatus.OK).body(userControllerService.getAllUsers());
}
@RequestMapping(value = "/get_by_condition", method = RequestMethod.POST)
public ResponseEntity getUserByCondition(@RequestParam(value = "userName") String userName,
@RequestParam(value = "description") String description) {
return ResponseEntity.status(HttpStatus.OK).body(userControllerService.getByCondition(userName, description));
}
@RequestMapping(value = "/create", method = RequestMethod.POST)
public ResponseEntity createUser(@RequestParam(value = "userName") String userName,
@RequestParam(value = "description") String description) {
User user = new User();
user.setUserName(userName);
user.setDescription(description);
userControllerService.createUser(user);
return ResponseEntity.status(HttpStatus.OK).body("create user success");
}
@RequestMapping(value = "/query_user", method = RequestMethod.POST)
public ResponseEntity queryUserById(@RequestParam(value = "id") Long id) {
return ResponseEntity.status(HttpStatus.OK).body(userControllerService.getUserById(id));
}
@RequestMapping(value = "/update_user", method = RequestMethod.POST)
public ResponseEntity updateUserById(@RequestParam(value = "id") Long id,
@RequestParam(value = "userName") String userName,
@RequestParam(value = "description") String description) {
User user = new User();
user.setId(id);
user.setUserName(userName);
user.setDescription(description);
userControllerService.updateUser(user);
return ResponseEntity.status(HttpStatus.OK).body("update user success");
}
@RequestMapping(value = "/del_user", method = RequestMethod.POST)
public ResponseEntity deleteUserById(@RequestParam(value = "id") Long id) {
userControllerService.delUserById(id);
return ResponseEntity.status(HttpStatus.OK).body("del user success");
}
}
12. 测试
使用postman进行接口测试,由于controller方法参数使用的是@RequestParam接收的,所以测试时,请求头要设置为x-www-form-urlencoded,否则会报“HTTP Status 400 – Required String parameter ‘xx’ is not present”错,具体请查看
示例代码:码云 – 卓立 – Mybatis Generator使用示例