关于数据库访问还有一个核心操作那就是事务的处理了,前面两篇博客小伙伴们已经见识到Spring Boot带给我们的巨大便利了,其实不用猜,我们也知道Spring Boot在数据库事务处理问题上也给我们带来惊喜,OK,废话不多说,就来看看如何在Spring Boot中使用事务吧。
可能还是会有一些小伙伴对Spring Boot并不是特别熟悉,不熟悉的小伙伴请移步这里从SpringMVC到Spring Boot,老司机请忽略。
创建Project并添加数据库依赖
这个没啥好说的,不懂如何创建一个Spring Boot工程的小伙伴请移步这里初识Spring Boot框架。创建的时候选择依赖时选择Web和JPA,如下图:
图片.png
org.springframework.boot
spring-boot-starter-data-jpa
mysql
mysql-connector-java
org.mybatis.spring.boot
mybatis-spring-boot-starter
1.3.2
配置application.properties
配置方式还是和前文一模一样,不懂的小伙伴请移步这里初识在Spring Boot中使用JPA,我这里直接贴代码,含义不再赘述:
spring.datasource.url=jdbc:mysql://127.0.0.1/springboot2?useUnicode=true&characterEncoding=utf-8&serverTimezone=UTC&useSSL=true
spring.datasource.username=root
spring.datasource.password=514730
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.jpa.properties.hibernate.hbm2ddl.auto=update
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL5InnoDBDialect
spring.jpa.show-sql= true
spring.thymeleaf.cache=false
#中文
spring.http.encoding.charset=UTF-8
spring.http.encoding.force=true
spring.http.encoding.enabled=true
SQL
-- auto-generated definition
CREATE TABLE book
(
id INT AUTO_INCREMENT
PRIMARY KEY,
name VARCHAR(255) NULL,
writer VARCHAR(255) NULL,
introduction VARCHAR(255) NULL
)
ENGINE = InnoDB;
图片.png
创建实体类
package com.demo.entity;
import javax.persistence.*;
import javax.validation.constraints.Min;
import javax.validation.constraints.NotEmpty;
@Entity
@Table
public class Book {
@Id
@GeneratedValue()
private Long id;
@NotEmpty(message = "姓名不能为空")
@Column(length=50)
private String name;
@NotEmpty(message = "writer不能为空")
private String writer;
@NotEmpty(message = "introduction不能为空")
private String introduction;
public Book() {
}
@Override
public String toString() {
return "Book{" +
"id=" + id +
", name='" + name + '\'' +
", writer='" + writer + '\'' +
", introduction='" + introduction + '\'' +
'}';
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getWriter() {
return writer;
}
public void setWriter(String writer) {
this.writer = writer;
}
public String getIntroduction() {
return introduction;
}
public void setIntroduction(String introduction) {
this.introduction = introduction;
}
}
创建实体类的Repository
import org.springframework.data.jpa.repository.JpaRepository;
public interface BookDao extends JpaRepository{
}
创建业务服务Service
创建Service接口
package com.demo.service;
import com.demo.entity.Book;
public interface BookService {
public void add(Book book);
public Book savePersonWithRollBack(Book person);
public Book savePersonWithoutRollBack(Book person);
}
创建Service实现类
@Service
@Transactional
public class BookServiceImpl implements BookService {
@Resource
BookDao dao;
public void add(Book book) {
dao.save(book);
}
@Transactional(rollbackFor = {IllegalArgumentException.class})
public Book savePersonWithRollBack(Book person) {
Book book= dao.save(person);
if (person.getName().equals("sang")){
throw new IllegalArgumentException("sang已经存在 数据将回滚");
}
return book;
}
@Transactional(noRollbackFor = {IllegalArgumentException.class})
public Book savePersonWithoutRollBack(Book person) {
Book book= dao.save(person);
if (person.getName().equals("sang")){
throw new IllegalArgumentException("sang已经存在 但数据不会回滚");
}
return book;
}
}
在这里我们使用到了@Transactional注解,该注解中有一个rollbackFor属性,该属性的值为数组,表示当该方法中抛出指定的异常时数据回滚,该注解还有个属性叫noRollbackFor,表示当该方法中抛出指定的异常时数据不回滚,这两个属性我们分别在两个方法中体现。
创建控制器
@RestController
public class BookController2 {
@Autowired
BookService service;
@RequestMapping("/norollback")
public Book noRollback(Book book) {
return service.savePersonWithoutRollBack(book);
}
@RequestMapping("/rollback")
public Book rollback(Book book)
{
return service.savePersonWithRollBack(book);
}
}
控制器创建成功之后接下来我们就可以直接在浏览器中访问这两个地址看看效果了。
测试
首先在浏览器中输入
http://localhost:8080/rollback?name=sang&writer=施耐庵&introduction=小说
我们来测试回滚的情况,访问结果如下:
图片.png
看看控制台抛出的异常:
图片.png
这个时候再去查看数据库,发现数据表中并没有插入数据
图片.png
控制台也打印了错误,但是这个时候再去看数据库,数据已成功插入了。如下图:
图片.png
图片.png