求教 JPA 一个很奇怪的问题

2018-12-10 13:12:47 +08:00
 jerryfu

前几天在做爬虫项目时

https://www.v2ex.com/t/515687

发现一个很奇怪的问题。

项目使用 springboot 配合 jpa 进行开发。使用 jpa 取 id 为 0 的记录进行更新时会报 Duplicate entry '0' for key 'PRIMARY',更新其他记录就没有任何问题。

更新的语句大概是这样的:

service 是这么写的:

dao 是这样的:

这是数据库表结构:

这是那条会报错的 id 为 0 的记录

谷歌百度找了半天没找到解决方法,也不知道为么会报主键重复冲突,我明明只是进行更新操作,不是进行插入操作。我把 id 为 0 的记录删掉或者把它的 id 改为一个非零的其他值,程序便不会报错误。

很是不能理解,是不是更新方法写的有问题?求指点,谢谢。

项目的地址是: https://github.com/jrhu05/jerryWebSpider

1925 次点击
所在节点    问与答
6 条回复
ywcjxf1515
2018-12-10 13:37:48 +08:00
把实体类( Entity )中使用注解的主键策略改一下试一试
jerryfu
2018-12-10 13:47:18 +08:00
@ywcjxf1515 我实体类对应的字段只加了个 @Id 注解,没有加主键生成策略,出发点是想自己维护主键 ID,这样设置应该没问题的吧?
johnniang
2018-12-10 14:08:08 +08:00
org.springframework.data.repository.core.support.AbstractEntityInformation

```java
/*
* (non-Javadoc)
* @see org.springframework.data.repository.core.EntityInformation#isNew(java.lang.Object)
*/
public boolean isNew(T entity) {

ID id = getId(entity);
Class<ID> idType = getIdType();

if (!idType.isPrimitive()) {
return id == null;
}

if (id instanceof Number) {
return ((Number) id).longValue() == 0L;
}

throw new IllegalArgumentException(String.format("Unsupported primitive id type %s!", idType));
}
```
ywcjxf1515
2018-12-10 14:09:10 +08:00
很奇怪我数据库是 PostgreSql (不是跑你这个项目),主键是表自己生成,但是第一项是的 id 是 1,而不是 0。我 ORM 我用的是 Hibernate,使用的 JPA 注解,也就是实体类的注解和你是相似的。一开始我用的是 Hibernate 的映射文件,而不是注解,一直改主键策略,最终映射文件中选的是 sequence,然后换成注解,不使用映射文件,然后主键策略选 sequence,不行。还有你的.sql 文件中,向数据库中插入记录,为什么又把主键也插入了,不是应该让表自己生成嘛。
johnniang
2018-12-10 14:14:36 +08:00
@johnniang 我来解释一下,在调用 save(entity)方法的时候,jpa 默认实现会判断这个 entity 是否为新的 entity,如果为新的,则创建该 entity,否则更新该 entity,上述代码最终判断出 0 为新的 entity,所以将会创建新的 entity,此时数据库中已经存在了 id 为 0 的数据,所以才会出现题者描述的错误。
alvinbone88
2018-12-10 14:45:58 +08:00

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/516088

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX