玩转spring boot——结合JPA事务
接着上篇
一、准备工作
修改pom.xml文件
<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.github.carter659</groupId>
<artifactId>spring06</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging> <parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.4.2.RELEASE</version>
</parent> <name>spring06</name>
<url>http://maven.apache.org</url> <properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<java.version>1.8</java.version>
</properties> <dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<dependency>
<groupId>commons-dbcp</groupId>
<artifactId>commons-dbcp</artifactId>
</dependency> </dependencies> <build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
pom.xml
添加src/resources/application.properties文件
spring.datasource.initialize=false
spring.datasource.url=jdbc:mysql://localhost:3306/demo
spring.datasource.username=root
spring.datasource.password=
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
application.properties
添加src/resources/templates/index.html文件
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title>玩转spring boot——结合JPA</title>
<script src="//cdn.bootcss.com/angular.js/1.5.6/angular.min.js"></script>
<script type="text/javascript">
/*<![CDATA[*/
var app = angular.module('app', []);
app.controller('MainController', function($rootScope, $scope, $http) { $scope.data = {};
$scope.rows = []; //添加
$scope.add = function() {
$scope.data = {
no : 'No.1234567890',
quantity : 100,
'date' : '2017-01-01'
};
} //保存
$scope.save = function() {
$http({
url : '/save',
method : 'POST',
data : $scope.data
}).success(function(r) {
//保存成功后刷新
window.location.reload();
});
} //初始化载入数据
$http({
url : '/findAll',
method : 'POST'
}).success(function(rows) {
for ( var i in rows) {
var row = rows[i];
$scope.rows.push(row);
}
}); }); /*]]>*/
</script>
</head>
<body ng-app="app" ng-controller="MainController">
<h1>玩转spring boot——JPA事务</h1>
<h4>
<a href="http://www.cnblogs.com/GoodHelper/">from 刘冬的博客</a>
</h4>
<input type="button" value="添加" ng-click="add()" />
<input type="button" value="保存" ng-click="save()" />
<br />
<br />
<h3>订单信息:</h3>
<input type="hidden" ng-model="data.id" />
<table cellspacing="1" style="background-color: #a0c6e5">
<tr>
<td>编号:</td>
<td><input ng-model="data.no" /></td>
<td>日期:</td>
<td><input ng-model="data.date" /></td>
<td>数量:</td>
<td><input ng-model="data.quantity" /></td>
</tr>
</table>
<br /> <h3>订单列表:</h3>
<table cellspacing="1" style="background-color: #a0c6e5">
<tr ng-repeat="row in rows" bgcolor='#F4FAFF'>
<td>{{row.no}}</td>
<td>{{row.date}}</td>
<td>{{row.quantity}}</td>
</tr>
</table> <br />
<a href="http://www.cnblogs.com/GoodHelper/">点击访问原版博客</a>
</body>
</html>
同上篇的Order类
package com.github.carter659.spring06; import java.util.Date; import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.Table;
import javax.persistence.Temporal;
import javax.persistence.TemporalType; import org.hibernate.annotations.GenericGenerator; /**
* 博客出处:http://www.cnblogs.com/GoodHelper/
*
* @author 刘冬
*
*/
@Entity
@Table(name = "t_order")
public class Order { @Id
@GeneratedValue(generator = "uuid")
@GenericGenerator(name = "uuid", strategy = "uuid2")
@Column(name = "order_id", length = 36)
public String id; @Column(name = "order_no", length = 50)
public String no; @Temporal(TemporalType.DATE)
@Column(name = "order_date")
public Date date; @Column(name = "quantity")
public int quantity; /**
* 省略 get set
*/
}
Order.java
新建实现JpaRepository的OrderRepository接口
package com.github.carter659.spring06; import org.springframework.data.jpa.repository.JpaRepository; /**
* 博客出处:http://www.cnblogs.com/GoodHelper/
*
* @author 刘冬
*
*/
public interface OrderRepository extends JpaRepository<Order, String> { }
OrderRepository.java
新建OrderDao类
package com.github.carter659.spring06; import java.util.List; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository; import com.mysql.jdbc.StringUtils; @Repository
public class OrderDao { @Autowired
private OrderRepository orderRepository; /**
* 获取全部
*
* @return
*/
public List<Order> findAll() {
return orderRepository.findAll();
} /**
* 持久化
*
* @param entity
* @return
*/
public void save(Order entity) throws Exception {
// 持久化
orderRepository.save(entity);
// 如果持久化成功,就抛出异常。如果开启事务,那么刚才持久化的数据应回滚
if (!StringUtils.isNullOrEmpty(entity.id))
throw new Exception("测试无法持久化第一条数据的异常");
}
}
假设:当成功insert一条数据后,抛出异常。如果事务生效,则数据会回滚。反之,则不回滚。
控制器:MainController
package com.github.carter659.spring06; import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Map; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.propertyeditors.CustomDateEditor;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.WebDataBinder;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.InitBinder;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.ResponseBody; /**
* 博客出处:http://www.cnblogs.com/GoodHelper/
*
* @author 刘冬
*
*/
@Controller
public class MainController { @Autowired
private OrderDao orderDao; /**
* 处理日期类型
*
* @param binder
*/
@InitBinder
public void initBinder(WebDataBinder binder) {
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
dateFormat.setLenient(false);
binder.registerCustomEditor(Date.class, new CustomDateEditor(dateFormat, true));
} @GetMapping("/")
public String index() {
return "index";
} /**
* 持久化
*
* @param entity
* @return
*/
@PostMapping("/save")
public @ResponseBody Map<String, Object> save(@RequestBody Order entity) {
Map<String, Object> result = new HashMap<>();
try {
orderDao.save(entity);
result.put("success", true);
} catch (Exception e) {
result.put("success", false);
}
return result;
} /**
* 获取全部
*
* @return
*/
@PostMapping("/findAll")
public @ResponseBody Object findAll() {
return orderDao.findAll();
}
}
MainController.java
程序入口:App.java
package com.github.carter659.spring06; import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication; /**
* 博客出处:http://www.cnblogs.com/GoodHelper/
*
* @author 刘冬
*
*/
@SpringBootApplication
public class App { public static void main(String[] args) {
SpringApplication.run(App.class, args);
}
}
App.java
运行效果:

