From 039bb48ccf02ffc9e0d983a3f15ef3958f1e7372 Mon Sep 17 00:00:00 2001 From: Gail Badner Date: Wed, 24 Mar 2010 18:19:00 +0000 Subject: [PATCH] HHH-4940 : Document immutable/read-only entity and immutable collection functionality git-svn-id: https://svn.jboss.org/repos/hibernate/core/trunk@19108 1b8cb986-b30d-0410-93ca-fae66ebed9b2 --- ...ational_Persistence_for_Idiomatic_Java.xml | 1 + .../main/docbook/en-US/content/readonly.xml | 858 ++++++++++++++++++ 2 files changed, 859 insertions(+) create mode 100644 documentation/manual/src/main/docbook/en-US/content/readonly.xml diff --git a/documentation/manual/src/main/docbook/en-US/HIBERNATE_-_Relational_Persistence_for_Idiomatic_Java.xml b/documentation/manual/src/main/docbook/en-US/HIBERNATE_-_Relational_Persistence_for_Idiomatic_Java.xml index bcf99f04e4..c101609a01 100644 --- a/documentation/manual/src/main/docbook/en-US/HIBERNATE_-_Relational_Persistence_for_Idiomatic_Java.xml +++ b/documentation/manual/src/main/docbook/en-US/HIBERNATE_-_Relational_Persistence_for_Idiomatic_Java.xml @@ -80,6 +80,7 @@ + diff --git a/documentation/manual/src/main/docbook/en-US/content/readonly.xml b/documentation/manual/src/main/docbook/en-US/content/readonly.xml new file mode 100644 index 0000000000..294616c365 --- /dev/null +++ b/documentation/manual/src/main/docbook/en-US/content/readonly.xml @@ -0,0 +1,858 @@ + + + + +%BOOK_ENTITIES; + +]> + + + Read-only entities + + + + Hibernate's treatment of read-only entities may + differ from what you may have encountered elsewhere. Incorrect usage + may cause unexpected results. + + + + + When an entity is read-only: + + + + + Hibernate does not dirty-check the entity's simple + properties or single-ended associations; + + + + + Hibernate will not update simple properties or updatable + single-ended associations; + + + + + Hibernate will not update the version of the read-only + entity if only simple properties or single-ended + updatable associations are changed; + + + + + + + In some ways, Hibernate treats read-only entities the same as entities that are + not read-only: + + + + + Hibernate cascades operations to associations as + defined in the entity mapping. + + + + + Hibernate updates the version if the entity has a + collection with changes that dirties the entity; + + + + + A read-only entity can be deleted. + + + + + + + Even if an entity is not read-only, its collection association can + be affected if it contains a read-only entity. + + + + For details about the affect of read-only entities on different + property and association types, see + . + + + + For details about how to make entities read-only, see + + + + + Hibernate does some optimizing for read-only entities: + + + + + It saves execution time by not dirty-checking simple properties or + single-ended associations. + + + + + It saves memory by deleting database snapshots. + + + + +
+ Making persistent entities read-only + + + Only persistent entities can be made read-only. Transient and + detached entities must be put in persistent state before they + can be made read-only. + + + + Hibernate provides the following ways to make persistent entities read-only: + + + + + + you can map an entity class as immutable; + when an entity of an immutable class is made persistent, + Hibernate automatically makes it read-only. + see for details + + + + + you can change a default so that entities loaded + into the session by Hibernate are automatically + made read-only; see for details + + + + + you can make an HQL query or criteria read-only so + that entities loaded when the query or criteria executes, + scrolls, or iterates, are automatically + made read-only; see for details + + + + + you can make a persistent entity that is already in the + in the session read-only; see + for details + + + + +
+ Entities of immutable classes + + + When an entity instance of an immutable class is made + persistent, Hibernate automatically makes it read-only. + + + An entity of an immutable class can created + and deleted the same as an entity of a mutable class. + + + + Hibernate treats a persistent entity of an immutable + class the same way as a read-only persistent entity + of a mutable class. The only exception is that + Hibernate will not allow an entity of an immutable + class to be changed so it is not read-only. + + +
+ +
+ Loading persistent entities as read-only + + + + Entities of immutable classes are automatically loaded + as read-only. + + + + + To change the default behavior so Hibernate loads entity + instances of mutable classes into the session and automatically + makes them read-only, call: + + Session.setDefaultReadOnly( true ); + + + To change the default back so entities loaded by Hibernate are not + made read-only, call: + + Session.setDefaultReadOnly( false ); + + + You can determine the current setting by calling: + + Session.isDefaultReadOnly(); + + + If Session.isDefaultReadOnly() returns true, entities loaded by + the following are automatically made read-only: + + + + + Session.load() + + + + + Session.get() + + + + + Session.merge() + + + + + executing, scrolling, or iterating HQL queries and + criteria; to override this setting for a particular + HQL query or criteria see + + + + + + + Changing this default has no effect on: + + + + + persistent entities already in the session when the + default was changed + + + + + persistent entities that are refreshed via + Session.refresh(); a refreshed persistent + entity will only be read-only if it was + read-only before refreshing + + + + + persistent entities added by the application via + Session.persist(), Session.save(), and Session.update() + Session.saveOrUpdate() + + + + +
+ +
+ Loading read-only entities from an HQL query/criteria + + + + Entities of immutable classes are automatically loaded + as read-only. + + + + + If Session.isDefaultReadOnly() returns false (the default) + when an HQL query or criteria executes, then entities + and proxies of mutable classes loaded by the query will + not be read-only. + + + + You can override this behavior so that entities and proxies loaded + by an HQL query or criteria are automatically made read-only. + + + + For an HQL query, call: + + Query.setReadOnly( true ); + + + Query.setReadOnly( true ) must be called before + Query.list(), Query.uniqueResult(), + Query.scroll(), or Query.iterate() + + + + For an HQL criteria, call: + + Criteria.setReadOnly( true ); + + + Criteria.setReadOnly( true ) must be called before + Criteria.list(), Criteria.uniqueResult(), + or Criteria.scroll() + + + + Entities and proxies that exist in the session before being returned + by an HQL query or criteria are not affected. + + + + Uninitialized persistent collections returned by the query are + not affected. Later, when the collection is initialized, + entities loaded into the session will be read-only if + Session.isDefaultReadOnly() returns true. + + + + Using Query.setReadOnly( true ) or + Criteria.setReadOnly( true ) works well + when a single HQL query or criteria loads all the entities and + intializes all the proxies and collections that the application + needs to be read-only. + + + + When it is not possible to load and initialize all + necessary entities in a single query or criteria, + you can temporarily change the session default to load + entities as read-only before the query is executed. + Then you can explicitly initialize proxies and collections + before restoring the session default. + + + +Session session = factory.openSession(); +Transaction tx = session.beginTransaction(); + +setDefaultReadOnly( true ); +Contract contract = + ( Contract ) session.createQuery( + "from Contract where customerName = 'Sherman'" ) + .uniqueResult(); +Hibernate.initialize( contract.getPlan() ); +Hibernate.initialize( contract.getVariations() ); +Hibernate.initialize( contract.getNotes() ); +setDefaultReadOnly( false ); +... +tx.commit(); +session.close(); + + + + + If Session.isDefaultReadOnly() returns true, then you can + use Query.setReadOnly( false ) and Criteria.setReadOnly( false ) + to override this session setting and load entities that are + not read-only. + + +
+ +
+ Making a persistent entity read-only + + + Persistent entities of immutable classes are automatically + made read-only. + + + + + To make a persistent entity or proxy read-only, call: + + Session.setReadOnly(entityOrProxy, true) + + + To change a read-only entity or proxy of a mutable class so + it is no longer read-only, call: + + Session.setReadOnly(entityOrProxy, false) + + + + When a read-only entity or proxy is changed so it is no longer + read-only, Hibernate assumes that the current state of the + read-only entity is consistent with its database representation. + If this is not true, then any non-flushed changes made before + or while the entity was read-only, will be ignored. + + + + + To throw away non-flushed changes and make the persistent entity + consistent with its database representation, call: + session.refresh( entity ); + + + To flush changes made before or while the entity + was read-only and make the database representation + consistent with the current state of the persistent + entity: + + +// evict the read-only entity so it is detached +session.evict( entity ); + +// make the detached entity (with the non-flushed changes) persistent +session.update( entity ); + +// now entity is no longer read-only and its changes can be flushed +s.flush(); + +
+
+ +
+ Read-only affect on property type + + + The following table summarizes how different property types are + affected by making an entity read-only. + + + + Affect of read-only entity on property types + + + + + + Property/Association Type + Changes flushed to DB? + + + + + + Simple + + () + + + no* + + + + Unidirectional one-to-one + Unidirectional many-to-one + + () + + + + + no* + no* + + + + + Unidirectional one-to-many + Unidirectional many-to-many + + () + + + + yes + yes + + + + + Bidirectional one-to-one + + () + + + only if the owning entity is not read-only* + + + + Bidirectional one-to-many/many-to-one + inverse collection + non-inverse collection + + () + + + + + only added/removed entities that are not read-only* + yes + + + + + Bidirectional many-to-many + + () + + + yes + + + +
+ + + * Behavior is different when the entity having the property/association + is read-only, compared to when it is not read-only. + + +
+ Simple properties + + + When a persistent object is read-only, Hibernate does not + dirty-check simple properties. + + + + Hibernate will not synchronize simple property state changes + to the database. If you have automatic versioning, Hibernate + will not increment the version if any simple properties change. + + + +Session session = factory.openSession(); +Transaction tx = session.beginTransaction(); + +// get a contract and make it read-only +Contract contract = ( Contract ) session.get( Contract.class, contractId ); +session.setReadOnly( contract, true ); + +// contract.getCustomerName() is "Sherman" +contract.setCustomerName( "Yogi" ); +tx.commit(); + +tx = session.beginTransaction(); + +contract = ( Contract ) session.get( Contract.class, contractId ); +// contract.getCustomerName() is still "Sherman" +... +tx.commit(); +session.close(); + + +
+ +
+ Unidirectional associations + +
+ Unidirectional one-to-one and many-to-one + + + Hibernate treats unidirectional one-to-one and many-to-one + associations in the same way when the owning entity is + read-only. + + + + We use the term unidirectional single-ended + association when referring to functionality + that is common to unidirectional one-to-one and many-to-one + associations. + + + + Hibernate does not dirty-check unidirectional single-ended + associations when the owning entity is read-only. + + + + If you change a read-only entity's reference to a + unidirectional single-ended association to null, + or to refer to a different entity, that change + will not be flushed to the database. + + + + + If an entity is of an immutable class, + then its references to unidirectional single-ended + associations must be assigned when that + entity is first created. Because the entity is + automatically made read-only, these references can + not be updated. + + + + + If automatic versioning is used, Hibernate will not + increment the version due to local changes to + unidirectional single-ended associations. + + + + In the following examples, Contract has a unidirectional + many-to-one association with Plan. Contract cascades save and + update operations to the association. + + + + The following shows that changing a read-only entity's + many-to-one association reference to null has no effect + on the entity's database representation. + + +// get a contract with an existing plan; +// make the contract read-only and set its plan to null +tx = session.beginTransaction(); +Contract contract = ( Contract ) session.get( Contract.class, contractId ); +session.setReadOnly( contract, true ); +contract.setPlan( null ); +tx.commit(); + +// get the same contract +tx = session.beginTransaction(); +contract = ( Contract ) session.get( Contract.class, contractId ); + +// contract.getPlan() still refers to the original plan; + +tx.commit(); +session.close(); + + + The following shows that, even though + an update to a read-only entity's many-to-one + association has no affect on the entity's + database representation, flush still cascades + the save-update operation to the locally + changed association. + + +// get a contract with an existing plan; +// make the contract read-only and change to a new plan +tx = session.beginTransaction(); +Contract contract = ( Contract ) session.get( Contract.class, contractId ); +session.setReadOnly( contract, true ); +Plan newPlan = new Plan( "new plan" +contract.setPlan( newPlan); +tx.commit(); + +// get the same contract +tx = session.beginTransaction(); +contract = ( Contract ) session.get( Contract.class, contractId ); +newPlan = ( Contract ) session.get( Plan.class, newPlan.getId() ); + +// contract.getPlan() still refers to the original plan; +// newPlan is non-null because it was persisted when +// the previous transaction was committed; + +tx.commit(); +session.close(); + +
+ +
+ Unidirectional one-to-many and many-to-many + + + Hibernate treats unidirectional one-to-many + and many-to-many associations owned by a read-only + entity the same as when owned by an entity that is not + read-only. + + + + Hibernate dirty-checks unidirectional one-to-many and + many-to-many associations; + + + + The collection can contain entities that + are read-only, as well as entities + that are not read-only. + + + + Entities can be added and removed from the + collection; changes are flushed to the database. + + + + If automatic versioning is used, Hibernate will + update the version due to changes in the collection + if they dirty the owning entity. + + +
+ +
+ +
+ Bidirectional associations + +
+ Bidirectional one-to-one + + + If a read-only entity owns a bidirectional + one-to-one association: + + + + + + Hibernate does not dirty-check the association. + + + + + updates that change the association reference + to null or to refer to a different entity + will not be flushed to the database. + + + + + If automatic versioning is used, Hibernate will not + increment the version due to local changes to + the association. + + + + + + + If an entity is of an immutable class, + and it owns a bidirectional one-to-one + association, then its reference must be + assigned when that entity is first created. + Because the entity is automatically made + read-only, these references cannot be updated. + + + + + When the owner is not read-only, Hibernate treats + an association with a read-only entity the same + as when the association is with an entity that is + not read-only. + + +
+ +
+ Bidirectional one-to-many/many-to-one + + + A read-only entity has no impact on a bidirectional + one-to-many/many-to-one association if: + + + + + + the read-only entity is on the one-to-many side + using an inverse collection; + + + + + the read-only entity is on the one-to-many side + using a non-inverse collection; + + + + + the one-to-many side uses a non-inverse collection + that contains the read-only entity + + + + + + When the one-to-many side uses an inverse collection: + + + + + + a read-only entity can only be added to the collection + when it is created; + + + + + a read-only entity can only be removed from the + collection by an orphan delete or by explicitly + deleting the entity. + + + + +
+ +
+ Bidirectional many-to-many + + Hibernate treats bidirectional many-to-many + associations owned by a read-only entity the + same as when owned by an entity that is not + read-only. + + + + Hibernate dirty-checks bidirectional many-to-many + associations. + + + + The collection on either side of the association + can contain entities that are read-only, as well + as entities that are not read-only. + + + + Entities are added and removed from both sides + of the collection; changes are flushed to the + database. + + + + If automatic versioning is used, Hibernate will + update the version due to changes in both sides of + the collection if they dirty the entity owning the + respective collections. + + +
+ +
+
+