HIBERNATE - Relational Persistence for Idiomatic Java
http://docs.jboss.org/hibernate/orm/4.3/manual/en-US/html_single/[2014-02-24 10:49:28]
Hibernate supports a broad range of collection mappings, a set being most common. For a many-to -many
association, or n:m entity relationship, an association table is required. Each row in this table represents a
link between a person and an event. The table name is declared using the
table attribute of the set
element. The identifier column name in the association, for the person side, is defined with the key
element, the column name for the event's side with the column attribute of the many-to-many. You also
have to tell Hibernate the class of the objects in your collection (the class on the other side of the collection
of references).
The database schema for this mapping is therefore:
1.2.3. Working the association
Now we will bring some people and events together in a new method in EventManager :
After loading a
Person and an Event, simply modify the collection using the normal collection methods.
There is no explicit call to
update() or save(); Hibernate automatically detects that the collection has been
modified and needs to be updated. This is called automatic dirty checking. You can also try it by modifying
the name or the date property of any of your objects. As long as they are in persistent state, that is, bound
to a particular Hibernate
org.hibernate.Session, Hibernate monitors any changes and executes SQL in a
write-behind fashion. The process of synchronizing the memory state with the database, usually only at the
end of a unit of work, is called flushing. In our code, the unit of work ends with a commit, or rollback, of
the database transaction.
You can load person and event in different units of work. Or you can modify an object outside of a
org.hibernate.Session, when it is not in persistent state (if it was persistent before, this state is called
detached). You can even modify a collection when it is detached:
The call to
makes a detached object persistent again by binding it to a new unit of work, so any
<key column="PERSON_ID"/>
<many-to-many column="EVENT_ID" class="Event"/>
</set>
</class>
_____________ __________________
| | | | _____________
| EVENTS | | PERSON_EVENT | | |
|_____________| |__________________| | PERSON |
| | | | |_____________|
| *EVENT_ID | <--> | *EVENT_ID | | |
| EVENT_DATE | | *PERSON_ID | <--> | *PERSON_ID |
| TITLE | |__________________| | AGE |
|_____________| | FIRSTNAME |
| LASTNAME |
|_____________|
private void addPersonToEvent(Long personId, Long eventId) {
Session session = HibernateUtil.getSessionFactory().getCurrentSession();
session.beginTransaction();
Person aPerson = (Person) session.load(Person.class, personId);
Event anEvent = (Event) session.load(Event.class, eventId);
aPerson.getEvents().add(anEvent);
session.getTransaction().commit();
}
private void addPersonToEvent(Long personId, Long eventId) {
Session session = HibernateUtil.getSessionFactory().getCurrentSession();
session.beginTransaction();
Person aPerson = (Person) session
.createQuery("select p from Person p left join fetch p.events where p.id =
:pid")
.setParameter("pid", personId)
.uniqueResult(); // Eager fetch the collection so we can use it detached
Event anEvent = (Event) session.load(Event.class, eventId);
session.getTransaction().commit();
// End of first unit of work
aPerson.getEvents().add(anEvent); // aPerson (and its collection) is detached
// Begin second unit of work
Session session2 = HibernateUtil.getSessionFactory().getCurrentSession();
session2.beginTransaction();
session2.update(aPerson); // Reattachment of aPerson
session2.getTransaction().commit();
}