Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
lect17-hibernate-orm / more / hibernate_reference.pdf
Скачиваний:
54
Добавлен:
18.03.2015
Размер:
2.2 Mб
Скачать

Chapter 11. Working with objects

• from Session.flush()

The SQL statements are issued in the following order:

1.all entity insertions in the same order the corresponding objects were saved using

Session.save()

2.all entity updates

3.all collection deletions

4.all collection element deletions, updates and insertions

5.all collection insertions

6.all entity deletions in the same order the corresponding objects were deleted using

Session.delete()

An exception is that objects using native ID generation are inserted when they are saved.

Except when you explicitly flush(), there are absolutely no guarantees about when the Session executes the JDBC calls, only the order in which they are executed. However, Hibernate does guarantee that the Query.list(..) will never return stale or incorrect data.

It is possible to change the default behavior so that flush occurs less frequently. The FlushMode class defines three different modes: only flush at commit time when the Hibernate Transaction

API is used, flush automatically using the explained routine, or never flush unless flush() is called explicitly. The last mode is useful for long running units of work, where a Session is kept open and disconnected for a long time (see Section 13.3.2, “Extended session and automatic versioning”).

sess = sf.openSession();

Transaction tx = sess.beginTransaction(); sess.setFlushMode(FlushMode.COMMIT); // allow queries to return stale state

Cat izi = (Cat) sess.load(Cat.class, id); izi.setName(iznizi);

// might return stale data

sess.find("from Cat as cat left outer join cat.kittens kitten");

// change to izi is not flushed!

...

tx.commit(); // flush occurs sess.close();

During flush, an exception might occur (e.g. if a DML operation violates a constraint). Since handling exceptions involves some understanding of Hibernate's transactional behavior, we discuss it in Chapter 13, Transactions and Concurrency.

11.11. Transitive persistence

It is quite cumbersome to save, delete, or reattach individual objects, especially if you deal with a graph of associated objects. A common case is a parent/child relationship. Consider the following example:

226

Transitive persistence

If the children in a parent/child relationship would be value typed (e.g. a collection of addresses or strings), their life cycle would depend on the parent and no further action would be required for convenient "cascading" of state changes. When the parent is saved, the value-typed child objects are saved and when the parent is deleted, the children will be deleted, etc. This works for operations such as the removal of a child from the collection. Since value-typed objects cannot have shared references, Hibernate will detect this and delete the child from the database.

Now consider the same scenario with parent and child objects being entities, not value-types (e.g. categories and items, or parent and child cats). Entities have their own life cycle and support shared references. Removing an entity from the collection does not mean it can be deleted), and there is by default no cascading of state from one entity to any other associated entities. Hibernate does not implement persistence by reachability by default.

For each basic operation of the Hibernate session - including persist(), merge(),

saveOrUpdate(), delete(), lock(), refresh(), evict(), replicate() - there is a

corresponding cascade style. Respectively, the cascade styles are named create, merge, save-update, delete, lock, refresh, evict, replicate. If you want an operation to be cascaded along an association, you must indicate that in the mapping document. For example:

<one-to-one name="person" cascade="persist"/>

Cascade styles my be combined:

<one-to-one name="person" cascade="persist,delete,lock"/>

You can even use cascade="all" to specify that all operations should be cascaded along the association. The default cascade="none" specifies that no operations are to be cascaded.

In case you are using annotatons you probably have noticed the cascade attribute taking an array of CascadeType as a value. The cascade concept in JPA is very is similar to the transitive persistence and cascading of operations as described above, but with slightly different semantics and cascading types:

CascadeType.PERSIST: cascades the persist (create) operation to associated entities persist() is called or if the entity is managed

CascadeType.MERGE: cascades the merge operation to associated entities if merge() is called or if the entity is managed

CascadeType.REMOVE: cascades the remove operation to associated entities if delete() is called

CascadeType.REFRESH: cascades the refresh operation to associated entities if refresh() is called

CascadeType.DETACH: cascades the detach operation to associated entities if detach() is called

227

Chapter 11. Working with objects

CascadeType.ALL: all of the above

Note

CascadeType.ALL also covers Hibernate specific operations like save-update, lock

