参考来自: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在插入造成重复时执行更新的更多相关文章

  1. 2017.9.15 postgresql批量插入造成冲突后执行更新

    参考来自:https://stackoverflow.com/questions/40647600/postgresql-multi-value-upserts/46233907#46233907 1 ...

  2. 当插入数据失败时,防止mysql自增长字段的自增长的方法

    问题描述: 当mysql设置了自增长字段时(注意:一个表中只能设置一个自增长字段,可以不是主键,但必须是键 ),如果插入数据失败,那么自增长字段仍然会占用这个自增长值,再次成功插入数据时就会造成断层. ...

  3. MYSQL插入处理重复键值的几种方法

    当unique列在一个UNIQUE键上插入包含重复值的记录时,默认insert的时候会报1062错误,MYSQL有三种不同的处理方法,下面我们分别介绍. 先建立2个测试表,在id列上创建unique约 ...

  4. 【转】insert忽略重复、mysql插入操作跳过、插入覆盖覆盖、mysql更新重复

    需求背景:一般情况,插入数据的时候,有脏数据的情况,主键重复的话,直接insert into 会报错的,然后下面的sql都不再执行了,如果可以确定后面的数据可以覆盖前面的数据,直接用replace i ...

  5. sql语句-------重复时插入更新

    ON DUPLICATE KEY UPDATE重复时插入更新 insert into user(id,username) value('231',"二人") on duplicat ...

  6. 跟我一起读postgresql源码(八)——Executor(查询执行模块之——可优化语句的执行)

    2.可优化语句的执行 可优化语句的共同特点是它们被查询编译器处理后都会生成査询计划树,这一类语句由执行器(Executor)处理.该模块对外提供了三个接口: ExecutorStart.Executo ...

  7. 跟我一起读postgresql源码(十)——Executor(查询执行模块之——Scan节点(下))

    接前文跟我一起读postgresql源码(九)--Executor(查询执行模块之--Scan节点(上)) ,本篇把剩下的七个Scan节点结束掉. T_SubqueryScanState, T_Fun ...

  8. 【转】Jmeter中使用CSV Data Set Config参数化不重复数据执行N遍

    Jmeter中使用CSV Data Set Config参数化不重复数据执行N遍 要求: 今天要测试上千条数据,且每条数据要求执行多次,(模拟多用户多次抽奖) 1.用户id有175个,且没有任何排序规 ...

  9. Jmeter===Jmeter中使用CSV Data Set Config参数化不重复数据执行N遍(转)

    Jmeter中使用CSV Data Set Config参数化不重复数据执行N遍 要求: 今天要测试上千条数据,且每条数据要求执行多次,(模拟多用户多次抽奖) 1.用户id有175个,且没有任何排序规 ...

随机推荐

  1. mvvm实现

    https://segmentfault.com/a/1190000006599500 http://blog.csdn.net/pur_e/article/details/53066275

  2. 牛客~~wannafly挑战赛19~A 队列

    链接:https://www.nowcoder.com/acm/contest/131/A来源:牛客网 题目描述 ZZT 创造了一个队列 Q.这个队列包含了 N 个元素,队列中的第 i 个元素用 Qi ...

  3. 插件安装:包管理器——Package Control

    首先,按CTRL+`,打开控制台   粘贴下面的代码,之后回车 如果是sublime3 ? 1 import urllib.request,os,hashlib; h = '7183a2d3e96f1 ...

  4. 行为型设计模式之中介者模式(Mediator)

    结构 意图 用一个中介对象来封装一系列的对象交互.中介者使各对象不需要显式地相互引用,从而使其耦合松散,而且可以独立地改变它们之间的交互. 适用性 一组对象以定义良好但是复杂的方式进行通信.产生的相互 ...

  5. 【原创】Linux环境下的图形系统和AMD R600显卡编程(8)——AMD显卡DRM驱动初始化过程

    前面几个blog对DRM驱动.显卡的显存管理机制.中断机制都进行了一些描述,现在阅读AMD drm驱动的初始化过程应该会轻松许多. 下面是一AMD的开发人员编写的文章(先暂时放在这里,后续有时间再添加 ...

  6. List的set和add方法

    问题描述:[相机]打开记录拍摄地理位置后拍照详情中少“宽度”属性; 原因分析:在listview动态刷新时用set(index,elemet)方法替换了宽度及其值: 解决方法:改为add(index, ...

  7. VirtualBox虚拟机安装CentOS 7

    新建虚拟机 因为比较简单,所以对于VirtualBox就不做过多介绍了,直接下载安装即可,安装好之后打开Oracle VM VirtualBox管理器,点击新建,选择Red Hat(根据windows ...

  8. HDU 5886 Tower Defence(2016青岛网络赛 I题,树的直径 + DP)

    题目链接  2016 Qingdao Online Problem I 题意  在一棵给定的树上删掉一条边,求剩下两棵树的树的直径中较长那的那个长度的期望,答案乘上$n-1$后输出. 先把原来那棵树的 ...

  9. bzoj 1067: [SCOI2007]降雨量

    题目链接: bzoj 1067: [SCOI2007]降雨量 题解: 很简单的一道题,但代码里有许多细节需要注意,切容易出错,调了三个小时OTZ 做一个st表维护区间最大值就 在获得年份在序列中的po ...

  10. linux安装mysql数据库(5.7之前的版本)

    到mysql官网下载mysql编译好的二进制安装包   解压32位安装包: 进入安装包所在目录,执行命令:tar mysql-5.6.17-linux-glibc2.5-i686.tar.gz   复 ...