hibernate主键的原语或包装器

Ano*_*nym 36 java orm hibernate

我一直在研究各种hibernate教程和示例,对于它们的身份/主键属性,有些使用Java原始类型,有些使用包装类型,即;

 private int id; 
Run Code Online (Sandbox Code Playgroud)

VS

 private Integer id;
Run Code Online (Sandbox Code Playgroud)

对于实体密钥,为什么以及何时使用其中一个?

Pas*_*ent 34

从Hibernate的角度来看,它不会改变任何东西,因为Hibernate使用相同的Hibernate类型来表示它们.

然而,正如字节码忍者指出,你不能区分原始INT的默认值0从分配的0同时也有可能没有歧义null(一个nullID总是意味着一个新的实体),这就是为什么我更喜欢使用可以为空的包装类型.

这是Hibernate的推荐.从参考文档:

4.1.2.提供标识符属性(可选)

Cat有一个名为id的属性.此属性映射到数据库表的主键列.该属性可能已被调用,其类型可能是任何基本类型,任何原始"包装"类型,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);
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 但是每次从DB读取这样的实体对象时,它不会创建包装器对象,最终会对GC造成压力吗?那么在我们知道主键不能为0的情况下使用原语会更好吗? (4认同)

Lam*_*bda 10

我更喜欢使用包装器类型,因为否则,当我们使用基本类型时,主键id0默认设置为,并且0可能是id实体的相应表中的实际列的值,这有时会导致困难找出错误.

但是,使用的包装,默认值id将是null与主键列不能有一个null值,从而无法更新,它的实体id值未设置与应用程序的逻辑有效值.