Persistent classes are classes in an application that implement the entities of the business problem
(e.g. Customer and Order in an E-commerce application). The term "persistent" here means that the classes
are able to be persisted, not that they are in the persistent state (see Section 11.1, “Hibernate object states”
for discussion).

Hibernate works best if these classes follow some simple rules, also known as the Plain Old Java Object (POJO)
programming model. However, none of these rules are hard requirements. Indeed, Hibernate assumes very little
about the nature of your persistent objects. You can express a domain model in other ways (using trees of
java.util.Map instances, for example).

The four main rules of persistent classes are explored in more detail in the following sections.

4.1.1. Implement a no-argument constructor

Cat has a no-argument constructor. All persistent classes must have a default
constructor (which can be non-public) so that Hibernate can instantiate them using
java.lang.reflect.Constructor.newInstance(). It is recommended
that this constructor be defined with at least package visibility in order for
runtime proxy generation to work properly.

4.1.2. Provide an identifier property

Note

Historically this was considered option. While still not (yet) enforced, this should be considered
a deprecated feature as it will be completely required to provide a identifier property in an
upcoming release.

Cat has a property named id. This property maps to the
primary key column(s) of the underlying database table. The type of the identifier property can
be any "basic" type (see ???). See Section 9.4, “Components as composite identifiers”
for information on mapping composite (multi-column) identifiers.

Note

Identifiers do not necessarily need to identify column(s) in the database physically defined
as a primary key. They should just identify columns that can be used to uniquely identify rows
in the underlying table.

We recommend that you declare consistently-named identifier properties on persistent classes and that you use
a nullable (i.e., non-primitive) type.

4.1.3. Prefer non-final classes (semi-optional)

A central feature of Hibernate, proxies (lazy loading), depends upon the
persistent class being either non-final, or the implementation of an interface that declares all public
methods. You can persist final classes that do not implement an interface with
Hibernate; you will not, however, be able to use proxies for lazy association fetching which will
ultimately limit your options for performance tuning. To persist a final
class which does not implement a "full" interface you must disable proxy generation. See
Example 4.2, “Disabling proxies in hbm.xml” and
Example 4.3, “Disabling proxies in annotations”.

Cat declares accessor methods for all its persistent fields. Many other ORM
tools directly persist instance variables. It is better to provide an indirection between the relational
schema and internal data structures of the class. By default, Hibernate persists JavaBeans style
properties and recognizes method names of the form getFoo, isFoo
and setFoo. If required, you can switch to direct field access for particular
properties.

Properties need not be declared public. Hibernate can persist a property declared
with package, protected or private visibility
as well.

4.2. Implementing inheritance

A subclass must also observe the first and second rules. It inherits
its identifier property from the superclass, Cat. For
example:

4.3. Implementing equals() and
hashCode()

intend to put instances of persistent classes in a
Set (the recommended way to represent many-valued
associations); and

intend to use reattachment of detached instances

Hibernate guarantees equivalence of persistent identity (database
row) and Java identity only inside a particular session scope. When you
mix instances retrieved in different sessions, you must implement
equals() and hashCode() if you wish
to have meaningful semantics for Sets.

The most obvious way is to implement
equals()/hashCode() by comparing the
identifier value of both objects. If the value is the same, both must be
the same database row, because they are equal. If both are added to a
Set, you will only have one element in the
Set). Unfortunately, you cannot use that approach with
generated identifiers. Hibernate will only assign identifier values to
objects that are persistent; a newly created instance will not have any
identifier value. Furthermore, if an instance is unsaved and currently in
a Set, saving it will assign an identifier value to the
object. If equals() and hashCode()
are based on the identifier value, the hash code would change, breaking
the contract of the Set. See the Hibernate website for
a full discussion of this problem. This is not a Hibernate issue, but
normal Java semantics of object identity and equality.

It is recommended that you implement equals() and
hashCode() using Business key
equality. Business key equality means that the
equals() method compares only the properties that form
the business key. It is a key that would identify our instance in the real
world (a natural candidate key):

4.4. Dynamic models

Note

The following features are currently considered
experimental and may change in the near future.

Persistent entities do not necessarily have to be represented as
POJO classes or as JavaBean objects at runtime. Hibernate also supports
dynamic models (using Maps of Maps
at runtime) and the representation of entities as DOM4J trees. With this
approach, you do not write persistent classes, only mapping files.

By default, Hibernate works in normal POJO mode. You can set a
default entity representation mode for a particular
SessionFactory using the
default_entity_mode configuration option (see Table 3.3, “Hibernate Configuration Properties”).

The following examples demonstrate the representation using
Maps. First, in the mapping file an
entity-name has to be declared instead of, or in
addition to, a class name:

One of the main advantages of dynamic mapping is quick turnaround
time for prototyping, without the need for entity class implementation.
However, you lose compile-time type checking and will likely deal with
many exceptions at runtime. As a result of the Hibernate mapping, the
database schema can easily be normalized and sound, allowing to add a
proper domain model implementation on top later on.

Please note that the call to getSession() using
an EntityMode is on the Session API,
not the SessionFactory. That way, the new
Session shares the underlying JDBC connection,
transaction, and other context information. This means you do not have to
call flush() and close() on the
secondary Session, and also leave the transaction and
connection handling to the primary unit of work.

4.5. Tuplizers

org.hibernate.tuple.Tuplizer and its sub-interfaces are responsible for
managing a particular representation of a piece of data given that representation's
org.hibernate.EntityMode. If a given piece of data is thought of as a data
structure, then a tuplizer is the thing that knows how to create such a data structure, how to extract
values from such a data structure and how to inject values into such a data structure. For example, for
the POJO entity mode, the corresponding tuplizer knows how create the POJO through its constructor.
It also knows how to access the POJO properties using the defined property accessors.

There are two (high-level) types of Tuplizers:

org.hibernate.tuple.entity.EntityTuplizer which is
responsible for managing the above mentioned contracts in regards to entities

org.hibernate.tuple.component.ComponentTuplizer which does the
same for components

Users can also plug in their own tuplizers. Perhaps you require that
java.util.Map implementation other than
java.util.HashMap be used while in the dynamic-map entity-mode. Or perhaps you
need to define a different proxy generation strategy than the one used by default. Both would be achieved
by defining a custom tuplizer implementation. Tuplizer definitions are attached to the entity or component
mapping they are meant to manage. Going back to the example of our Customer entity,
Example 4.6, “Specify custom tuplizers in annotations” shows how to specify a custom
org.hibernate.tuple.entity.EntityTuplizer using annotations while
Example 4.7, “Specify custom tuplizers in hbm.xml” shows how to do the same in hbm.xml

4.6. EntityNameResolvers

org.hibernate.EntityNameResolver is a contract for resolving the entity name
of a given entity instance. The interface defines a single method resolveEntityName
which is passed the entity instance and is expected to return the appropriate entity name (null is
allowed and would indicate that the resolver does not know how to resolve the entity name of the given entity
instance). Generally speaking, an org.hibernate.EntityNameResolver is going
to be most useful in the case of dynamic models. One example might be using proxied interfaces as your
domain model. The hibernate test suite has an example of this exact style of usage under the
org.hibernate.test.dynamicentity.tuplizer2. Here is some of the code from that package
for illustration.