diff --git a/reference/en/modules/basic_mapping.xml b/reference/en/modules/basic_mapping.xml
index 0735044266..3697ce5eca 100644
--- a/reference/en/modules/basic_mapping.xml
+++ b/reference/en/modules/basic_mapping.xml
@@ -1710,6 +1710,44 @@
+
+ natural-id
+
+
+
+
+ ......
+]]>
+
+
+ Even though we recommend the use of surrogate keys as primary keys, you should still try
+ to identify natural keys for all entities. A natural key is a property or combination of
+ properties that is unique and non-null. If it is also immutable, even better. Map the
+ properties of the natural key inside the <natural-id> element.
+ Hibernate will generate the necessary unique key and nullability constraints, and your
+ mapping will be more self-documenting.
+
+
+
+ We strongly recommend that you implement equals() and
+ hashCode() to compare the natural key properties of the entity.
+
+
+
+ This mapping is not intended for use with entities with natural primary keys.
+
+
+
+
+
+ mutable (optional, defaults to false):
+ By default, natural identifier properties as assumed to be immutable (constant).
+
+
+
+
+
+
component, dynamic-component
diff --git a/reference/en/modules/best_practices.xml b/reference/en/modules/best_practices.xml
index 7cd1c1cf3d..543cbaf9e5 100644
--- a/reference/en/modules/best_practices.xml
+++ b/reference/en/modules/best_practices.xml
@@ -18,9 +18,17 @@
Hibernate makes identifier properties optional. There are all sorts of reasons why
you should use them. We recommend that identifiers be 'synthetic' (generated, with
- no business meaning). It doesn't make a difference if you use long
- or java.lang.Long; primitives might be syntactically easier to handle
- though.
+ no business meaning).
+
+
+
+
+ Identify natural keys.
+
+
+ Identify natural keys for all entities, and map them using
+ <natural-id>. Implement equals() and
+ hashCode() to compare the properties that make up the natural key.
@@ -47,7 +55,8 @@
This is a good practice if your queries call non-ANSI-standard SQL functions.
- Externalising the query strings to mapping files will make the application more portable.
+ Externalising the query strings to mapping files will make the application more
+ portable.
@@ -86,12 +95,11 @@
Use hand-coded JDBC in bottlenecks.
- In performance-critical areas of the system, some kinds of operations (eg. mass update /
- delete) might benefit from direct JDBC. But please, wait until you know
- something is a bottleneck. And don't assume that direct JDBC is necessarily faster. If need to
- use direct JDBC, it might be worth opening a Hibernate Session and using that SQL
- connection. That way you can still use the same transaction strategy and underlying connection
- provider.
+ In performance-critical areas of the system, some kinds of operations might benefit from
+ direct JDBC. But please, wait until you know something is a bottleneck.
+ And don't assume that direct JDBC is necessarily faster. If you need to use direct JDBC, it might
+ be worth opening a Hibernate Session and using that JDBC connection. That
+ way you can still use the same transaction strategy and underlying connection provider.
@@ -107,27 +115,29 @@
- In a three tiered architecture, consider using saveOrUpdate().
+ In a three tiered architecture, consider using detached objects.
When using a servlet / session bean architecture, you could pass persistent objects loaded in
the session bean to and from the servlet / JSP layer. Use a new session to service each request.
- Use Session.update() or Session.saveOrUpdate() to update the
- persistent state of an object.
+ Use Session.merge() or Session.saveOrUpdate() to
+ synchronize objects with the database.
- In a two tiered architecture, consider using session disconnection.
+ In a two tiered architecture, consider using long persistence contexts.
Database Transactions have to be as short as possible for best scalability. However, it is often
- neccessary to implement long running Application Transactions, a single unit-of-work from the
- point of view of a user. This Application Transaction might span several client requests and
- response cycles. Either use Detached Objects or, in two tiered architectures, simply disconnect
- the Hibernate Session from the JDBC connection and reconnect it for each subsequent request. Never
- use a single Session for more than one Application Transaction usecase, otherwise, you will run
- into stale data.
+ neccessary to implement long running application transactions, a single
+ unit-of-work from the point of view of a user. An application transaction might span several
+ client request/response cycles. It is common to use detached objects to implement application
+ transactions. An alternative, extremely appropriate in two tiered architecture, is to maintain
+ a single open persistence contact (session) for the whole lifecycle of the application transaction
+ and simply disconnect from the JDBC connection at the end of each request and reconnect at the
+ beginning of the subsequent request. Never share a single session across more than one application
+ transaction, or you will be working with stale data.
@@ -139,7 +149,7 @@
the Transaction and close the Session. If you don't, Hibernate
can't guarantee that in-memory state accurately represents persistent state. As a special case of this,
do not use Session.load() to determine if an instance with the given identifier
- exists on the database; use find() instead.
+ exists on the database; use Session.get() or a query instead.
@@ -147,11 +157,30 @@
Prefer lazy fetching for associations.
- Use eager (outer-join) fetching sparingly. Use proxies and/or lazy collections for most associations
- to classes that are not cached at the JVM-level. For associations to cached classes, where there is
- a high probability of a cache hit, explicitly disable eager fetching using
- outer-join="false". When an outer-join fetch is appropriate to a particular use
- case, use a query with a left join.
+ Use eager fetching sparingly. Use proxies and lazy collections for most associations to classes that
+ are not likely to be completely held in the second-level cache. For associations to cached classes,
+ where there is an a extremely high probability of a cache hit, explicitly disable eager fetching using
+ lazy="false". When an join fetching is appropriate to a particular use
+ case, use a query with a left join fetch.
+
+
+
+
+
+ Use the open session in view pattern, or a disciplined
+ assembly phase to avoid problems with unfetched data.
+
+
+
+ Hibernate frees the developer from writing tedious Data Transfer Objects (DTO).
+ In a traditional EJB architecture, DTOs serve dual purposes: first, they work around the problem
+ that entity beans are not serializable; second, they implicitly define an assembly phase where
+ all data to be used by the view is fetched and marshalled into the DTOs before returning control
+ to the presentation tier. Hibernate eliminates the first purpose. However, you will still need
+ an assembly phase (think of your business methods as having a strict contract with the presentation
+ tier about what data is available in the detached objects) unless you are prepared to hold the
+ persistence context (the session) open across the view rendering process. This is not a limitation
+ of Hibernate! It is a fundamental requirement of safe transactional data access.
@@ -167,23 +196,6 @@
-
- Implement equals() and hashCode() using a unique business key.
-
-
- If you compare objects outside of the Session scope, you have to implement equals()
- and hashCode(). Inside the Session scope, Java object identity is guaranteed. If
- you implement these methods, never ever use the database identifier! A transient object doesn't have
- an identifier value and Hibernate would assign a value when the object is saved. If the object
- is in a Set while being saved, the hash code changes, breaking the contract. To implement
- equals() and hashCode(), use a unique business key, that is,
- compare a unique combination of class properties. Remember that this key has to be stable and unique
- only while the object is in a Set, not for the whole lifetime (not as stable as a database primary
- key). Never use collections in the equals() comparison (lazy loading) and be careful
- with other associated classes that might be proxied.
-
-
-
Don't use exotic association mappings.
@@ -196,6 +208,15 @@
+
+ Prefer bidirectional associations.
+
+
+ Unidirectional associations are more difficult to query. In a large application, almost
+ all associations must be navigable in both directions in queries.
+
+
+
diff --git a/reference/en/modules/query_criteria.xml b/reference/en/modules/query_criteria.xml
index e7386b16ee..3cb774f981 100644
--- a/reference/en/modules/query_criteria.xml
+++ b/reference/en/modules/query_criteria.xml
@@ -52,9 +52,9 @@ List cats = crit.list();]]>
.add( Restrictions.in( "name", new String[] { "Fritz", "Izi", "Pk" } ) )
.add( Restrictions.disjunction()
.add( Restrictions.isNull("age") )
- .add( Restrictions.eq("age", new Integer(0) ) )
- .add( Restrictions.eq("age", new Integer(1) ) )
- .add( Restrictions.eq("age", new Integer(2) ) )
+ .add( Restrictions.eq("age", new Integer(0) ) )
+ .add( Restrictions.eq("age", new Integer(1) ) )
+ .add( Restrictions.eq("age", new Integer(2) ) )
) )
.list();]]>
@@ -83,9 +83,9 @@ Property age = Property.forName("age");
List cats = sess.createCriteria(Cat.class)
.add( Restrictions.disjunction()
.add( age.isNull() )
- .add( age.eq( new Integer(0) ) )
- .add( age.eq( new Integer(1) ) )
- .add( age.eq( new Integer(2) ) )
+ .add( age.eq( new Integer(0) ) )
+ .add( age.eq( new Integer(1) ) )
+ .add( age.eq( new Integer(2) ) )
) )
.add( Property.forName("name").in( new String[] { "Fritz", "Izi", "Pk" } ) )
.list();]]>
@@ -332,13 +332,13 @@ List results = session.createCriteria(Cat.class)
- Detached queries and subqueries
-
- The DetachedCriteria class lets you create a query outside the scope
- of a session, and then later execute it using some arbitrary Session.
-
-
- Detached queries and subqueries
+
+ The DetachedCriteria class lets you create a query outside the scope
+ of a session, and then later execute it using some arbitrary Session.
+
+
+
-
- A DetachedCriteria may also be used to express a subquery. Criterion
- instances involving subqueries may be obtained via Subqueries or
- Property.
-
-
-
-
-
-
-
- Even correlated subqueries are possible:
-
+
+ A DetachedCriteria may also be used to express a subquery. Criterion
+ instances involving subqueries may be obtained via Subqueries or
+ Property.
+
-
+
+
+
+
+ Even correlated subqueries are possible:
+
+
+
-
-
-
-
+ .add( Property.forName("weight).gt(avgWeightForSex) )
+ .list();]]>
+
+
+
+
+
+
+ Queries by natural identifier
+
+
+ For most queries, including criteria queries, the query cache is not very efficient,
+ because query cache invalidation occurs too frequently. However, there is one special
+ kind of query where we can optimize the cache invalidation algorithm: lookups by a
+ constant natural key. In some applications, this kind of query occurs frequently.
+ The criteria API provides special provision for this use case.
+
+
+
+ First, you should map the natural key of your entity using
+ <natural-id>, and enable use of the second-level cache.
+
+
+
+
+
+
+
+
+
+
+
+
+]]>
+
+
+ Note that this functionality is not intended for use with entities with
+ mutable natural keys.
+
+
+
+ Next, enable the Hibernate query cache.
+
+
+
+ Now, Restrictions.naturalId() allows us to make use of
+ the more efficient cache algorithm.
+
+
+
+
+
+