当前位置: 首页 > 知识库问答 >
问题:

服务器重新启动后插入时违反唯一约束

邓昊天
2023-03-14

我运行的是JBoss EAP 7服务器和Oracle 11g数据库,以及Hibernate for JPA。我注意到一些奇怪的事情。当我第一次创建数据库并启动服务器时,一切正常。我从客户端发送请求,服务器将数据保存在数据库中。

如果我重新启动服务器并尝试这样做,我会为每个请求得到一个唯一的违反约束的异常:

java.sql.SQLIntegrityConstraintViolationException: ORA-00001: unique constraint (SCHEMA.SYS_C0010299) violated

at oracle.jdbc.driver.T4CTTIoer.processError(T4CTTIoer.java:447)
at oracle.jdbc.driver.T4CTTIoer.processError(T4CTTIoer.java:396)
at oracle.jdbc.driver.T4C8Oall.processError(T4C8Oall.java:951)
at oracle.jdbc.driver.T4CTTIfun.receive(T4CTTIfun.java:513)
at oracle.jdbc.driver.T4CTTIfun.doRPC(T4CTTIfun.java:227)
at oracle.jdbc.driver.T4C8Oall.doOALL(T4C8Oall.java:531)
at oracle.jdbc.driver.T4CPreparedStatement.doOall8(T4CPreparedStatement.java:208)
at oracle.jdbc.driver.T4CPreparedStatement.executeForRows(T4CPreparedStatement.java:1046)
at oracle.jdbc.driver.OracleStatement.doExecuteWithTimeout(OracleStatement.java:1336)
at oracle.jdbc.driver.OraclePreparedStatement.executeInternal(OraclePreparedStatement.java:3613)
at oracle.jdbc.driver.OraclePreparedStatement.executeUpdate(OraclePreparedStatement.java:3694)
at oracle.jdbc.driver.OraclePreparedStatementWrapper.executeUpdate(OraclePreparedStatementWrapper.java:1354)
at org.jboss.jca.adapters.jdbc.WrappedPreparedStatement.executeUpdate(WrappedPreparedStatement.java:537)
at org.hibernate.engine.jdbc.internal.ResultSetReturnImpl.executeUpdate(ResultSetReturnImpl.java:204)

我用下面的查询检查了sqlplus中的约束。(如果重要的话,我以系统用户的身份运行查询,而不是以服务器的身份运行)。

SELECT A.TABLE_NAME,C.TABLE_NAME,COLUMN_NAME FROM ALL_CONS_COLUMNS A
JOIN ALL_CONSTRAINTS C ON A.CONSTRAINT_NAME = C.CONSTRAINT_NAME
WHERE C.CONSTRAINT_NAME = 'SYS_C0010299';

这似乎发生在我的一个表的主键上。该主键是用序列生成的。

@Id
@Column(name="ID_COL")
@GeneratedValue(strategy=GenerationType.SEQUENCE, generator = "SEQ_NAME_GEN")
@SequenceGenerator(name = "SEQ_NAME_GEN", sequenceName = "SEQ_NAME")
private Long id;

如果我创建了一个新的数据库,那么应用程序在重新启动服务器之前,会再次正常工作。为什么会发生这种情况?

这是一个实体类与另一个实体类的关系:

// other class
@OneToMany(cascade=CascadeType.ALL, mappedBy="otherClass")
@MapKey(name = "mapKey")
private Map<MapKey, ConstraintViolationEntityClass>
    map;

// problematic class (ConstraintViolationEntityClass)
@Column(name = "MAP_KEY")
@Enumerated(EnumType.ORDINAL)
private EnumType enumType;
@ManyToOne
@JoinColumn(name = "OTHER_CLASS_ID", nullable = false)
private OtherClass otherClass;

这是我用来为ConstraintViolationEntityClass创建表的SQL代码:

create table schema.ConstraintViolationEntityTable (
  id_col number(10) not null primary key,
  map_key number(2) not null,
  other_class_id number(10) not null,
  constraint other_class_fk foreign key (other_class_id) references schema.other_class(id)
);

这是我的persistence.xml:

<persistence-unit name="unit1" transaction-type="JTA">
  <jta-data-source>java:jboss/OracleDS</jta-data-source>
  <exclude-unlisted-classes>false</exclude-unlisted-classes>
  <properties>
    <property name="hibernate.transaction.jta.platform" value="org.hibernate.service.jta.platform.internal.JBossStandAloneJtaPlatform"/>
    <property name="hibernate.show_sql" value="true" />
    <property name="hibernate.format_sql" value="true" />
    <property name="hibernate.hbm2ddl.auto" value="validate" />
  </properties>
</persistence-unit>

由于某种原因,成功请求插入的行的某些主键是负数。检查dba_sequences,序列的last_number为 43,即使表中只有 24 行(每个客户端请求添加 12 行)

共有1个答案

屈升
2023-03-14

正如PeterM链接到的答案中所述,序列生成器的默认分配大小是50,这是问题的根本原因,因为您定义了增量为1的序列。我只评论一下负价值的问题。

分配大小为 50(在 SequenceGenerator.allocationSize 中设置)意味着 Hibernate 将:

  • 使用INCREMENT BY 50创建序列(如果允许)
  • 从序列中获取下一个值n
  • n-50开始分配id,直到n
  • 一旦用完数字,重复上面的两个步骤

因为您已经使序列增加了1,所以很容易看出负值来自哪里(以及为什么会违反约束)。如果您尝试插入超过50行,您会遇到约束冲突,而不必重新启动服务器。

 类似资料:
  • 我在创建应用程序时遇到了这个问题。因此,每当我添加第一条评论时,问题都不会出现,但当我第二次尝试时,我会收到此错误: 重复的键值违反了唯一约束“tripplanner_discussion_author_id_key”详细信息:键 (author_id)=(1) 已存在。 我试图把放到 models.py,但它根本没有帮助。 models.py views.py 更新 当我登录到另一个用户时,一个

  • 如果存在,上面的代码通过按用户名搜索来获取用户,如果不存在,则创建一个新对象,并更新其属性并将其保存回数据库。 理想情况下,该代码应该处理对象已经存在于数据库中的情况。但它抛出了以下错误: 我不明白这是为什么。在互联网上搜索,发现这可能是因为指数被破坏,并已重置序列,但无法找到确切的原因和解决方案。请帮我做这件事。预先感谢

  • 当并发客户机试图将数据插入子表时,我们面临唯一的约束冲突问题。 假设我们有1以下的表格。用户user_id、first_name、last_name。2.项目project_idproject_name和project_description。 两者都有着多对多的关系。 当两个客户端试图创建一个新用户时。假设client1创建了user1(id=aa1),子记录项目(id=1)。Client2还创

  • 这是我的stacktrace: 学生表: 学生实体:学生标识默认为自动递增 postgres控制台(这些学生由sql脚本创建): 在此处输入图像描述 我也尝试过这样生成,但这没有帮助 我用postgreql它似乎我有问题与id Generator,谢谢你的想法和答案

  • 我在django应用程序中创建了一个模型,并从pgadmin将数据填充到表中,但现在当我试图从应用程序创建记录时,它抛出了这个完整性错误: 重复的键值违反了唯一约束“packsapp_foo_pkey” 详细信息:键(id)=(4)已经存在。 这是models.py 我是否总是必须从应用程序本身插入数据? Views.py