简体   繁体   English

2 使用不同 hibernate 版本但相同 oracle 数据库的应用程序抛出唯一约束错误

[英]2 Applications using different hibernate versions but same oracle database throwing unique constraint error

There are 2 applications: one is using Spring boot - 1.5.18.Release version, which has hibernate version as 5.0.12.Final有2个应用:一个是使用Spring boot - 1.5.18.Release版本,其中hibernate版本为5.0.12.Final

: https://search.maven.org/artifact/org.springframework.boot/spring-boot-dependencies/1.5.18.RELEASE/pom https://search.maven.org/artifact/org.springframework.boot/spring-boot-dependencies/1.5.18.RELEASE/pom

and another application is using Spring boot - 2.4.1 version which has hibernate version as 5.4.25.Final: https://search.maven.org/artifact/org.springframework.boot/spring-boot-dependencies/2.4.1/pom where we have used @SequenceGenerator(name = "sequenceGenerator", sequenceName = "ABCD_SEQ",allocationSize = 1), and another application is using Spring boot - 2.4.1 version which has hibernate version as 5.4.25.Final: https://search.maven.org/artifact/org.springframework.boot/spring-boot-dependencies/2.4.1 /pom我们使用了@SequenceGenerator(name = "sequenceGenerator", sequenceName = "ABCD_SEQ",allocationSize = 1),

The allocation size is required because the application does not starts up分配大小是必需的,因为应用程序没有启动

while the allocation size was not required in first application.而第一次申请时不需要分配大小。

Database sequence is created with "INCREMENT BY 1" and same oracle database is used by both applications.数据库序列是使用“INCREMENT BY 1”创建的,并且两个应用程序都使用相同的 oracle 数据库。

The 2 applications uses many similar entity which is copied in another application/project.这两个应用程序使用了许多类似的实体,这些实体被复制到另一个应用程序/项目中。

But when inserting record from the second application where spring-boot is 2.4.1, we are getting unique sequence generator issue.但是当从 spring-boot 为 2.4.1 的第二个应用程序插入记录时,我们遇到了唯一的序列生成器问题。

When analysed, we found out that the first application(1.5.18.Release) is abruptly incrementing the sequence although it should increment it by 1, leaving lot of gaps in between, sometimes by 50, 100, etc. and when second application(2.4.1) tries to insert record, there is error of unique constraint.分析时,我们发现第一个应用程序(1.5.18.Release)突然增加序列,尽管它应该增加 1,在两者之间留下很多间隙,有时是 50、100 等,当第二个应用程序( 2.4.1) 尝试插入记录,出现唯一约束错误。

Please help, exactly where to search for the root cause, or how the hibernate cache mechanism is used this case?请帮忙,究竟在哪里寻找根本原因,或者这种情况下如何使用hibernate缓存机制?

One of the entity in first application (1.5.18.Release)第一个应用程序中的一个实体(1.5.18.Release)

@Entity
@Table(name = "MERCURY_INSTANCE")
public class MercuryInstance implements Serializable {

    @Id
    @Column(name = "MERCURY_INSTANCE_KEY", nullable = false)
    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "seqGen")
    @SequenceGenerator(name = "seqGen", sequenceName = "MERCURY_INSTANCE_SEQ")
    private Long mercuryInstanceKey;

    @ManyToOne(cascade = CascadeType.DETACH, fetch = FetchType.LAZY)
    @JoinColumn(name = "MERCURY_KEY", referencedColumnName = "MERCURY_KEY", nullable = false)
    private MERCURY mercury;

    @OneToOne(cascade = CascadeType.ALL, fetch = FetchType.EAGER)
    @JoinColumn(name = "MERCURY_INSTANCE_KEY", referencedColumnName = "MERCURY_INSTANCE_KEY", nullable = false)
    private MercuryInstanceTechParams MercuryInstanceTechParams;

    @ManyToMany(mappedBy = "mercuryGroupInstances")
    private List<MercuryGroupInstance> MercuryGroupInstances;
    
    @Column(name = "CREATED_DATE")
    private Timestamp createdDte;
    @Column(name = "CREATED_BY")
    private String createdBy;
    @Column(name = "UPDATED_DATE")
    private Timestamp updatedDte;
    @Column(name = "UPDATED_BY")
    private String updatedBy;
    /* getter and setters of above fields */

}

While another application(2.4.1) is similar, only difference is the sequence generator such as:虽然另一个应用程序(2.4.1)是相似的,但唯一的区别是序列生成器,例如:

@Id
@Column(name = "MERCURY_INSTANCE_KEY", nullable = false)
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "seqGen")
@SequenceGenerator(name = "seqGen", sequenceName = "MERCURY_INSTANCE_SEQ", allocationSize = 1)
private Long mercuryInstanceKey;

and the database sequence is:数据库序列为:

CREATE SEQUENCE "MERCURY_INSTANCE_SEQ" MINVALUE 1 MAXVALUE 9999999999999999999999999999 INCREMENT BY 1 START WITH 55 NOCACHE NOORDER NOCYCLE; CREATE SEQUENCE "MERCURY_INSTANCE_SEQ" MINVALUE 1 MAXVALUE 9999999999999999999999999999 INCREMENT BY 1 START WITH 55 NOCACHE NOORDER NOCYCLE;

@SequenceGenerator has an allocation size of 50 by default. @SequenceGenerator默认分配大小为 50。 First of all, it is a best practice to align your allocation size with INCREMENT BY value in your db sequence .首先,最佳实践是将分配大小与 db sequence 中的INCREMENT BY值对齐

