简体   繁体   English

hibernate主键的原语或包装器

[英]Primitive or wrapper for hibernate primary keys

I've been looking at various hibernate tutorials and samples, for their identity/primary key property, some use a Java primitive type, some uses the wrapper type, that is; 我一直在研究各种hibernate教程和示例,对于它们的身份/主键属性,有些使用Java原始类型,有些使用包装类型,即;

 private int id; 

vs VS

 private Integer id;

Why and when would I use one over the other, for the entity key ? 对于实体密钥,为什么以及何时使用其中一个?

From an Hibernate point of view, it doesn't change anything as Hibernate uses the same Hibernate type to represent them. 从Hibernate的角度来看,它不会改变任何东西,因为Hibernate使用相同的Hibernate类型来表示它们。

However, as pointed out by Bytecode Ninja, you can't distinguish the default value of a primitive int 0 from a an assigned 0 while there is no possible ambiguity with a null (a null id always means a new entity), which is why I prefer to use a nullable wrapper type. 然而,正如Bytecode Ninja所指出的,你无法区分原始int 0的默认值和指定的0而没有可能的nullnull id总是意味着一个新的实体),这就是为什么我更喜欢使用可空的包装类型。

And this is the Hibernate recommendation. 这是Hibernate的推荐。 From the Reference Documentation: 从参考文档:

4.1.2. 4.1.2。 Provide an identifier property (optional) 提供标识符属性(可选)

Cat has a property called id. Cat有一个名为id的属性。 This property maps to the primary key column of a database table. 此属性映射到数据库表的主键列。 The property might have been called anything, and its type might have been any primitive type, any primitive "wrapper" type, java.lang.String or java.util.Date. 该属性可能已被调用,其类型可能是任何基本类型,任何原始“包装”类型,java.lang.String或java.util.Date。 If your legacy database table has composite keys, you can use a user-defined class with properties of these types (see the section on composite identifiers later in the chapter.) 如果旧数据库表具有复合键,则可以使用具有这些类型属性的用户定义类(请参阅本章后面的复合标识符部分。)

The identifier property is strictly optional. identifier属性是严格可选的。 You can leave them off and let Hibernate keep track of object identifiers internally. 您可以将它们关闭,让Hibernate在内部跟踪对象标识符。 We do not recommend this, however. 但是,我们不建议这样做。

In fact, some functionality is available only to classes that declare an identifier property: 实际上,某些功能仅适用于声明标识符属性的类:

  • Transitive reattachment for detached objects (cascade update or cascade merge) - see Section 10.11, “Transitive persistence” 分离对象的传递重新附加(级联更新或级联合并) - 请参见第10.11节“传递持久性”
  • Session.saveOrUpdate() Session.saveOrUpdate()
  • Session.merge() Session.merge()的

We recommend that you declare consistently-named identifier properties on persistent classes and that you use a nullable (ie, non-primitive) type. 我们建议您在持久化类上声明一致命名的标识符属性,并使用可空(即非原始)类型。

And I actually leverage this in my base class: 我实际上在我的基类中利用它:

@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);
    }
}

I prefer using the wrapper types, because otherwise, when we use primitive types, the primary key id will be set to 0 by default, and 0 could be the value of an actual id column in the corresponding table of the entity, and this can sometimes lead to hard to pinpoint bugs. 我更喜欢使用的包装类型,因为否则的话,当我们使用原始类型,主键id将被设置为0默认情况下,和0可能是一个实际的值id在实体的相应表列,这可以有时导致难以查明错误。

But using a wrapper, the default value of id will be null and a primary key column cannot have a null value, thus you can't update an entity that its id value is not set with a valid value by your application's logic. 但是使用包装器时, id的默认值将为null并且主键列不能具有null值,因此您无法通过应用程序的逻辑更新其id值未使用有效值设置的实体。

You can specify your primary key as a primitive or a wrapper. 您可以将主键指定为基元或包装器。 And since usually the avantages of an Integer aren't needed, it's best to keep it simple with an int . 而且由于通常不需要Integer的优点,所以最好用int保持简单。

More info at oracle.com . 有关更多信息,请访问oracle.com

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM