我应该在JPA2.0中使用Primitives或包装器吗?

时间:2012-02-05 04:41:47

标签: java hibernate jpa-2.0

我在SO看到这个question往往会导致原始人,并且从coderanch看到这个往往会导致包装。两者都略显陈旧。

我没有任何特殊需求,只想了解标准的良好做法。

网络上的例子也是混合的。例如,有些像这样:

@Id
@Column(name = "CUSTOMER_ID")
public long customerId;

其他人使用Wrappers:

@Id
@Column(name = "CUSTOMER_ID")
public Long customerId;

5 个答案:

答案 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