我在SO看到这个question往往会导致原始人,并且从coderanch看到这个往往会导致包装。两者都略显陈旧。
我没有任何特殊需求,只想了解标准的良好做法。
网络上的例子也是混合的。例如,有些像这样:
@Id
@Column(name = "CUSTOMER_ID")
public long customerId;
其他人使用Wrappers:
@Id
@Column(name = "CUSTOMER_ID")
public Long customerId;
答案 0 :(得分:15)
两者之间的区别是可空性。原始类型不能为null,而“Wrapped”类型可以为null。
我更喜欢使用包装类型,因为您可以判断对象是否已保存/加载到数据库中,无论id值是否为null。
我不认为这里有“最佳实践”,也许是风格问题?
答案 1 :(得分:6)
Hibernate建议你:
我们建议您声明一致命名的标识符属性 持久化类和你使用可空的(即, 非原始的类型。 more
答案 2 :(得分:1)
如果使用原语,它将始终保持默认值,在这种情况下为0L,即使数据库中没有该值也是如此。如果您使用包装器对象,如果该值不在数据库中或实体尚未保留,则它将具有空值。
答案 3 :(得分:1)
我认为答案包含在@Column注释中的可空元素中。如果它可以为空,那么包裹原语是可以的。但是在nullable = false列上(如ID所示)原语更好。您将获得额外的检查,因为null无法转换为int / long。
答案 4 :(得分:0)
从Hibernate的角度来看,它并没有改变任何东西,因为Hibernate使用相同的Hibernate类型来表示它们。
然而,正如Bytecode Ninja所指出的,你不能区分原始int 0的默认值和指定的0,而没有可能与null的歧义(null id总是意味着一个新的实体),这就是为什么我更喜欢使用可以为空的包装类型。
这是Hibernate的推荐。参考文献:
4.1.2。提供标识符属性(可选)
Cat有一个名为id的属性。此属性映射到数据库表的主键列。该属性可能被称为任何东西,它的类型可能是任何原始类型,任何原始"包装" type,java.lang.String或java.util.Date。如果旧数据库表具有复合键,则可以使用具有这些类型属性的用户定义类(请参阅本章后面的复合标识符部分。)
identifier属性是严格可选的。您可以将它们关闭,让Hibernate在内部跟踪对象标识符。但是,我们不建议这样做。
实际上,某些功能仅适用于声明标识符属性的类:
分离对象的传递重新附加(级联更新或级联合并) - 请参见第10.11节“传递持久性” Session.saveOrUpdate() Session.merge()的 我们建议您在持久化类上声明一致命名的标识符属性,并使用可空(即非原始)类型。
我实际上在我的基类中使用它:
@MappedSuperclass
public class BaseEntity implements Serializable {
private static final long serialVersionUID = 1L;
private Long id;
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
@Transient
public boolean isNew() {
return (this.id == null);
}
}
请在此处查看更多详情:https://stackoverflow.com/posts/3537407/edit