前几天在做爬虫项目时
发现一个很奇怪的问题。
项目使用 springboot 配合 jpa 进行开发。使用 jpa 取 id 为 0 的记录进行更新时会报 Duplicate entry '0' for key 'PRIMARY',更新其他记录就没有任何问题。
更新的语句大概是这样的:
service 是这么写的:
dao 是这样的:
这是数据库表结构:
这是那条会报错的 id 为 0 的记录
谷歌百度找了半天没找到解决方法,也不知道为么会报主键重复冲突,我明明只是进行更新操作,不是进行插入操作。我把 id 为 0 的记录删掉或者把它的 id 改为一个非零的其他值,程序便不会报错误。
很是不能理解,是不是更新方法写的有问题?求指点,谢谢。
1
ywcjxf1515 2018-12-10 13:37:48 +08:00 via iPad
把实体类( Entity )中使用注解的主键策略改一下试一试
|
2
jerryfu OP @ywcjxf1515 我实体类对应的字段只加了个 @Id 注解,没有加主键生成策略,出发点是想自己维护主键 ID,这样设置应该没问题的吧?
|
3
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)); } ``` |
4
ywcjxf1515 2018-12-10 14:09:10 +08:00 via iPad
很奇怪我数据库是 PostgreSql (不是跑你这个项目),主键是表自己生成,但是第一项是的 id 是 1,而不是 0。我 ORM 我用的是 Hibernate,使用的 JPA 注解,也就是实体类的注解和你是相似的。一开始我用的是 Hibernate 的映射文件,而不是注解,一直改主键策略,最终映射文件中选的是 sequence,然后换成注解,不使用映射文件,然后主键策略选 sequence,不行。还有你的.sql 文件中,向数据库中插入记录,为什么又把主键也插入了,不是应该让表自己生成嘛。
|
5
johnniang 2018-12-10 14:14:36 +08:00
@johnniang 我来解释一下,在调用 save(entity)方法的时候,jpa 默认实现会判断这个 entity 是否为新的 entity,如果为新的,则创建该 entity,否则更新该 entity,上述代码最终判断出 0 为新的 entity,所以将会创建新的 entity,此时数据库中已经存在了 id 为 0 的数据,所以才会出现题者描述的错误。
|
6
alvinbone88 2018-12-10 14:45:58 +08:00
建议去看文档,Persistence Context 部分
http://docs.jboss.org/hibernate/orm/current/userguide/html_single/Hibernate_User_Guide.html#pc |