Questo contenuto non è disponibile nella lingua selezionata.
4.3. Additional Information
4.3.1. Implementing Inheritance Copia collegamentoCollegamento copiato negli appunti!
Copia collegamentoCollegamento copiato negli appunti!
A subclass must also observe the first and second rules. It inherits its identifier property from the superclass,
Cat
. For example:
4.3.2. Implementing equals() and hashCode() Copia collegamentoCollegamento copiato negli appunti!
Copia collegamentoCollegamento copiato negli appunti!
You have to override the
equals()
and hashCode()
methods if you:
- 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 Set
s.
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):
A business key does not have to be as solid as a database primary key candidate. Immutable or unique properties are usually good candidates for a business key.
4.3.3. Dynamic Models Copia collegamentoCollegamento copiato negli appunti!
Copia collegamentoCollegamento copiato negli appunti!
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
Map
s of Map
s 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.
The following examples demonstrate the representation using
Map
s. First, in the mapping file an entity-name
has to be declared instead of, or in addition to, a class name:
Even though associations are declared using target class names, the target type of associations can also be a dynamic entity instead of a POJO.
After setting the default entity mode to
dynamic-map
for the SessionFactory
, you can, at runtime, work with Map
s of Map
s:
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.
Entity representation modes can also be set on a per
Session
basis:
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.3.4. Tuplizers Copia collegamentoCollegamento copiato negli appunti!
Copia collegamentoCollegamento copiato negli appunti!
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 and how to extract values from and 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, represented by the
org.hibernate.tuple.entity.EntityTuplizer
and org.hibernate.tuple.component.ComponentTuplizer
interfaces. EntityTuplizer
s are responsible for managing the above mentioned contracts in regards to entities, while ComponentTuplizer
s do the same for components.
Users can also plug in their own tuplizers. Perhaps you require that a
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:
4.3.5. EntityNameResolvers Copia collegamentoCollegamento copiato negli appunti!
Copia collegamentoCollegamento copiato negli appunti!
The
org.hibernate.EntityNameResolver
interface 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.
In order to register an
org.hibernate.EntityNameResolver
users must either:
- Implement a custom tupilizer, implementing the
getEntityNameResolvers
method. - Register it with the
org.hibernate.impl.SessionFactoryImpl
(which is the implementation class fororg.hibernate.SessionFactory
) using theregisterEntityNameResolver
method.