Hibernate在插入一定数量的记录后会生成负数ID

3

我的应用程序中的Hibernate(3.6.1.Final)表现很奇怪,我现在非常绝望。这种行为在MariaDB 10.1和Amazon RDS上都会发生。

在一定数量的成功持久化操作之后(大约总共5k次),Hibernate会触发一个:

SQLIntegrityConstraintViolationException: Cannot add or update a child row: a foreign key constraint fails

根据堆栈跟踪,Hibernate试图将实体中的外键填充为一个负值,从而违反了FK约束( FK的目标表没有这样的主键值)。
奇怪的是:
  • 仅在成功持续约5k次后才会发生
  • 提交此类数量的持久操作后,即使重新启动应用程序(以及数据库),也会发生错误。唯一的解决方法是清除数据库并重复。
  • 无论负载是连续的、批处理的、单线程的还是多线程的都会出现错误。
以下是在插入期间违反的实体的FK:
    @Entity
    @Cacheable
    @Cache(usage = CacheConcurrencyStrategy.READ_WRITE)
    public class Charge extends Entry {

        @OneToOne(cascade = CascadeType.ALL)
        @JoinColumn(name = "totalId")
        private Amount total;
     //....

以下是 Amount 实体中主键的定义:

     @GeneratedValue
     @Id
     @Column(nullable = false)
     private Integer pk;
     //....

我的问题是:

  • 为什么FK会出现无效的负值?(被FK指向的主键设置为自动增量,从1开始,之前的所有插入都按照这个规则完美执行)
  • 为什么错误只在大约5k次持久化后才发生?
  • 为什么即使重新启动应用程序也无法解决问题?数据库没问题,因为在应用程序外手动插入有效的FK值可以正常工作。

我怀疑是Hibernate以及它如何管理DB上的自动增量。有很多关于这个主题的帖子,但没有一个符合我的特定情况(只有在一定使用量后才出现错误)。

最后注意:在DB上,auto_increment最初设置为1。在错误出现之前的所有初始持久性(Amount实体)都具有从1开始的递增PK:(1,2,3,...)。那么,为什么在一段时间后Hibernate会出现负数(与FK不兼容)?

非常感谢您的帮助。

最好 G.


在数据库端如何定义主键? - Arnaud
什么负值?-1吗?还是一些随机的负值?绝对值是否与任何现有的外键匹配? - Dragan Bozanovic
Amount 表在数据库中的主键定义如下:pk int(11) NOT NULL AUTO_INCREMENT, - user2248614
负值是一个非常高的负数,大约是-32656或类似的数字。 - user2248614
2个回答

2
也许是int类型的限制吗?
尝试这个:
@Id
@GeneratedValue (strategy = GenerationType.AUTO)
@Column (name = "id")
private long id;

据我所见,在源代码中,默认策略已经是自动的,而且5k仍然在整数范围内,自动装箱可能会抛出npe而不是产生奇怪的负值。请参考以下链接:https://github.com/hibernate/hibernate-jpa-api/blob/master/src/main/java/javax/persistence/GeneratedValue.java - HRgiger
但我同意这值得长时间尝试。 - HRgiger
抱歉,我无法帮忙,这很奇怪 : ( - Yiao SUN

0

我们曾经遇到过完全相同的问题,原因是使用了旧版的Mariadb JDBC驱动程序。我们当时使用的是1.4.2版本。在切换到Mariadb JDBC驱动程序的1.5.5版本后,问题得到了解决。


这是MariaDB Connector-J项目的相关错误报告 https://jira.mariadb.org/browse/CONJ-284 - Ramil Israfilov

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接