V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
V2EX 提问指南
jerryfu
V2EX  ›  问与答

求教 JPA 一个很奇怪的问题

  •  
  •   jerryfu · 2018-12-10 13:12:47 +08:00 · 2087 次点击
    这是一个创建于 2177 天前的主题,其中的信息可能已经有所发展或是发生改变。

    前几天在做爬虫项目时

    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

    6 条回复    2018-12-10 14:45:58 +08:00
    ywcjxf1515
        1
    ywcjxf1515  
       2018-12-10 13:37:48 +08:00 via iPad
    把实体类( Entity )中使用注解的主键策略改一下试一试
    jerryfu
        2
    jerryfu  
    OP
       2018-12-10 13:47:18 +08:00
    @ywcjxf1515 我实体类对应的字段只加了个 @Id 注解,没有加主键生成策略,出发点是想自己维护主键 ID,这样设置应该没问题的吧?
    johnniang
        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));
    }
    ```
    ywcjxf1515
        4
    ywcjxf1515  
       2018-12-10 14:09:10 +08:00 via iPad
    很奇怪我数据库是 PostgreSql (不是跑你这个项目),主键是表自己生成,但是第一项是的 id 是 1,而不是 0。我 ORM 我用的是 Hibernate,使用的 JPA 注解,也就是实体类的注解和你是相似的。一开始我用的是 Hibernate 的映射文件,而不是注解,一直改主键策略,最终映射文件中选的是 sequence,然后换成注解,不使用映射文件,然后主键策略选 sequence,不行。还有你的.sql 文件中,向数据库中插入记录,为什么又把主键也插入了,不是应该让表自己生成嘛。
    johnniang
        5
    johnniang  
       2018-12-10 14:14:36 +08:00
    @johnniang 我来解释一下,在调用 save(entity)方法的时候,jpa 默认实现会判断这个 entity 是否为新的 entity,如果为新的,则创建该 entity,否则更新该 entity,上述代码最终判断出 0 为新的 entity,所以将会创建新的 entity,此时数据库中已经存在了 id 为 0 的数据,所以才会出现题者描述的错误。
    alvinbone88
        6
    alvinbone88  
       2018-12-10 14:45:58 +08:00
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   1174 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 23ms · UTC 23:05 · PVG 07:05 · LAX 15:05 · JFK 18:05
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.