每次执行服务器和客户端时,Id的GeneratedValue计数器都会重置

时间:2015-01-01 19:32:56

标签: jpa eclipselink primary-key generated

我正在使用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 时,从一个开始按顺序生成密钥。如果我关闭客户端和服务器并再次执行它们,那么&#34;计数器&#34;密钥生成器的重新建立。这会导致错误,因为应用程序将尝试使用主键&#34; 1&#34;创建另一个 Utente

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

1 个答案:

答案 0 :(得分:3)

代码:

@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 以避免产生此类间隙。

另见: