Session thirdSession =
HibernateUtil.getSessionFactory().openSession();
Transaction thirdTransaction = thirdSession.beginTransaction();
// msgId holds the identifier value of the first message
message = (Message) thirdSession.get( Message. class , msgId );
message.setText( " Greetings Earthling " );
message.setNextMessage(
new Message( " Take me to your leader (please) " )
);
thirdTransaction.commit();
thirdSession.close();
This code calls three SQL statements inside the same database transaction:
from MESSAGES m
where m.MESSAGE_ID = 1
insert into MESSAGES (MESSAGE_ID, MESSAGE_TEXT, NEXT_MESSAGE_ID)
values ( 2 , ' Take me to your leader (please) ' , null )
update MESSAGES
set MESSAGE_TEXT = ' Greetings Earthling ' , NEXT_MESSAGE_ID = 2
where MESSAGE_ID = 1
Notice how Hibernate detected the modification to the text and nextMessage
properties of the first message and automatically updated the database—Hibernate
did automatic dirty checking. This feature saves you the effort of explicitly asking
Hibernate to update the database when you modify the state of an object
inside a unit of work. Similarly, the new message was made persistent when a reference
was created from the first message. This feature is called cascading save. It
saves you the effort of explicitly making the new object persistent by calling
save(), as long as it’s reachable by an already persistent instance.
Also notice that the ordering of the SQL statements isn’t the same as the order
in which you set property values. Hibernate uses a sophisticated algorithm to
determine an efficient ordering that avoids database foreign key constraint violations
but is still sufficiently predictable to the user. This feature is called transactional
write-behind.