添加数据

点击保存按钮,并观察数据是否回滚:

虽然抛出异常,但数据并未回滚。
二、实现事务
这时,我修改OrderDao类,增加@Transactional(readOnly = false, rollbackFor = Throwable.class)注解:

package com.github.carter659.spring06; import java.util.List; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Transactional; import com.mysql.jdbc.StringUtils; @Repository
@Transactional(readOnly = false, rollbackFor = Throwable.class)
public class OrderDao { @Autowired
private OrderRepository orderRepository; /**
* 获取全部
*
* @return
*/
public List<Order> findAll() {
return orderRepository.findAll();
} /**
* 持久化
*
* @param entity
* @return
*/
public void save(Order entity) throws Exception {
// 持久化
orderRepository.save(entity);
// 如果持久化成功,就抛出异常。如果开启事务,那么刚才持久化的数据应回滚
if (!StringUtils.isNullOrEmpty(entity.id))
throw new Exception("测试无法持久化第一条数据的异常");
}
}
继续添加数据:

按钮保存按钮,发现:数据回滚

代码下载:https://github.com/carter659/spring-boot-06.git

如果你觉得我的博客对你有帮助,可以给我点儿打赏,左侧微信,右侧支付宝。
有可能就是你的一点打赏会让我的博客写的更好:)
玩转spring boot——结合JPA事务的更多相关文章
- 玩转spring boot——结合JPA入门
参考官方例子:https://spring.io/guides/gs/accessing-data-jpa/ 接着上篇内容 一.小试牛刀 创建maven项目后,修改pom.xml文件 <proj ...
- 玩转spring boot——开篇
很久没写博客了,而这一转眼就是7年.这段时间并不是我没学习东西,而是园友们的技术提高的非常快,这反而让我不知道该写些什么.我做程序已经有十几年之久了,可以说是彻彻底底的“程序老炮”,至于技术怎么样?我 ...
- 玩转spring boot——properties配置
前言 在以往的java开发中,程序员最怕大量的配置,是因为配置一多就不好统一管理,经常出现找不到配置的情况.而项目中,从开发测试环境到生产环境,往往需要切换不同的配置,如测试数据库连接换成生产数据库连 ...
- 玩转Spring Boot 集成Dubbo
玩转Spring Boot 集成Dubbo 使用Spring Boot 与Dubbo集成,这里我之前尝试了使用注解的方式,简单的使用注解注册服务其实是没有问题的,但是当你涉及到使用注解的时候在服务里面 ...
- Spring Boot2 系列教程(二十五)Spring Boot 整合 Jpa 多数据源
本文是 Spring Boot 整合数据持久化方案的最后一篇,主要和大伙来聊聊 Spring Boot 整合 Jpa 多数据源问题.在 Spring Boot 整合JbdcTemplate 多数据源. ...
- 玩转spring boot——快速开始
开发环境: IED环境:Eclipse JDK版本:1.8 maven版本:3.3.9 一.创建一个spring boot的mcv web应用程序 打开Eclipse,新建Maven项目 选择quic ...
- 玩转spring boot——结合redis
一.准备工作 下载redis的windows版zip包:https://github.com/MSOpenTech/redis/releases 运行redis-server.exe程序 出现黑色窗口 ...
- 玩转spring boot——AOP与表单验证
AOP在大多数的情况下的应用场景是:日志和验证.至于AOP的理论知识我就不做赘述.而AOP的通知类型有好几种,今天的例子我只选一个有代表意义的“环绕通知”来演示. 一.AOP入门 修改“pom.xml ...
- 玩转spring boot——结合AngularJs和JDBC
参考官方例子:http://spring.io/guides/gs/relational-data-access/ 一.项目准备 在建立mysql数据库后新建表“t_order” ; -- ----- ...
随机推荐
- Jenkins 安装的HTML Publisher Plugin 插件无法展示ant生成的JunitReport报告
最近在做基于jenkins ant junit 的测试持续集成,单独ant junit生成的junitreport报告打开正常,使用Jenkins的HTML Publisher Plugin 插件无 ...
- nodejs进阶(5)—接收请求参数
1. get请求参数接收 我们简单举一个需要接收参数的例子 如果有个查找功能,查找关键词需要从url里接收,http://localhost:8000/search?keyword=地球.通过前面的进 ...
- hibernate多对一双向关联
关联是类(类的实例)之间的关系,表示有意义和值得关注的连接. 本系列将介绍Hibernate中主要的几种关联映射 Hibernate一对一主键单向关联Hibernate一对一主键双向关联Hiberna ...
- Hyper-V3:虚拟机的配置
在Hyper-V成功新建一台虚拟机,在正式使用之前,必须配置VM使用的硬件资源,并授予用户访问VM的权限等,本文罗列出一些常见的配置,供读者参阅. 一,为虚拟机分配使用的内存 在Hyper-V Man ...
- Linux程序包管理之rpm
rpm简介 rpm( Red Hat Package Manager )是一个开放的软件包管理系统.它工作于Red Hat Linux及其他Linux系统,成为Linux中公认的软件包管理标准. rp ...
- OpenSUSE下编译安装OpenFoam
在不是Ubuntu系统下安装OpenFoam,需要采用编译安装的方式.以下以OpenSuSE为例进行编译安装. 1 软件包准备 需要下载两个程序包: OpenFOAM-4.x-version-4.1. ...
- babel-loader-presets
babel-loader的presets的设置有一定的顺序.es2015必须出现在stage-0前面,我记得这是因为es2015是ES6的标准,state-0等是对ES7一些提案的支持, state- ...
- 开源一个WEB版本GEF,基于SVG的网页流程图框架
8月开始断断续续的制作这个web gef,没有任何依赖,完全原生js开发,目前已经完成了雏形,基本上可以在项目里应用了. 下图展示的是demo1的效果,包括拖拽,生成连线,点击生成\取消墙体,整个de ...
- NoSql1 在Linux(CentOS)上安装memcached及使用
前言: 今天是初五,生活基本要从过年的节奏中回归到正常的生活了,所以想想也该想想与工作有关的事情了.我之前在工作中会经常使用memcached和redis,但是自己一直没有时间系统的好好看 ...
- EasyPR--开发详解(8)文字定位
今天我们来介绍车牌定位中的一种新方法--文字定位方法(MSER),包括其主要设计思想与实现.接着我们会介绍一下EasyPR v1.5-beta版本中带来的几项改动. 一. 文字定位法 在EasyPR前 ...