MyBatis为了方便与Spring Boot集成,专门提供了一个符合其规范的starter项目mybatis-spring-boot-starter。因此,我们只需在pom.xml添加相关依赖即可轻松集成。下面介绍了Spring Boot整合Mybatis的具体步骤以及事务使用(包含解决事务失效的坑),本项目依赖Spring Boot版本为2.X,mybatis为3.X。
1、mysql数据库准备
创建数据库mybatis,并创建sys_user表
CREATE TABLE `sys_user` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`user_name` varchar(50) DEFAULT NULL,
`user_password` varchar(50) DEFAULT NULL,
`user_email` varchar(50) DEFAULT NULL,
`user_info` text,
`head_img` blob,
`create_time` datetime DEFAULT NULL,
PRIMARY KEY (`id`)
)
INSERT INTO `sys_user` VALUES ('1', 'admin', '123456', '[email protected]', '管理员', null, '2019-06-12 14:44:59');
INSERT INTO `sys_user` VALUES ('2', 'test', '123456', '[email protected]', '测试用户', null, '2019-06-11 13:56:03');
2、pom.xml中添加依赖
org.springframework.boot
spring-boot-starter-web
mysql
mysql-connector-java
org.mybatis.spring.boot
mybatis-spring-boot-starter
1.3.2
junit
junit
test
3、application.properties
#数据源配置
spring.datasource.url=jdbc:mysql://XXXX:3306/mybatis?userUnicode=true&characterEncoding=UTF-8
spring.datasource.username=root
spring.datasource.password=XXXX
#mybatis配置
#映射文件的路径,多个配置可以使用英文逗号隔开
mybatis.mapperLocations=classpath:mapper/*.xml
#类型别名包配置,只能指定具体的包,多个配置可以使用英文逗号隔开
mybatis.typeAliasesPackage=com.henry.springboot.model
#日志等级
logging.level.com.henry.springboot.mapper=debug
4、logback.xml日志配置
[%-5level] %d{HH:mm:ss.SSS} [%thread] %logger - %msg%n
${APP_HOME}/common/log.log
${APP_HOME}/logs/common/log-%d{yyyy-MM-dd}.%i.log
10000
10GB
[%-5level] %d{HH:mm:ss.SSS} [%thread] %logger - %msg%n
至此配置已经基本完成(除mapper.xml文件),在写代码之前先看下项目结构:
5、项目代码
(1)mapper接口及配置
UserMapper类
package com.henry.springboot.mapper;
import java.util.List;
import org.springframework.transaction.annotation.Transactional;
import com.henry.springboot.model.SysUser;
public interface UserMapper {
/**
* 查询全部数据
*
* @return
*/
List selectAll();
/**
* 根据指定条件查询数据
* @return
*/
SysUser selectById(Long id);
/**
* 插入记录
* @param sysUser
* @return
*/
int insert(SysUser sysUser);
}
在src/main/resources中新建mapper文件夹并创建UserMapper.xml文件
insert into sys_user(
id, user_name, user_password, user_email, user_info, head_img, create_time) values(
#{id}, #{userName}, #{userPassword}, #{userEmail}, #{userInfo}, #{headImg, jdbcType=BLOB},
#{createTime, jdbcType=TIMESTAMP})
(2)服务层代码
服务接口UserService:
package com.henry.springboot.service;
import java.util.List;
import com.henry.springboot.model.SysUser;
public interface UserService {
SysUser findById(Long id);
List findAll();
void insert(SysUser sysUser) throws Exception;
}
服务接口实现类:
package com.henry.springboot.service.impl;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import com.henry.springboot.mapper.UserMapper;
import com.henry.springboot.model.SysUser;
import com.henry.springboot.service.UserService;
@Service
public class UserServiceImpl implements UserService {
@Autowired
private UserMapper UserMapper;
@Override
public SysUser findById(Long id) {
return UserMapper.selectById(id);
}
@Override
public List findAll() {
return UserMapper.selectAll();
}
@Transactional(rollbackFor = Exception.class)
@Override
public void insert(SysUser sysUser) throws Exception {
int i = UserMapper.insert(sysUser);
throw new Exception("发生异常了");
}
}
(3)controller代码
UserController类
package com.henry.springboot.controller;
import java.util.Date;
import java.util.List;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.henry.springboot.model.SysUser;
import com.henry.springboot.service.impl.UserServiceImpl;
@RestController
public class UserController {
private static final Logger logger = LoggerFactory.getLogger(UserController.class);
@Autowired
private UserServiceImpl userService;
@RequestMapping("users/{id}")
SysUser user(@PathVariable("id") Long id) {
return userService.findById(id);
}
@RequestMapping("users")
List user() {
return userService.findAll();
}
@RequestMapping("insert")
public String insert() {
SysUser user = new SysUser();
user.setUserName("test");
user.setUserPassword("123456");
user.setUserEmail("[email protected]");
user.setUserInfo("测试1");
user.setHeadImg(new byte[] { 1, 2, 3 });
user.setCreateTime(new Date());
try {
userService.insert(user);
} catch (Exception e) {
logger.error("", e);
}
return "success";
}
}
(4)model层代码
SysUser类
package com.henry.springboot.model;
import java.util.Date;
public class SysUser {
private Long id;
private String userName;
private String userPassword;
private String userEmail;
private String userInfo;
private byte[] headImg;
private Date createTime;
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;
}
public String getUserPassword() {
return userPassword;
}
public void setUserPassword(String userPassword) {
this.userPassword = userPassword;
}
public String getUserEmail() {
return userEmail;
}
public void setUserEmail(String userEmail) {
this.userEmail = userEmail;
}
public String getUserInfo() {
return userInfo;
}
public void setUserInfo(String userInfo) {
this.userInfo = userInfo;
}
public byte[] getHeadImg() {
return headImg;
}
public void setHeadImg(byte[] headImg) {
this.headImg = headImg;
}
public Date getCreateTime() {
return createTime;
}
public void setCreateTime(Date createTime) {
this.createTime = createTime;
}
}
6、运行
启动Spring Boot
(1)浏览器访问localhost:8080/users获取所有用户
(2)localhost:8080/users/1
7、事务处理
Spring Boot2.X事务处理非常简单,只需要在Service层添加@Transactional注解即可,上面代码中已经添加了。继续在浏览器中输入:localhost:8080/insert
后台:
数据库:
数据中数据依旧是两条,可以看到数据并没有真正插入到数据库中,因为事务遇到异常回滚了。
8、事务处理中的坑
坑1:上面服务层的Transaction后面我们加了(rollbackFor = Exception.class),如果不加会怎么样呢?
我们去掉后重新运行项目后,浏览器继续访问localhost:8080/insert,再看项目后台及数据库:
数据库中记录插入成功了,事务回滚失败!
这是因为Spring的默认事务规则是遇到运行异常(RuntimeException及其子类)和程序错误(Error)才会进行事务回滚,显然throw new Exception("发生异常了");直接抛出不会进行事务回滚,但是可以在@Transactional注解中使用rollbackFor属性明确指定异常。
坑2:mysql的表是有事务安全( 比如:InnoDB)和非事务安全(比如:ISAM、MyISAM)之分的。如果自己的表是MyISAM类型的,那么久改为InnoDB,以支持事务处理。参见文章:https://blog.csdn.net/kaifaxiaoliu/article/details/79990357
最后附上该项目的下载地址:https://download.csdn.net/download/jcy1009015337/11290055,没有积分的私信我~~