【spring data jpa】使用spring data jpa时,关于service层一个方法中进行【删除】和【插入】两种操作在同一个事务内处理
场景:
现在有这么一个情况,就是在service中提供的一个方法是先将符合条件的数据全部删除,然后再将新的条件全部插入数据库中
这个场景需要保证service中执行两步
1.删除
2.插入
这两步自然是在同一个事务中完成才是一个完整的操作。
那么针对这个场景,看看注解怎么用
1》》先看dao层 链接:http://www.cnblogs.com/sxdcgaq8080/p/8984140.html
dao层也就是repository层的delete操作,也就是在jpa中使用delete操作,需要加上
@Modifying
@Transactional
这两个注解,因为
1.@Modifying 以通知 SpringData, 这是一个 UPDATE 或 DELETE 操作
2.UPDATE 或 DELETE 操作需要使用事务,所以在dao层的delete方法上需要加上这两个注解

2》》然后说service层的这个方法中的两步走
需要在入口方法上加上
@Transactional
注解,用来保证两步操作在同一个事务内执行

这样的情况,是第一个事务注解起作用,delete方法上的注解是为了支持delete操作才加的
======================================
但是这个时候依旧是会出问题的,因为执行spring data的delete操作,并不会立即执行,而是等到service方法执行完成,才会提交事务。但是这样的话 insert插入就会出现 重复数据存在,不能重复插入的错误!!!
理一下这个逻辑:【spring的事务@Transactional底层是spring AOP】
1.进入方法,开启事务
2.代码delete方法是jpa的delete方法,断点在此处发现并没有执行delete的sql语句,但是执行了一条select语句。【可见自定义的delete方法是根据查到的数据再拼接sql在事务提交的时候才执行】
3.执行save的插入方法,执行了insert语句,报错数据已经存在,不能重复插入
4.关闭事务
而我们想要delete在insert之前就执行了,并且还要保证delete和insert是在同一个事务中进行的。
解决方案1:
仅更改service代码
手动调用flush()方法,【让jpa在selete出这个对象之后,拼接了delete语句,然后即刻执行sql作用到数据库】,这样在下面insert的时候delete已经执行了,就不会出现重复数据的错误。

解决方法2:
就是写@Query("JPQL语句")
告诉jpa,我要明确执行这条delete的sql语句,避免了【让它去查一遍,拿到实体以后再拼接SQL语句,最后在方法结束,事务提交的时候才去执行delete语句】,这个时候已经迟了。
这个时候是不会执行select语句的,只执行了delete和insert
仅改变dao层代码

service不变如下