etc...

A special cascade style, delete-orphan, applies only to one-to-many associations, and indicates that the delete() operation should be applied to any child object that is removed from the association. Using annotations there is no CascadeType.DELETE-ORPHAN equivalent. Instead you can use the attribute orphanRemoval as seen in Example 11.4, “@OneToMany with orphanRemoval”. If an entity is removed from a @OneToMany collection or an associated entity is dereferenced from a @OneToOne association, this associated entity can be marked for deletion if orphanRemoval is set to true.

Example 11.4. @OneToMany with orphanRemoval

@Entity

public class Customer {

private Set<Order> orders;

@OneToMany(cascade=CascadeType.ALL, orphanRemoval=true)

public Set<Order> getOrders() { return orders; }

public void setOrders(Set<Order> orders) { this.orders = orders; }

[...]

}

@Entity

public class Order { ... }

Customer customer = em.find(Customer.class, 1l);

Order order = em.find(Order.class, 1l);

customer.getOrders().remove(order); //order will be deleted by cascade

Recommendations:

It does not usually make sense to enable cascade on a many-to-one or many-to-many association. In fact the @ManyToOne and @ManyToMany don't even offer aorphanRemoval attribute. Cascading is often useful for one-to-one and one-to-many associations.

• If the

child

object's

lifespan

is bounded

by the

lifespan of the parent

object,

make

it a

life cycle

object by

specifying

cascade="all,delete-

orphan"(@OneToMany(cascade=CascadeType.ALL, orphanRemoval=true)).

Otherwise, you might not need cascade at all. But if you think that you will often be working with the parent and children together in the same transaction, and you want to save yourself some typing, consider using cascade="persist,merge,save-update".

228

Using metadata

Mapping an association (either a single valued association, or a collection) with cascade="all" marks the association as a parent/child style relationship where save/update/delete of the parent results in save/update/delete of the child or children.

Furthermore, a mere reference to a child from a persistent parent will result in save/update of the child. This metaphor is incomplete, however. A child which becomes unreferenced by its parent is not automatically deleted, except in the case of a one-to-many association mapped with cascade="delete-orphan". The precise semantics of cascading operations for a parent/child

relationship are as follows:

If a parent is passed to persist(), all children are passed to persist()

If a parent is passed to merge(), all children are passed to merge()

If a parent is passed to save(), update() or saveOrUpdate(), all children are passed to saveOrUpdate()

If a transient or detached child becomes referenced by a persistent parent, it is passed to saveOrUpdate()

If a parent is deleted, all children are passed to delete()

If a child is dereferenced by a persistent parent, nothing special happens - the application should explicitly delete the child if necessary - unless cascade="delete-orphan", in which case the "orphaned" child is deleted.

Finally, note that cascading of operations can be applied to an object graph at call time or at flush time. All operations, if enabled, are cascaded to associated entities reachable when the operation is executed. However, save-update and delete-orphan are transitive for all associated entities reachable during flush of the Session.

11.12. Using metadata

Hibernate requires a rich meta-level model of all entity and value types. This model can be useful to the application itself. For example, the application might use Hibernate's metadata to implement a "smart" deep-copy algorithm that understands which objects should be copied (eg. mutable value types) and which objects that should not (e.g. immutable value types and, possibly, associated entities).

Hibernate exposes metadata via the ClassMetadata and CollectionMetadata interfaces and the Type hierarchy. Instances of the metadata interfaces can be obtained from the

SessionFactory.

Cat fritz = ......;

ClassMetadata catMeta = sessionfactory.getClassMetadata(Cat.class);

Object[] propertyValues = catMeta.getPropertyValues(fritz);

String[] propertyNames = catMeta.getPropertyNames();

Type[] propertyTypes = catMeta.getPropertyTypes();

// get a Map of all properties which are not collections or associations Map namedValues = new HashMap();

229

Chapter 11. Working with objects

for ( int i=0; i<propertyNames.length; i++ ) {

if ( !propertyTypes[i].isEntityType() && !propertyTypes[i].isCollectionType() ) {

namedValues.put( propertyNames[i], propertyValues[i] );

}

}

230

Соседние файлы в папке more