2017.7.7 postgreSQL在插入造成重复时执行更新
参考来自:https://stackoverflow.com/questions/1109061/insert-on-duplicate-update-in-postgresql/1109198#1109198
功能需求:接口定义中包含字段update,当它为true时,批量插入中有记录造成唯一键重复时,不报异常,而是执行更新。
1.接口定义
{
"resources":
[
{
"name":"*",
"display_name": "*",
"description": "*",
"service": "*"
},
....
],
"update":"true"
}
2.代码
原本是通过报的异常 DuplicateKeyException,在catch语句里执行update。但是这样操作有一个问题,后面单独说。
try {
resourceDao.insert(resource); } catch (DuplicateKeyException e) {
// if (StringUtils.equals(update,Constants.KEY_FALSE)) {
// throw new AuthServiceException(ErrorCode.RESOURCE_DUPLICATE_KEY, new Object[]{resource.getFdResName()}, e);
// }else if (StringUtils.equals(update,Constants.KEY_TRUE)){
// resourceDao.update(resource);
// }
throw new AuthServiceException(ErrorCode.RESOURCE_DUPLICATE_KEY, new Object[]{resource.getFdResName()}, e);
} catch (Exception e) {
throw new AuthServiceException(ErrorCode.RESOURCE_CREATE_FAILED, new Object[]{resource.getFdResName()}, e);
}
3.SQL语句
示例语句:
1 INSERT INTO the_table (id, column_1, column_2)
2 VALUES (1, 'A', 'X')3 ON CONFLICT (唯一键) DO UPDATE
4 SET column_1 ='A',
5 column_2 = 'X';
完整语句:
<insert id="insert" parameterType="Resource" useGeneratedKeys="true" keyProperty="fdResid">
INSERT INTO t_resource
<trim prefix="(" suffix=")" suffixOverrides=",">
<if test="fdResName != null">
fd_res_name,
</if>
<if test="fdDisplayName != null">
fd_display_name,
</if>
<if test="fdResDesc != null">
fd_res_desc,
</if>
<if test="fdTenantId != null">
fd_tenantid,
</if>
<if test="fdService != null">
fd_service,
</if>
</trim>
<trim prefix="values (" suffix=")" suffixOverrides=",">
<if test="fdResName != null">
#{fdResName,jdbcType=VARCHAR},
</if>
<if test="fdDisplayName != null">
#{fdDisplayName,jdbcType=VARCHAR},
</if>
<if test="fdResDesc != null">
#{fdResDesc,jdbcType=VARCHAR},
</if>
<if test="fdTenantId != null">
#{fdTenantId,jdbcType=INTEGER},
</if>
<if test="fdService != null">
#{fdService,jdbcType=VARCHAR},
</if>
</trim> <if test="fdUpdate == 'true'">
ON CONFLICT(fd_res_name, fd_tenantid, fd_service) DO UPDATE
<set>
<if test="fdDisplayName != null">fd_display_name = #{fdDisplayName},</if>
<if test="fdResDesc != null">fd_res_desc = #{fdResDesc},</if>
<if test="fdService != null">fd_service = #{fdService},</if>
<if test="fdModifyDate != null">
fd_modify_date = #{fdModifyDate,jdbcType=VARCHAR},
</if>
<if test="fdModifyPerson != null">
fd_modify_person = #{fdModifyPerson,jdbcType=VARCHAR},
</if>
</set>
</if>
</insert>
4.遇到的问题
之前提到过,之前的处理是通过所报异常信息来做的。如果重复了,在catch语句里执行update。
1 catch (DuplicateKeyException e) {
2 if (StringUtils.equals(update,Constants.KEY_FALSE)) {
3 throw new AuthServiceException(ErrorCode.RESOURCE_DUPLICATE_KEY, new Object[]{resource.getFdResName()}, e);
4 }else if (StringUtils.equals(update,Constants.KEY_TRUE)){
5 resourceDao.update(resource);
6 }
7 throw new AuthServiceException(ErrorCode.RESOURCE_DUPLICATE_KEY, new Object[]{resource.getFdResName()}, e);
8 }
但是在插入重复数据时,报了如下错误:
Caused by: org.postgresql.util.PSQLException: ERROR: current transaction is aborted, commands ignored until end of transaction block
原因是这个类ServiceResource上标记了@Transactional(在没有事务管理的场景下,是可以像上面那样做的):

