An event that occurs for each entity instance at flush time
| Method from org.hibernate.event.def.DefaultFlushEntityEventListener Detail: |
public void checkId(Object object,
EntityPersister persister,
Serializable id,
EntityMode entityMode) throws HibernateException {
if ( id != null && id instanceof DelayedPostInsertIdentifier ) {
// this is a situation where the entity id is assigned by a post-insert generator
// and was saved outside the transaction forcing it to be delayed
return;
}
if ( persister.canExtractIdOutOfEntity() ) {
Serializable oid = persister.getIdentifier( object, entityMode );
if (id==null) {
throw new AssertionFailure("null id in " + persister.getEntityName() + " entry (don't flush the Session after an exception occurs)");
}
if ( !persister.getIdentifierType().isEqual(id, oid, entityMode) ) {
throw new HibernateException(
"identifier of an instance of " +
persister.getEntityName() +
" was altered from " + id +
" to " + oid
);
}
}
}
make sure user didn't mangle the id |
protected void dirtyCheck(FlushEntityEvent event) throws HibernateException {
final Object entity = event.getEntity();
final Object[] values = event.getPropertyValues();
final SessionImplementor session = event.getSession();
final EntityEntry entry = event.getEntityEntry();
final EntityPersister persister = entry.getPersister();
final Serializable id = entry.getId();
final Object[] loadedState = entry.getLoadedState();
int[] dirtyProperties = session.getInterceptor().findDirty(
entity,
id,
values,
loadedState,
persister.getPropertyNames(),
persister.getPropertyTypes()
);
event.setDatabaseSnapshot(null);
final boolean interceptorHandledDirtyCheck;
boolean cannotDirtyCheck;
if ( dirtyProperties==null ) {
// Interceptor returned null, so do the dirtycheck ourself, if possible
interceptorHandledDirtyCheck = false;
cannotDirtyCheck = loadedState==null; // object loaded by update()
if ( !cannotDirtyCheck ) {
// dirty check against the usual snapshot of the entity
dirtyProperties = persister.findDirty( values, loadedState, entity, session );
}
else {
// dirty check against the database snapshot, if possible/necessary
final Object[] databaseSnapshot = getDatabaseSnapshot(session, persister, id);
if ( databaseSnapshot != null ) {
dirtyProperties = persister.findModified(databaseSnapshot, values, entity, session);
cannotDirtyCheck = false;
event.setDatabaseSnapshot(databaseSnapshot);
}
}
}
else {
// the Interceptor handled the dirty checking
cannotDirtyCheck = false;
interceptorHandledDirtyCheck = true;
}
event.setDirtyProperties(dirtyProperties);
event.setDirtyCheckHandledByInterceptor(interceptorHandledDirtyCheck);
event.setDirtyCheckPossible(!cannotDirtyCheck);
}
Perform a dirty check, and attach the results to the event |
protected boolean handleInterception(FlushEntityEvent event) {
SessionImplementor session = event.getSession();
EntityEntry entry = event.getEntityEntry();
EntityPersister persister = entry.getPersister();
Object entity = event.getEntity();
//give the Interceptor a chance to modify property values
final Object[] values = event.getPropertyValues();
final boolean intercepted = invokeInterceptor( session, entity, entry, values, persister );
//now we might need to recalculate the dirtyProperties array
if ( intercepted && event.isDirtyCheckPossible() && !event.isDirtyCheckHandledByInterceptor() ) {
int[] dirtyProperties;
if ( event.hasDatabaseSnapshot() ) {
dirtyProperties = persister.findModified( event.getDatabaseSnapshot(), values, entity, session );
}
else {
dirtyProperties = persister.findDirty( values, entry.getLoadedState(), entity, session );
}
event.setDirtyProperties(dirtyProperties);
}
return intercepted;
}
|
protected boolean invokeInterceptor(SessionImplementor session,
Object entity,
EntityEntry entry,
Object[] values,
EntityPersister persister) {
return session.getInterceptor().onFlushDirty(
entity,
entry.getId(),
values,
entry.getLoadedState(),
persister.getPropertyNames(),
persister.getPropertyTypes()
);
}
|
protected final boolean isUpdateNecessary(FlushEntityEvent event) throws HibernateException {
EntityPersister persister = event.getEntityEntry().getPersister();
Status status = event.getEntityEntry().getStatus();
if ( !event.isDirtyCheckPossible() ) {
return true;
}
else {
int[] dirtyProperties = event.getDirtyProperties();
if ( dirtyProperties!=null && dirtyProperties.length!=0 ) {
return true; //TODO: suck into event class
}
else {
return hasDirtyCollections( event, persister, status );
}
}
}
Performs all necessary checking to determine if an entity needs an SQL update
to synchronize its state to the database. Modifies the event by side-effect!
Note: this method is quite slow, avoid calling if possible! |
public void onFlushEntity(FlushEntityEvent event) throws HibernateException {
final Object entity = event.getEntity();
final EntityEntry entry = event.getEntityEntry();
final EventSource session = event.getSession();
final EntityPersister persister = entry.getPersister();
final Status status = entry.getStatus();
final EntityMode entityMode = session.getEntityMode();
final Type[] types = persister.getPropertyTypes();
final boolean mightBeDirty = entry.requiresDirtyCheck(entity);
final Object[] values = getValues( entity, entry, entityMode, mightBeDirty, session );
event.setPropertyValues(values);
//TODO: avoid this for non-new instances where mightBeDirty==false
boolean substitute = wrapCollections( session, persister, types, values);
if ( isUpdateNecessary( event, mightBeDirty ) ) {
substitute = scheduleUpdate( event ) || substitute;
}
if ( status != Status.DELETED ) {
// now update the object .. has to be outside the main if block above (because of collections)
if (substitute) persister.setPropertyValues( entity, values, entityMode );
// Search for collections by reachability, updating their role.
// We don't want to touch collections reachable from a deleted object
if ( persister.hasCollections() ) {
new FlushVisitor(session, entity).processEntityPropertyValues(values, types);
}
}
}
Flushes a single entity's state to the database, by scheduling
an update action, if necessary |
protected void validate(Object entity,
EntityPersister persister,
Status status,
EntityMode entityMode) {
// validate() instances of Validatable
if ( status == Status.MANAGED && persister.implementsValidatable( entityMode ) ) {
( (Validatable) entity ).validate();
}
}
|