这两种方式都可以解决 delete操作和save操作在同一个事务中的原子性。
但是第一种方法相当于是多做了一步,就是执行delete的时候会去数据库selete一次。。。而第二种方法则会直接执行delete语句,不会执行selete。
【spring data jpa】使用spring data jpa时,关于service层一个方法中进行【删除】和【插入】两种操作在同一个事务内处理的更多相关文章
- 当 IDENTITY_INSERT 设置为 OFF 时,不能向表 'OrderList' 中的标识列插入显式值
问题描述:在SQL SERVER 2008中,向数据表中字段插入数据时,会报错,错误如下: 当 IDENTITY_INSERT 设置为 OFF 时,不能向表 'OrderList' 中的标识列插入显式 ...
- 当 IDENTITY_INSERT 设置为 OFF 时,不能向表 '#TT' 中的标识列插入显式值。 sql server 临时表
当 IDENTITY_INSERT 设置为 OFF 时,不能向表 '#TT' 中的标识列插入显式值.我是在SqlServer写存储过程中遇到的这个错误,当时就心想:临时表怎么会有主键呢,我也没有设置主 ...
- 当 IDENTITY_INSERT 设置为 OFF 时,不能为表‘XXX’中的标识列插入显式值。
在创建事务复制时,很多时候不一定使用快照进行初始化,而是使用备份还原初始化.当对有标识列(即identity的自增列)的表进行复制的时候,使用备份还原初始化搭建起来的复制常常就会报错,即:当 IDEN ...
- The Data Way Vol.4|开源是创造软件诸多方法中最好的一种形式
关于「The Data Way」 「The Data Way」是由 SphereEx 公司出品的一档播客节目.这里有开源.数据.技术的故事,同时我们关注开发者的工作日常,也讨论开发者的生活日常:我们聚 ...
- Spring main方法中怎么调用Dao层和Service层的方法
在web环境中,一般serviceImpl中的dao之类的数据库连接都由容器启动的时候创建好了,不会报错.但是在main中,没有这个环境,所以需要获取环境: ApplicationContext ct ...
- [Bug]当IDENTITY_INSERT设置为OFF时,不能为表“xx”中的标识列插入显示的值
写在前面 在设计数据库表时,将主键设置为了自增的.在使用linq to sql的时候,添加数据,出现此错误. 解决方案 找到linq to sql生成的**.dbml文件,在对应的表上面右键修改其属性 ...
- 当 IDENTITY_INSERT 设置为 OFF 时,不能为表 'tb_MyInvoices' 中的标识列插入显式值
默认情况下,IDENTITY_INSER就是off 这种情况下,你写insert 语句时,identity栏位,不要写值,系统会自动帮你写入. 举例说明: ,),dt datetime,pay int ...
- 通过特殊处理 Resize 事件解决 WinForm 加载时闪烁问题的一个方法
WinForm 上放置的控件多了或者有大背景图,窗体加载时就会闪烁,对于一般的闪烁,设置 DoubleBuffer=True或许有一点改善,要立竿见影的解决可以重载 CreateParams 使用 W ...
- 当 IDENTITY_INSERT 设置为 OFF 时,不能为表 'T_Shell' 中的标识列插入显式值。
--允许将显示值插入表的标识列中-ON:允许 OFF:不允许set identity_insert T_shell ONset identity_insert T_Shell OFF
随机推荐
- POJ3216 最小路径覆盖
首先说一下题意,Q个区域,M个任务,每个区域任务可能有多个,然后给你个到各地所需时间的矩阵,每个任务都有开始和持续时间,问最少需要多少工人? 每个工人只能同时执行一个任务. 通过题意,我的瞬间反应就是 ...
- excludeFromRecents标签
Android:excludeFromRecents控制在不在recent列表中显示. true时不显示:false显示,默认. 运行如下activity后,不会显示在recent列表中. <a ...
- java静态代理模式
代理模式分为动态代理和静态代理. 静态代理简述: 1.为其他对象提供一种代理,以控制对这个对象的访问. 2.代理对象会起到中介的作用,可以增加些功能,也可以去掉某些功能. 静态代理: 代理和被代理对象 ...
- Nginx从入门到放弃-第2章 基础篇
2-1 什么是Nginx 2-2 常见的中间件服务 2-3 Nginx的特性_实现优点1 2-4 Nginx特性_实现优点2 2-5 Nginx特性_实现优点3 2-6 Nginx特性_实现优点4 2 ...
- adb pull 文件夹的时候注意
传说之美 分享快乐 记录生活 学习探索 博客园 首页 新随笔 联系 管理 订阅 随笔- 75 文章- 0 评论- 19 Android 用adb pull或push 拷贝手机文件到到电脑上,拷贝 ...
- 读《MySql必知必会》笔记
MySql必知必会 2017-12-21 意义:记录个人不注意的,或不明确的,或不知道的细节方法技巧,此书250页 登陆: mysql -u root-p -h myserver -P 9999 SH ...
- 【bzoj1043】[HAOI2008]下落的圆盘 计算几何
题目描述 有n个圆盘从天而降,后面落下的可以盖住前面的.求最后形成的封闭区域的周长.看下面这副图, 所有的红色线条的总长度即为所求. 输入 第一行为1个整数n,N<=1000接下来n行每行3个实 ...
- [POI2005]SKA-Piggy Banks (Tarjan缩点)
题目链接 Solution \(Tarjan\) 缩点乱搞. 考虑到环内如果有一个被打开,那么也就全部打开了. 然后很显然入度为 \(0\) 的点需要被砸破. 所以缩点之后找到入度为 \(0\) 的即 ...
- 洛谷 [P2480] 古代猪文
卢卡斯定理 注意特判底数和模数相等的情况 http://www.cnblogs.com/poorpool/p/8532809.html #include <iostream> #inclu ...
- C语言第三题
1.完成char *p,char *q 的字符串比较,相等返回1,错误返回-1 2.用户需要计算的2个20位数数字的加法,写程序实现让用户输入两个20位以上的数字并且相加,输出结果