38

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;

 private int id; 

vs

 private Integer id;

Why and when would I use one over the other, for the entity key ?

Pascal Thivent
  • 562,542
  • 136
  • 1,062
  • 1,124
Anonym
  • 7,345
  • 8
  • 35
  • 32

3 Answers3

35

From an Hibernate point of view, it doesn't change anything as Hibernate uses the same Hibernate type to represent them.

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.

And this is the Hibernate recommendation. From the Reference Documentation:

4.1.2. Provide an identifier property (optional)

Cat has a property called 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. 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. You can leave them off and let Hibernate keep track of object identifiers internally. 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”
  • Session.saveOrUpdate()
  • Session.merge()

We recommend that you declare consistently-named identifier properties on persistent classes and that you use a nullable (i.e., 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);
    }
}
Pascal Thivent
  • 562,542
  • 136
  • 1,062
  • 1,124
  • I agree If he want to use a primitive type, he also can encapsulate by using an Integer – Arthur Ronald Aug 21 '10 at 22:02
  • 6
    But won't it create wrapper objects every time such an entity object is read from DB, ultimately stressing GC? So would it be better to use primitives where we know that the primary key can't be 0? – shrini1000 Jan 10 '12 at 06:53
  • 1
    This is still the recommendation as of Hibernate 5.1 but it is now in section "2.5.5. Provide identifier attribute(s)" – Night Owl Mar 22 '16 at 20:06
12

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.

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.

Behrang
  • 46,888
  • 25
  • 118
  • 160
  • Is it always necessary to set the id by application logic? Is there no way hibernate can figure out the next id while persisting a new object when using wrapper as primary key? – Nikhil Sahu Jun 06 '16 at 10:18
1

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.

More info at oracle.com.

Colin Hebert
  • 91,525
  • 15
  • 160
  • 151