----------------------------------------------------------------------------------------------------------------
Understanding Java identity and equality:
Along with Java identity (memory location) and object equality, you pick up
database identity (which is the location in the persistent data store). You now have
three methods for identifying objects:
■ Objects are identical if they occupy the same memory location in the JVM.
This can be checked by using the == operator. This concept is known as
object identity.
■ Objects are equal if they have the same value, as defined by the
equals(Object o) method. Classes that don’t explicitly override this
method inherit the implementation defined by java.lang.Object, which
compares object identity. This concept is known as equality.
■ Objects stored in a relational database are identical if they represent the
same row or, equivalently, if they share the same table and primary key
value. This concept is known as database identity.
---------------------------------------------------------------------------------------------------------------
Handling database identity:
Hibernate exposes database identity to the application in two ways:
■ The value of the identifier property of a persistent instance
■ The value returned by Session.getIdentifier(Object entity)
----------------------------------------------------------------------------------------------------------------
Adding an identifier property to entities
The identifier property is special—its value is the primary key value of the database
row represented by the persistent instance. We don’t usually show the identifier
property in the domain model diagrams. In the examples, the identifier
property is always named id. If myCategory is an instance of Category, calling
myCategory.getId() returns the primary key value of the row represented by
myCategory in the database.
Let’s implement an identifier property for the Category class:
private Long id;
...
public Long getId() {
return this.id;
}
private void setId(Long id) {
this.id = id;
}
...
}
Should you make the accessor methods for the identifier property private scope or
public? Well, database identifiers are often used by the application as a convenient
handle to a particular instance, even outside the persistence layer. For example,
it’s common for web applications to display the results of a search screen to the
user as a list of summary information. When the user selects a particular element,
the application may need to retrieve the selected object, and it’s common to use a
lookup by identifier for this purpose—you’ve probably already used identifiers
this way, even in applications that rely on JDBC. It’s usually appropriate to fully
expose the database identity with a public identifier property accessor.
On the other hand, you usually declare the setId() method private and let
Hibernate generate and set the identifier value. Or, you map it with direct field
access and implement only a getter method. (The exception to this rule is
classes with natural keys, where the value of the identifier is assigned by the
application before the object is made persistent instead of being generated by
Hibernate. We discuss natural keys in chapter 8.) Hibernate doesn’t allow you to
change the identifier value of a persistent instance after it’s first assigned. A primary
key value never changes—otherwise the attribute wouldn’t be a suitable
primary key candidate!
The Java type of the identifier property, java.lang.Long in the previous example,
depends on the primary key type of the CATEGORY table and how it’s mapped
in Hibernate metadata.
-----------------------------------------------------------------------------------------------------------------
Mapping the identifier property
A regular (noncomposite) identifier property is mapped in Hibernate XML files
with the <id> element:
<id name="id" column="CATEGORY_ID" type="long">
<generator class="native"/>
</id>
...
</class>
The identifier property is mapped to the primary key column CATEGORY_ID of the
table CATEGORY. The Hibernate type for this property is long, which maps to a
BIGINT column type in most databases and which has also been chosen to match
the type of the identity value produced by the native identifier generator.
For a JPA entity class, you use annotations in the Java source code to map the
identifier property:
@Table(name="CATEGORY")
public class Category {
private Long id;
...
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@Column(name = "CATEGORY_ID")
public Long getId() {
return this.id;
}
private void setId(Long id) {
this.id = id;
}
...
}
The @Id annotation on the getter method marks it as the identifier property, and
@GeneratedValue with the GenerationType.AUTO option translates into a native
identifier generation strategy, like the native option in XML Hibernate mappings.
Note that if you don’t define a strategy, the default is also Generation Type.AUTO, so you could have omitted this attribute altogether. You also specify a database column—otherwise Hibernate would use the property name. The mapping type is implied by the Java property type, java.lang.Long.
Of course, you can also use direct field access for all properties, including the
database identifier:
<table name="CATEGORY"/>
<attributes>
<id name="id">
<generated-value strategy="AUTO"/>
</id>
...
</attributes>
</entity>