Java 装箱vs图元类型作为实体id

Java 装箱vs图元类型作为实体id,java,database,hibernate,jpa,orm,Java,Database,Hibernate,Jpa,Orm,在JPA(Hibernate实现)中,哪个类型更适合用于实体的id: 装箱类型(例如整数)或未装箱类型(例如整数) 一位朋友说,您应该使用装箱类型,因为当您在程序中创建新实体时,Hibernate会看到id为null,并了解它应该在数据库中创建新行(相反,如果id不是null,Hibernate可能会更新数据库中的现有行) 但是我的实体的id是int,它运行良好,没有任何错误,我们知道原始实例变量的默认值是0。因此,他说hibernate可能将0视为特殊对象,并假设该对象是一个新对象。似乎建议使

在JPA(Hibernate实现)中,哪个类型更适合用于实体的id: 装箱类型(例如
整数
)或未装箱类型(例如
整数

一位朋友说,您应该使用装箱类型,因为当您在程序中创建新实体时,Hibernate会看到id为
null
,并了解它应该在数据库中创建新行(相反,如果id不是
null
,Hibernate可能会更新数据库中的现有行)

但是我的实体的id是
int
,它运行良好,没有任何错误,我们知道原始实例变量的默认值是
0
。因此,他说hibernate可能将
0
视为特殊对象,并假设该对象是一个新对象。

似乎建议使用Boxed类型

我们建议您在持久类上声明一致命名的标识符属性,并使用可空(即非基本)类型


嗯,我们使用非原语,我们有充分的理由这样做。例如,我们的许多字段是
int/Integer
,其绝对业务值为
0
是完全有效的。例如,考虑一个债务字段-如果该字段为
,则表示您没有债务


问题是,对于原语,零是一个默认值-因此您可能会意外地忘记设置它,例如通过
setDebt
,因此它可能会以一个您从未打算使用的值到达您的数据库。出于这个原因,我们使用
Integer
进行一些验证,例如,该验证不应为null;但是,即使我们忘记添加适当的验证,代码也可能会出现
NullPointerException
(最好是在测试中),我更喜欢异常而不是数据库中不一致的值

我们可以这样想:

当我们有一个值x::Int,那么“x”就是一个计算 计算时将返回Int或will 位于底部(未定义)

当程序运行并计算x时,假设它计算为 实际整数(不是底部)。那么在将来任何时候,x被计算, 我们不想重做整个计算,只想得到值 我们之前计算出来的

我们要做的是替换为thunk(计算),它 计算x时发出的砰的一声,该声仅返回所需的值 以前计算过

问题是,将来每次你需要得到x时,你都有 按照此指针指向返回值的(普通)代码。这 如果您经常需要这些值,则会变得昂贵

输入未绑定的值。未绑定的值只是该低级值,而不是 包裹在砰的一声中。这意味着它在某种意义上是严格的
如果您的程序不一定会死掉,则不能取消定义。

实体id的原语(例如int)和它的包装器(例如整数)之间没有区别。根据JPA规范,两者都是有效的。JPA提供者足够聪明,可以跟踪实体的状态和生命周期。当实体id为0(基本类型)或NULL(包装类型)时,如果配置了id生成器,JPA提供程序将为实体生成id。如果id是自动生成的,则零不被视为有效的实体id

使用
Cmobilecom-JPA
对这两种情况进行了测试,效果相当。当然,没有发现性能差异


免责声明:我是Java和Android的轻量级JPA实现的开发人员。

我更喜欢实体模型中的盒式类型,因为这样可以灵活地在泛型中使用盒式类型。 例如,这里的实体模型只能具有扩展为可序列化id的类型。它将在以后的服务层中非常有用,在服务层中,我们可以对主键执行各种操作

public interface BaseEntity<E extends Serializable> extends Serializable {
  E getId();
}
公共接口BaseEntity扩展了可序列化{
E getId();
}
实体模型可能类似于:

@Entity
public class PhoneNumber implements BaseEntity<Long> {
  private static final long serialVersionUID = 1L;

  @Id
  @GeneratedValue(strategy = GenerationType.IDENTITY)
  @Column(name = "PHONE_NUMBER_ID")
  private Long id;
@实体
公共类PhoneNumber实现BaseEntity{
私有静态最终长serialVersionUID=1L;
@身份证
@GeneratedValue(策略=GenerationType.IDENTITY)
@列(name=“电话号码”\u ID)
私人长id;

实体和集合的唯一标识符可以是除二进制、blob和clob之外的任何基本类型。(也允许使用复合标识符,见下文。)


基本值类型在org.hibernate.hibernate上定义了相应的类型常量。例如,hibernate.STRING表示字符串类型。

这个答案没有回答这个问题。这个问题专门询问@Id字段。只需从1开始排序,就可以避免将0作为有效数字(这是Hibernate中的默认行为)。