2017.7.7 postgreSQL在插入造成重复时执行更新的更多相关文章
- 2017.9.15 postgresql批量插入造成冲突后执行更新
参考来自:https://stackoverflow.com/questions/40647600/postgresql-multi-value-upserts/46233907#46233907 1 ...
- 当插入数据失败时,防止mysql自增长字段的自增长的方法
问题描述: 当mysql设置了自增长字段时(注意:一个表中只能设置一个自增长字段,可以不是主键,但必须是键 ),如果插入数据失败,那么自增长字段仍然会占用这个自增长值,再次成功插入数据时就会造成断层. ...
- MYSQL插入处理重复键值的几种方法
当unique列在一个UNIQUE键上插入包含重复值的记录时,默认insert的时候会报1062错误,MYSQL有三种不同的处理方法,下面我们分别介绍. 先建立2个测试表,在id列上创建unique约 ...
- 【转】insert忽略重复、mysql插入操作跳过、插入覆盖覆盖、mysql更新重复
需求背景:一般情况,插入数据的时候,有脏数据的情况,主键重复的话,直接insert into 会报错的,然后下面的sql都不再执行了,如果可以确定后面的数据可以覆盖前面的数据,直接用replace i ...
- sql语句-------重复时插入更新
ON DUPLICATE KEY UPDATE重复时插入更新 insert into user(id,username) value('231',"二人") on duplicat ...
- 跟我一起读postgresql源码(八)——Executor(查询执行模块之——可优化语句的执行)
2.可优化语句的执行 可优化语句的共同特点是它们被查询编译器处理后都会生成査询计划树,这一类语句由执行器(Executor)处理.该模块对外提供了三个接口: ExecutorStart.Executo ...
- 跟我一起读postgresql源码(十)——Executor(查询执行模块之——Scan节点(下))
接前文跟我一起读postgresql源码(九)--Executor(查询执行模块之--Scan节点(上)) ,本篇把剩下的七个Scan节点结束掉. T_SubqueryScanState, T_Fun ...
- 【转】Jmeter中使用CSV Data Set Config参数化不重复数据执行N遍
Jmeter中使用CSV Data Set Config参数化不重复数据执行N遍 要求: 今天要测试上千条数据,且每条数据要求执行多次,(模拟多用户多次抽奖) 1.用户id有175个,且没有任何排序规 ...
- Jmeter===Jmeter中使用CSV Data Set Config参数化不重复数据执行N遍(转)
Jmeter中使用CSV Data Set Config参数化不重复数据执行N遍 要求: 今天要测试上千条数据,且每条数据要求执行多次,(模拟多用户多次抽奖) 1.用户id有175个,且没有任何排序规 ...
随机推荐
- java 复习整理(一 java简介和基础语法)
现在公司用的是封装太多东西的平台开发,觉着之前学的东西很多都忘了,所以想好好总结回顾一下.之前总是想学很多编程语言像python.s6.node.react,但现在越来越体会到编程语言只是一个开发的工 ...
- nginx简易部署
Nginx (engine x) 可作为web反向代理服务器.能够代理外部网络上的主机,访问内部网络 1 首先windows下载nginx :http://nginx.org/download/ngi ...
- noip 2010 三国游戏
三国游戏 三国游戏 描述 小涵很喜欢电脑游戏,这些天他正在玩一个叫做<三国>的游戏. 在游戏中,小涵和计算机各执一方,组建各自的军队进行对战.游戏中共有N 位武将(N为偶数且不小于4),任 ...
- jquery 追加元素的方法(append prepend after before 的区别)
append() 方法在被选元素的结尾插入内容. prepend() 方法在被选元素的开头插入内容. after() 方法在被选元素之后插入内容. before() 方法在被选元素之前插入内容. &l ...
- STM in Haskell
Software Transactional Memory,软件事务内存管理(应该是这么翻译的吧T_T) 类似于数据库的事务,所有的操作都有log,最后验证其他线程是否对数据进行修改,要是有那么就回滚 ...
- PHP命令行执行程序php.exe使用及常用参数
PHP命令行执行程序php.exe参数说明 -f <file>:以命令行方式运行指定的PHP文件,只要指定具体的PHP文件(带绝对路径),php.exe就可以执行PHP文件,所以这个参数单 ...
- python--jinja2
from jinja2 import Template # 创建一个Template模板去渲染它 s = "my name is {{mashiro}}" t = Template ...
- iis日志详解
c-客户端操作.cs-客户端到服务器的操作.sc-服务器到客户端的操作. s-sitename s-computername s-ip cs-method cs-uri-stem cs-uri-que ...
- NYOJ 21.三个水杯-初始态到目标态的最少次数-经典BFS
题目传送门:biubiubiu~ 三个水杯 时间限制:1000 ms | 内存限制:65535 KB 难度:4 描述 给出三个水杯,大小不一,并且只有最大的水杯的水是装满的,其余两个为空杯子. ...
- HDU 1203 【01背包/小数/概率DP】
I NEED A OFFER! Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others) Tot ...