1

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

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

4

1 回答 1

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

也可以看看:

于 2015-01-01T20:38:18.700 回答