每次执行服务器和客户端时,Id 的 GeneratedValue 计数器都会重置
GeneratedValue counter for Id resets every time that the server and client are executed
我正在使用 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 时,密钥是从一个开始按顺序生成的。如果我关闭客户端和服务器并再次执行它们,密钥生成器的 "counter" 将重新建立。这会导致错误,因为应用程序将尝试使用主键“1”创建另一个 Utente。
有人可以帮我解决这个问题吗?
代码:
@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
的数据库序列(如果您让持久性提供程序生成您的 tables 我想您也可以让它以某种方式创建序列,但此示例将展示如何做手动),您应该在您正在使用的数据库中查找有关如何执行此操作的信息(可能类似于 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) 的其他值将得到 "lost" 在服务器重启时。下次分配值范围时,它将是 50-99,因此 table 中的下一个 ID 将是 50。
现在您的 table 中有以下 ID:0,1,2,50
。通常这应该不是问题,但您也可以将 allocationSize 设置为较低的值或 1 以避免产生此类间隙。
另请参阅:
- what is the use of annotations @Id and @GeneratedValue(strategy = GenerationType.IDENTITY)? Why the generationtype is identity?
- what is sequence (Database) ? When we need it?
- The differences between GeneratedValue strategies
我正在使用 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 时,密钥是从一个开始按顺序生成的。如果我关闭客户端和服务器并再次执行它们,密钥生成器的 "counter" 将重新建立。这会导致错误,因为应用程序将尝试使用主键“1”创建另一个 Utente。
有人可以帮我解决这个问题吗?
代码:
@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
的数据库序列(如果您让持久性提供程序生成您的 tables 我想您也可以让它以某种方式创建序列,但此示例将展示如何做手动),您应该在您正在使用的数据库中查找有关如何执行此操作的信息(可能类似于 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) 的其他值将得到 "lost" 在服务器重启时。下次分配值范围时,它将是 50-99,因此 table 中的下一个 ID 将是 50。
现在您的 table 中有以下 ID:0,1,2,50
。通常这应该不是问题,但您也可以将 allocationSize 设置为较低的值或 1 以避免产生此类间隙。
另请参阅:
- what is the use of annotations @Id and @GeneratedValue(strategy = GenerationType.IDENTITY)? Why the generationtype is identity?
- what is sequence (Database) ? When we need it?
- The differences between GeneratedValue strategies