spring-data-jpa - java.sql.SQLIntegrityConstraintViolationException:更新时键“日期”的重复条目“2020-05-29”
问题描述
无法更新数据库中的记录,它尝试插入新记录,但由于唯一约束而引发错误
我有如下实体,
@Setter
@Getter
@Audited
@Entity
@Accessors(chain = true)
@EqualsAndHashCode
@NoArgsConstructor
@AllArgsConstructor
@EntityListeners(AuditingEntityListener.class)
public class Sum {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private long id;
// Date
@Column(nullable = false, unique = true)
private Date date;
// Sum of won
@Column(nullable = false, scale = 2)
private BigDecimal won;
@CreatedDate
private Date createdDateTime;
}
使用 flyway 脚本创建 db 表,如下所示,
CREATE TABLE `sum` (
`id` bigint NOT NULL AUTO_INCREMENT,
`date` date NOT NULL UNIQUE,
`won` numeric(28,2) NOT NULL,
`created_date_time` datetime NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
CREATE TABLE `sum_aud` (
`id` bigint NOT NULL AUTO_INCREMENT,
`rev` int(11) NOT NULL UNIQUE,
`revtype` tinyint(4) DEFAULT NULL,
`date` date NOT NULL unique,
`won` numeric(28,2) NOT NULL,
`created_date_time` datetime NOT NULL,
PRIMARY KEY (`id`,`rev`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
CREATE TABLE `revinfo` (
`rev` int(11) NOT NULL AUTO_INCREMENT,
`revtstmp` bigint(20) DEFAULT NULL,
PRIMARY KEY (`rev`)
) ENGINE=InnoDB AUTO_INCREMENT=40 DEFAULT CHARSET=latin1;
jpaRepository 如下,
public interface SumRepository extends PagingAndSortingRepository<Sum,Long> {
@Query("select t from Sum t where t.date = ?1")
Iterable<Sum> findByDate(Date previousDate);
}
我正在尝试按如下方式插入/更新记录,
public void saveSum(Sum sumObj) {
// update if exist already
Iterable<Sum> Sums = getDBRecord(Sum.getDate());
Iterator it = Sums.iterator();
if (it.hasNext()) {
Sum existingRecord = (Sum) it.next();
existingRecord
.setCreatedDateTime(sumObj.getCreatedDateTime())
.setWon(sumObj.getWon());
sumRepository.save(existingRecord);
} else
sumRepository.save(sumObj);
}
但是,如果我尝试为现有记录设置任何属性,则会引发以下错误,
java.sql.SQLIntegrityConstraintViolationException: Duplicate entry '2020-05-29' for key 'date'
at com.mysql.cj.jdbc.exceptions.SQLError.createSQLException(SQLError.java:117)
at com.mysql.cj.jdbc.exceptions.SQLError.createSQLException(SQLError.java:97)
at com.mysql.cj.jdbc.exceptions.SQLExceptionsMapping.translateException(SQLExceptionsMapping.java:122)
at com.mysql.cj.jdbc.ClientPreparedStatement.executeInternal(ClientPreparedStatement.java:955)
at com.mysql.cj.jdbc.ClientPreparedStatement.executeUpdateInternal(ClientPreparedStatement.java:1094)
at com.mysql.cj.jdbc.ClientPreparedStatement.executeUpdateInternal(ClientPreparedStatement.java:1042)
at com.mysql.cj.jdbc.ClientPreparedStatement.executeLargeUpdate(ClientPreparedStatement.java:1345)
at com.mysql.cj.jdbc.ClientPreparedStatement.executeUpdate(ClientPreparedStatement.java:1027)
at com.zaxxer.hikari.pool.ProxyPreparedStatement.executeUpdate(ProxyPreparedStatement.java:61)
at com.zaxxer.hikari.pool.HikariProxyPreparedStatement.executeUpdate(HikariProxyPreparedStatement.java)
at org.hibernate.engine.jdbc.internal.ResultSetReturnImpl.executeUpdate(ResultSetReturnImpl.java:197)
at org.hibernate.persister.entity.AbstractEntityPersister.insert(AbstractEntityPersister.java:3238)
at org.hibernate.persister.entity.AbstractEntityPersister.insert(AbstractEntityPersister.java:3763)
at org.hibernate.action.internal.EntityInsertAction.execute(EntityInsertAction.java:107)
at org.hibernate.engine.spi.ActionQueue.executeActions(ActionQueue.java:604)
at org.hibernate.engine.spi.ActionQueue.lambda$executeActions$1(ActionQueue.java:478)
at java.base/java.util.LinkedHashMap.forEach(LinkedHashMap.java:684)
at org.hibernate.engine.spi.ActionQueue.executeActions(ActionQueue.java:475)
at org.hibernate.event.internal.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:348)
at org.hibernate.event.internal.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:40)
at org.hibernate.event.service.internal.EventListenerGroupImpl.fireEventOnEachListener(EventListenerGroupImpl.java:102)
at org.hibernate.internal.SessionImpl.doFlush(SessionImpl.java:1360)
at org.hibernate.internal.SessionImpl.flush(SessionImpl.java:1347)
at org.hibernate.envers.internal.synchronization.AuditProcess.doBeforeTransactionCompletion(AuditProcess.java:177)
at org.hibernate.envers.internal.synchronization.AuditProcessManager$1.doBeforeTransactionCompletion(AuditProcessManager.java:47)
at org.hibernate.engine.spi.ActionQueue$BeforeTransactionCompletionProcessQueue.beforeTransactionCompletion(ActionQueue.java:954)
at org.hibernate.engine.spi.ActionQueue.beforeTransactionCompletion(ActionQueue.java:525)
at org.hibernate.internal.SessionImpl.beforeTransactionCompletion(SessionImpl.java:2379)
at org.hibernate.engine.jdbc.internal.JdbcCoordinatorImpl.beforeTransactionCompletion(JdbcCoordinatorImpl.java:447)
at org.hibernate.resource.transaction.backend.jdbc.internal.JdbcResourceLocalTransactionCoordinatorImpl.beforeCompletionCallback(JdbcResourceLocalTransactionCoordinatorImpl.java:183)
at org.hibernate.resource.transaction.backend.jdbc.internal.JdbcResourceLocalTransactionCoordinatorImpl.access$300(JdbcResourceLocalTransactionCoordinatorImpl.java:40)
at org.hibernate.resource.transaction.backend.jdbc.internal.JdbcResourceLocalTransactionCoordinatorImpl$TransactionDriverControlImpl.commit(JdbcResourceLocalTransactionCoordinatorImpl.java:281)
at org.hibernate.engine.transaction.internal.TransactionImpl.commit(TransactionImpl.java:101)
我不明白为什么它不持久化一个对象来更新它,而是尝试创建一个新的对象来插入,我也可以在上面的日志中看到 ResultSetReturnImpl.executeUpdate 方法被调用然后为什么它给唯一键错误
有人知道吗?我试图搜索与此相关的许多问题,但找不到任何有用的信息。现在有点卡住了。
解决方案
推荐阅读
- firebase - firebase 可调用函数返回 CORS 错误且未从客户端调用
- angular - Angular 9:从 fonts.google.com 导入的 SCSS 在生产模式下不起作用
- json - Cypress:是否可以从 json 文件中获取整个 json 数据,放置在 fixtures 文件夹中并将其内容粘贴到 textarea 中?
- django - Django 模板中的 ' 等字符。可能是unicode错误
- c - 取消引用 void * 就像 (int) - 标准做法?
- git - 如何将一个提交从一个远程分支推送到另一个远程分支
- android - android中的活动最小化
- wordpress - 按 2 个自定义字段排序。一个字段有时是空的
- colors - 常用于暗物质模拟的颜色图
- azure-devops - 在将任务标记为“完成”之前,我是否需要将任务的剩余小时数更改为零?