Movatterモバイル変換


[0]ホーム

URL:


Hibernate.orgCommunity Documentation

Chapter 12. Read-only entities

Table of Contents

12.1. Making persistent entities read-only
12.1.1. Entities of immutable classes
12.1.2. Loading persistent entities as read-only
12.1.3. Loading read-only entities from an HQL query/criteria
12.1.4. Making a persistent entity read-only
12.2. Read-only affect on property type
12.2.1. Simple properties
12.2.2. Unidirectional associations
12.2.3. Bidirectional associations

Important

Hibernate's treatment ofread-only entities may differ from what you may have encountered elsewhere. Incorrect usage may cause unexpected results.

When an entity is read-only:

In some ways, Hibernate treats read-only entities the same as entities that are not read-only:

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, seeSection 12.2, “Read-only affect on property type”.

For details about how to make entities read-only, seeSection 12.1, “Making persistent entities read-only”

Hibernate does some optimizing for read-only entities:

12.1. 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:

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.

Note

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:

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()

Note

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 beforeQuery.list(),Query.uniqueResult(),Query.scroll(), orQuery.iterate()

For an HQL criteria, call:

Criteria.setReadOnly( true );

Criteria.setReadOnly( true ) must be called beforeCriteria.list(),Criteria.uniqueResult(), orCriteria.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.

UsingQuery.setReadOnly( true ) orCriteria.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.

Note

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)

Important

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 detachedsession.evict( entity );// make the detached entity (with the non-flushed changes) persistentsession.update( entity );// now entity is no longer read-only and its changes can be flusheds.flush();

12.2. Read-only affect on property type

The following table summarizes how different property types are affected by making an entity read-only.

Table 12.1. Affect of read-only entity on property types

Property/Association TypeChanges flushed to DB?
Simple

(Section 12.2.1, “Simple properties”)

no*

Unidirectional one-to-one

Unidirectional many-to-one

(Section 12.2.2.1, “Unidirectional one-to-one and many-to-one”)

no*

no*

Unidirectional one-to-many

Unidirectional many-to-many

(Section 12.2.2.2, “Unidirectional one-to-many and many-to-many”)

yes

yes

Bidirectional one-to-one

(Section 12.2.3.1, “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

(Section 12.2.3.2, “Bidirectional one-to-many/many-to-one”)

only added/removed entities that are not read-only*

yes

Bidirectional many-to-many

(Section 12.2.3.3, “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.

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-onlyContract 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();

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 termunidirectional 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.

Note

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 contracttx = 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 plantx = 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 contracttx = 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();

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.

If a read-only entity owns a bidirectional one-to-one association:

Note

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.

A read-only entity has no impact on a bidirectional one-to-many/many-to-one association if:

When the one-to-many side uses an inverse collection:

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.



[8]ページ先頭

©2009-2025 Movatter.jp