【问题标题】:GeneratedValue counter for Id resets every time that the server and client are executed每次执行服务器和客户端时,Id 的 GeneratedValue 计数器都会重置
【发布时间】:2015-02-28 07:13:09
【问题描述】:

我正在开发一个带有 EJB 和 JPA 的 JavaEE 应用程序。

我的实体是这样定义的,例如:

@Entity
public class Utente implements Serializable {

@Id
@GeneratedValue
private int cod_utente;
private String nome_utente;
private String morada_utente;
@Temporal(TemporalType.DATE)
private GregorianCalendar dnasc_utente;
private int tel_utente;
private List<GregorianCalendar> agenda;
@OneToMany
@JoinColumn(nullable=true)
private List<Prescricao> lista_presc;

当我创建实体Utente 时,键是从一个开始按顺序生成的。如果我关闭客户端和服务器并再次执行它们,则重新建立密钥生成器的“计数器”。这会导致错误,因为应用程序将尝试使用主键“1”创建另一个 Utente

有人可以帮我解决这个问题吗?

【问题讨论】:

  • AFAIK 它应该可以工作。您是否尝试过手动设置不同的生成策略?
  • 顺便说一句,哪个 JPA 提供商?哪个数据库系统? JPA 属性是否设置为该方言?
  • 我正在使用 glassfish。 JPA 提供程序是 EclipseLink

标签: jpa eclipselink primary-key generated


【解决方案1】:

代码:

@Id
@GeneratedValue
private int cod_utente;

没有设置特定的策略来生成 ID 的值。

和这段代码一样:

@Id
@GeneratedValue(strategy=GenerationType.AUTO)
private int cod_utente;

GenerationType.AUTO 表示持久性提供程序(在 Glassfish 中,默认持久性提供程序是 EclipseLink)应该为您正在使用的数据库选择适当的策略。看起来持久性提供程序正在选择一种策略,即在您的情况下在服务器重新启动后重新启动值。

有不同的生成策略,你可以在EclipseLink Wiki找到一些详细的信息。

我猜你最好的选择是使用数据库序列 (GenerationType.SEQUENCE) 来生成 ID 值。

例子:

创建一个名为 GEN_SEQUENCE 的数据库序列(如果您让持久性提供程序生成您的表,我猜您也可以让它以某种方式创建序列,但此示例将展示如何手动完成),您应该查找有关如何在您使用的数据库中执行此操作(可能类似于CREATE SEQUENCE gen_sequence;)。将您的代码更改为:

@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "my_seq_gen")
@SequenceGenerator(name = "my_seq_gen", sequenceName = "GEN_SEQUENCE")
private int cod_utente;

您也可以对不同的类使用相同的序列。

更新:

对于@SequenceGenerator,你可以设置一个allocationSize,这个值是被保留的序列值的数量。默认值为 50。当您有一个从 0 开始的序列时,第一次从该序列请求一个值时,该序列分配(并保留)值 0-49(或 1-50)。持久性提供程序可以使用这些值,直到所有值都被使用,然后接下来的 50 个值(50-99 或 51-100)将被分配和保留。该序列会记住当前位置,因此如果它被多个类使用,它不会两次给出相同的范围。

对于 allocationSize 的值,您可以保留默认值,但这可能会在 ID 中产生间隙。如果一个序列范围(例如 0-49)被分配(保留)并且只有一个或一些值被使用(例如 0、1 和 2),则该范围的其他值(3-49)将“丢失”服务器重启。下一次分配的值范围将是 50-99,因此表中的下一个 ID 将是 50。
现在您的表中有以下 ID:0,1,2,50。通常这应该不是问题,但您也可以将 allocationSize 设置为较低的值或 1 以避免产生此类间隙。

另请参阅:

【讨论】:

  • 要使用该策略,我们需要设置allocationSize 对吗?该值对应于什么?设置该值的标准是什么?
  • 我在我的实体中写了这段代码:@Id @SequenceGenerator(name="seq7", initialValue=1, allocationSize=100) @GeneratedValue(strategy=GenerationType.SEQUENCE, generator="seq7") private int cod_ficha; 但是在运行服务器时出现了这个错误:xception [EclipseLink-4002] (Eclipse Persistence Services - 2.5.2.v20140319-9ad6abd): org.eclipse.persistence.exceptions.DatabaseException Internal Exception: java.sql.SQLSyntaxErrorException: SEQUENCE 'SEQ7' does not exist. Error Code: 30000 Call: VALUES(NEXT VALUE FOR seq7) Query: ValueReadQuery(sql="VALUES(NEXT VALUE FOR seq7)")
  • 错误信息说,序列不存在。如答案中所述,您必须在数据库上手动创建序列。
猜你喜欢
  • 1970-01-01
  • 2011-12-09
  • 2021-12-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多