This value tends to depend on whether your application is read or write intensive.该值往往取决于您的应用程序是读取密集型还是写入密集型。 In addition you have to think also about performance(if it often writes to db, lower values may cause performance issues).此外,您还必须考虑性能(如果它经常写入数据库,较低的值可能会导致性能问题)。 In case your application is a read only application then the impact of using allocation size 1000 or 1 is negligible.如果您的应用程序是只读应用程序,则使用分配大小 1000 或 1 的影响可以忽略不计。

Next generation of Sequence Id is based on allocationSize.下一代Sequence Id 基于allocationSize。

So for instance, the first app requests ids from 1-50 and the second one is asking every time there is an insert.因此,例如,第一个应用程序请求 1-50 的 id,而第二个应用程序在每次插入时都询问。 In this case the ids from 1-50 are going to be used by the first application, but then the second app requests an id and will be given an id within the range of 1-50 (since INCREMENT BY=1 ).在这种情况下,第一个应用程序将使用 1-50 的 id,但随后第二个应用程序请求一个 id 并将获得一个 1-50 范围内的 id(因为INCREMENT BY=1 )。 This results in an exception for which ever app is going to save second with the same id.这会导致任何应用程序将使用相同的 id 保存第二个异常。

So, the easiest solution would be to change:因此,最简单的解决方案是更改:

@SequenceGenerator(name = "seqGen", sequenceName = "MERCURY_INSTANCE_SEQ")

of the first app to:第一个应用程序到:

@SequenceGenerator(name = "seqGen", sequenceName = "MERCURY_INSTANCE_SEQ", allocationsize=1)

'allocationSize' doesn't mean that the entities ids will increase by this value but it is a number after which the database query will be made again to get the next database sequence value. 'allocationSize'并不意味着实体 id 会增加这个值,而是一个数字,之后将再次进行数据库查询以获得下一个数据库序列值。 On the application side, ids for an entities instances will always increase by 1 unless we reach the allocationSize limit.在应用程序方面,实体实例的 id 将始终增加 1,除非我们达到 allocationSize 限制。 After 'allocationSize' is reached, the next id will be retrieved from the database sequence again.达到“allocationSize”后,将再次从数据库序列中检索下一个 id。 In case if application restarts or redeployed before allocationSize limit is reached, we will see a one-time jump in the next value.如果应用程序在达到 allocationSize 限制之前重新启动或重新部署,我们将看到下一个值的一次性跳跃。 'allocationSize' is to improve performance. 'allocationSize' 是为了提高性能。

In your first scenario: The sequence generator is consistent.在您的第一个场景中:序列生成器是一致的。 It's only task is to generate unique integer values, nothing else.唯一的任务是生成唯一的 integer 值,仅此而已。 As mentioned this behaviour is caused by oracle caching, pre-allocating, the sequences numbers (20 by default).如前所述,此行为是由 oracle 缓存、预分配序列号(默认为 20)引起的。 The ID column is an surrogate/artificial primary key and only used to uniquely identify the row, no information whatsoever should be derived from it. ID 列是代理/人工主键,仅用于唯一标识行,不应从中派生任何信息。 Even if you don't cache the sequence number you will never get an uninterrupted series of ID's due to rolled back transactions, deletes, application and database server restarts.即使您不缓存序列号,您也永远不会因为回滚事务、删除、应用程序和数据库服务器重新启动而获得不间断的一系列 ID。 And not caching sequences has a heavy performance penalty on high volume transaction system.并且不缓存序列会对大容量事务系统造成严重的性能损失。

In your second scenario: try putting SequenceGenerator on the top of your class to make hibernate pick up correct sequqnce.在第二种情况下:尝试将 SequenceGenerator 放在 class 的顶部,以使 hibernate 拾取正确的序列。

@Entity
@Table(name = "{your_table_name}")
@SequenceGenerator(name = "seqGen", sequenceName = "MERCURY_INSTANCE_SEQ", allocationSize = 1)
public class {$your class name$} {


@Id
@Column(name = "MERCURY_INSTANCE_KEY", nullable = false)
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "seqGen")
private Long mercuryInstanceKey;

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 使用 Java 和 oracle 数据库的奇怪的唯一约束错误 - Strange unique constraint error using Java and an oracle database 使用 hibernate 在不同的应用程序上更新同一个表 - Updating the same table on the different applications using hibernate 尝试使用休眠模式将数据插入数据库时​​出错。 错误是约束违例异常(使用Oracle DB) - Error while trying to insert data into database using hibernate. error is Constraint Violation exception (using Oracle DB) 使用Hibernate从两个不同的Web应用程序(GXT)连接同一数据库 - Connecting the same database from two different web applications(GXT) using Hibernate 同一个数据库的不同应用 - Different applications to the same database 使用Hibernate将两个或多个应用程序连接到同一个数据库 - Connect two or more applications to the same database using Hibernate 在Hibernate JPA2上使用唯一约束 - Using unique constraint on Hibernate JPA2 HIBERNATE抛出错误:“在更新对象时,“具有相同标识符值的另一个对象已与该会话关联”” - HIBERNATE Throwing ERROR:“a different object with the same identifier value was already associated with the session ”, while Updating the object Hibernate:在同一个应用程序中使用两个不同的DataBase模式 - Hibernate: Using two different DataBase schemas in the same application 由于 schema.sql 和休眠导致的唯一约束错误 - Unique constraint error due to schema.sql and hibernate
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM