HHH-2762 : SessionImplementor.getNonFlushedChanges()/applyNonFlushedChanges() API and initial implementation
git-svn-id: https://svn.jboss.org/repos/hibernate/core/trunk@17948 1b8cb986-b30d-0410-93ca-fae66ebed9b2
This commit is contained in:
parent
13b6de2490
commit
5d3893d290
|
@ -266,7 +266,7 @@ public final class CollectionEntry implements Serializable {
|
|||
}
|
||||
|
||||
void afterDeserialize(SessionFactoryImplementor factory) {
|
||||
loadedPersister = factory.getCollectionPersister(role);
|
||||
loadedPersister = ( factory == null ? null : factory.getCollectionPersister(role) );
|
||||
}
|
||||
|
||||
public boolean wasDereferenced() {
|
||||
|
@ -414,7 +414,7 @@ public final class CollectionEntry implements Serializable {
|
|||
( String ) ois.readObject(),
|
||||
( Serializable ) ois.readObject(),
|
||||
( Serializable ) ois.readObject(),
|
||||
session.getFactory()
|
||||
( session == null ? null : session.getFactory() )
|
||||
);
|
||||
}
|
||||
}
|
|
@ -128,7 +128,7 @@ public final class CollectionKey implements Serializable {
|
|||
( Serializable ) ois.readObject(),
|
||||
( Type ) ois.readObject(),
|
||||
EntityMode.parse( ( String ) ois.readObject() ),
|
||||
session.getFactory()
|
||||
( session == null ? null : session.getFactory() )
|
||||
);
|
||||
}
|
||||
}
|
|
@ -104,7 +104,7 @@ public final class EntityEntry implements Serializable {
|
|||
final boolean isBeingReplicated,
|
||||
final boolean loadedWithLazyPropertiesUnfetched) {
|
||||
this.entityName = entityName;
|
||||
this.persister = factory.getEntityPersister( entityName );
|
||||
this.persister = ( factory == null ? null : factory.getEntityPersister( entityName ) );
|
||||
this.id = id;
|
||||
this.entityMode = entityMode;
|
||||
this.status = status;
|
||||
|
@ -322,7 +322,7 @@ public final class EntityEntry implements Serializable {
|
|||
ObjectInputStream ois,
|
||||
SessionImplementor session) throws IOException, ClassNotFoundException {
|
||||
return new EntityEntry(
|
||||
session.getFactory(),
|
||||
( session == null ? null : session.getFactory() ),
|
||||
( String ) ois.readObject(),
|
||||
( Serializable ) ois.readObject(),
|
||||
EntityMode.parse( ( String ) ois.readObject() ),
|
||||
|
|
|
@ -171,7 +171,7 @@ public final class EntityKey implements Serializable {
|
|||
( String ) ois.readObject(),
|
||||
( Type ) ois.readObject(),
|
||||
ois.readBoolean(),
|
||||
session.getFactory(),
|
||||
( session == null ? null : session.getFactory() ),
|
||||
EntityMode.parse( ( String ) ois.readObject() )
|
||||
);
|
||||
}
|
||||
|
|
|
@ -0,0 +1,49 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* Copyright (c) 2009, Red Hat Middleware LLC or third-party contributors as
|
||||
* indicated by the @author tags or express copyright attribution
|
||||
* statements applied by the authors. All third-party contributions are
|
||||
* distributed under license by Red Hat Middleware LLC.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use, modify,
|
||||
* copy, or redistribute it subject to the terms and conditions of the GNU
|
||||
* Lesser General Public License, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this distribution; if not, write to:
|
||||
* Free Software Foundation, Inc.
|
||||
* 51 Franklin Street, Fifth Floor
|
||||
* Boston, MA 02110-1301 USA
|
||||
*/
|
||||
package org.hibernate.engine;
|
||||
|
||||
/**
|
||||
* This interface defines the public API for changes to an EventSource that have not
|
||||
* been flushed to the database.
|
||||
*
|
||||
* @author Gail Badner
|
||||
*/
|
||||
|
||||
import java.io.Serializable;
|
||||
import org.hibernate.event.EventSource;
|
||||
|
||||
public interface NonFlushedChanges extends Serializable {
|
||||
|
||||
/**
|
||||
* Extracts the non-flushed Changes from an EventSource into this NonFlushedChanges object.
|
||||
* <p>
|
||||
* @param source
|
||||
*/
|
||||
void extractFromSession(EventSource source);
|
||||
|
||||
/**
|
||||
* Remove the non-flushed changes from this NonFlushedChanges object.
|
||||
*/
|
||||
void clear();
|
||||
}
|
|
@ -287,6 +287,24 @@ public interface SessionImplementor extends Serializable {
|
|||
*/
|
||||
int executeNativeUpdate(NativeSQLQuerySpecification specification, QueryParameters queryParameters) throws HibernateException;
|
||||
|
||||
|
||||
/**
|
||||
* Return changes to this session that have not been flushed yet.
|
||||
*
|
||||
* @return The non-flushed changes.
|
||||
*/
|
||||
public NonFlushedChanges getNonFlushedChanges() throws HibernateException;
|
||||
|
||||
/**
|
||||
* Apply non-flushed changes from a different session to this session. It is assumed
|
||||
* that this SessionImpl is "clean" (e.g., has no non-flushed changes, no cached entities,
|
||||
* no cached collections, no queued actions). The specified NonFlushedChanges object cannot
|
||||
* be bound to any session.
|
||||
* <p/>
|
||||
* @param nonFlushedChanges the non-flushed changes
|
||||
*/
|
||||
public void applyNonFlushedChanges(NonFlushedChanges nonFlushedChanges) throws HibernateException;
|
||||
|
||||
// copied from Session:
|
||||
|
||||
public EntityMode getEntityMode();
|
||||
|
|
|
@ -0,0 +1,109 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* Copyright (c) 2009, Red Hat Middleware LLC or third-party contributors as
|
||||
* indicated by the @author tags or express copyright attribution
|
||||
* statements applied by the authors. All third-party contributions are
|
||||
* distributed under license by Red Hat Middleware LLC.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use, modify,
|
||||
* copy, or redistribute it subject to the terms and conditions of the GNU
|
||||
* Lesser General Public License, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this distribution; if not, write to:
|
||||
* Free Software Foundation, Inc.
|
||||
* 51 Franklin Street, Fifth Floor
|
||||
* Boston, MA 02110-1301 USA
|
||||
*/
|
||||
package org.hibernate.impl;
|
||||
|
||||
/**
|
||||
* An implementation of NonFlushedChanges.
|
||||
*
|
||||
* @author Gail Badner
|
||||
*/
|
||||
|
||||
import org.hibernate.engine.NonFlushedChanges;
|
||||
import org.hibernate.engine.ActionQueue;
|
||||
import org.hibernate.engine.StatefulPersistenceContext;
|
||||
import org.hibernate.event.EventSource;
|
||||
import org.hibernate.AssertionFailure;
|
||||
import org.hibernate.EntityMode;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.HashMap;
|
||||
import java.io.Serializable;
|
||||
import java.io.ObjectInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.ObjectOutputStream;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public final class NonFlushedChangesImpl implements NonFlushedChanges {
|
||||
|
||||
private static final Logger log = LoggerFactory.getLogger(NonFlushedChangesImpl.class);
|
||||
|
||||
private static class SessionNonFlushedChanges implements Serializable {
|
||||
private transient EntityMode entityMode;
|
||||
private transient ActionQueue actionQueue;
|
||||
private transient StatefulPersistenceContext persistenceContext;
|
||||
|
||||
public SessionNonFlushedChanges(EventSource session) {
|
||||
this.entityMode = session.getEntityMode();
|
||||
this.actionQueue = session.getActionQueue();
|
||||
this.persistenceContext = ( StatefulPersistenceContext ) session.getPersistenceContext();
|
||||
}
|
||||
|
||||
private void readObject(ObjectInputStream ois) throws IOException, ClassNotFoundException {
|
||||
ois.defaultReadObject();
|
||||
entityMode = EntityMode.parse( ( String ) ois.readObject() );
|
||||
persistenceContext = StatefulPersistenceContext.deserialize( ois, null );
|
||||
actionQueue = ActionQueue.deserialize( ois, null );
|
||||
}
|
||||
|
||||
private void writeObject(ObjectOutputStream oos) throws IOException {
|
||||
log.trace( "serializing SessionNonFlushedChanges" );
|
||||
oos.defaultWriteObject();
|
||||
oos.writeObject( entityMode.toString() );
|
||||
persistenceContext.serialize( oos );
|
||||
actionQueue.serialize( oos );
|
||||
}
|
||||
}
|
||||
private Map nonFlushedChangesByEntityMode = new HashMap();
|
||||
|
||||
public NonFlushedChangesImpl( EventSource session ) {
|
||||
extractFromSession( session );
|
||||
}
|
||||
|
||||
public void extractFromSession(EventSource session) {
|
||||
if ( nonFlushedChangesByEntityMode.containsKey( session.getEntityMode() ) ) {
|
||||
throw new AssertionFailure( "Already has non-flushed changes for entity mode: " + session.getEntityMode() );
|
||||
}
|
||||
nonFlushedChangesByEntityMode.put( session.getEntityMode(), new SessionNonFlushedChanges( session ) );
|
||||
}
|
||||
|
||||
private SessionNonFlushedChanges getSessionNonFlushedChanges(EntityMode entityMode) {
|
||||
return ( SessionNonFlushedChanges ) nonFlushedChangesByEntityMode.get( entityMode );
|
||||
}
|
||||
|
||||
/* package-protected */
|
||||
ActionQueue getActionQueue(EntityMode entityMode) {
|
||||
return getSessionNonFlushedChanges( entityMode ).actionQueue;
|
||||
}
|
||||
|
||||
/* package-protected */
|
||||
StatefulPersistenceContext getPersistenceContext(EntityMode entityMode) {
|
||||
return getSessionNonFlushedChanges( entityMode ).persistenceContext;
|
||||
}
|
||||
|
||||
public void clear() {
|
||||
nonFlushedChangesByEntityMode.clear();
|
||||
}
|
||||
}
|
|
@ -28,6 +28,8 @@ import java.io.IOException;
|
|||
import java.io.ObjectInputStream;
|
||||
import java.io.ObjectOutputStream;
|
||||
import java.io.Serializable;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.sql.Connection;
|
||||
import java.sql.SQLException;
|
||||
import java.util.Collection;
|
||||
|
@ -72,6 +74,7 @@ import org.hibernate.engine.ActionQueue;
|
|||
import org.hibernate.engine.CollectionEntry;
|
||||
import org.hibernate.engine.EntityEntry;
|
||||
import org.hibernate.engine.EntityKey;
|
||||
import org.hibernate.engine.NonFlushedChanges;
|
||||
import org.hibernate.engine.PersistenceContext;
|
||||
import org.hibernate.engine.QueryParameters;
|
||||
import org.hibernate.engine.StatefulPersistenceContext;
|
||||
|
@ -127,9 +130,11 @@ import org.hibernate.proxy.LazyInitializer;
|
|||
import org.hibernate.stat.SessionStatistics;
|
||||
import org.hibernate.stat.SessionStatisticsImpl;
|
||||
import org.hibernate.type.Type;
|
||||
import org.hibernate.type.SerializationException;
|
||||
import org.hibernate.util.ArrayHelper;
|
||||
import org.hibernate.util.CollectionHelper;
|
||||
import org.hibernate.util.StringHelper;
|
||||
import org.hibernate.util.SerializationHelper;
|
||||
|
||||
|
||||
/**
|
||||
|
@ -377,6 +382,138 @@ public final class SessionImpl extends AbstractSessionImpl
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return changes to this session and its child sessions that have not been flushed yet.
|
||||
* <p/>
|
||||
* @return The non-flushed changes.
|
||||
*/
|
||||
public NonFlushedChanges getNonFlushedChanges() throws HibernateException {
|
||||
errorIfClosed();
|
||||
checkTransactionSynchStatus();
|
||||
NonFlushedChanges nonFlushedChanges = new NonFlushedChangesImpl( this );
|
||||
if ( childSessionsByEntityMode != null ) {
|
||||
Iterator it = childSessionsByEntityMode.values().iterator();
|
||||
while ( it.hasNext() ) {
|
||||
nonFlushedChanges.extractFromSession( ( EventSource ) it.next() );
|
||||
}
|
||||
}
|
||||
return nonFlushedChanges;
|
||||
}
|
||||
|
||||
/**
|
||||
* Apply non-flushed changes from a different session to this session. It is assumed
|
||||
* that this SessionImpl is "clean" (e.g., has no non-flushed changes, no cached entities,
|
||||
* no cached collections, no queued actions). The specified NonFlushedChanges object cannot
|
||||
* be bound to any session.
|
||||
* <p/>
|
||||
* @param nonFlushedChanges the non-flushed changes
|
||||
*/
|
||||
public void applyNonFlushedChanges(NonFlushedChanges nonFlushedChanges) throws HibernateException {
|
||||
errorIfClosed();
|
||||
checkTransactionSynchStatus();
|
||||
replacePersistenceContext( ( ( NonFlushedChangesImpl ) nonFlushedChanges ).getPersistenceContext( entityMode) );
|
||||
replaceActionQueue( ( ( NonFlushedChangesImpl ) nonFlushedChanges ).getActionQueue( entityMode ) );
|
||||
if ( childSessionsByEntityMode != null ) {
|
||||
for ( Iterator it = childSessionsByEntityMode.values().iterator(); it.hasNext(); ) {
|
||||
( ( SessionImpl ) it.next() ).applyNonFlushedChanges( nonFlushedChanges );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void replacePersistenceContext(StatefulPersistenceContext persistenceContextNew) {
|
||||
if ( persistenceContextNew.getSession() != null ) {
|
||||
throw new IllegalStateException( "new persistence context is already connected to a session " );
|
||||
}
|
||||
persistenceContext.clear();
|
||||
ObjectInputStream ois = null;
|
||||
try {
|
||||
ois = new ObjectInputStream( new ByteArrayInputStream( serializePersistenceContext( persistenceContextNew ) ) );
|
||||
this.persistenceContext = StatefulPersistenceContext.deserialize( ois, this );
|
||||
}
|
||||
catch (IOException ex) {
|
||||
throw new SerializationException( "could not deserialize the persistence context", ex );
|
||||
}
|
||||
catch (ClassNotFoundException ex) {
|
||||
throw new SerializationException( "could not deserialize the persistence context", ex );
|
||||
}
|
||||
finally {
|
||||
try {
|
||||
if (ois != null) ois.close();
|
||||
}
|
||||
catch (IOException ex) {}
|
||||
}
|
||||
}
|
||||
|
||||
private static byte[] serializePersistenceContext(StatefulPersistenceContext pc) {
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream( 512 );
|
||||
ObjectOutputStream oos = null;
|
||||
try {
|
||||
oos = new ObjectOutputStream( baos );
|
||||
( ( StatefulPersistenceContext ) pc ).serialize( oos );
|
||||
}
|
||||
catch (IOException ex) {
|
||||
throw new SerializationException( "could not serialize persistence context", ex );
|
||||
}
|
||||
finally {
|
||||
if ( oos != null ) {
|
||||
try {
|
||||
oos.close();
|
||||
}
|
||||
catch( IOException ex ) {
|
||||
//ignore
|
||||
}
|
||||
}
|
||||
}
|
||||
return baos.toByteArray();
|
||||
}
|
||||
|
||||
private void replaceActionQueue(ActionQueue actionQueueNew) {
|
||||
if ( actionQueue.hasAnyQueuedActions() ) {
|
||||
throw new IllegalStateException( "cannot replace an ActionQueue with queued actions " );
|
||||
}
|
||||
actionQueue.clear();
|
||||
ObjectInputStream ois = null;
|
||||
try {
|
||||
ois = new ObjectInputStream( new ByteArrayInputStream( serializeActionQueue( actionQueueNew ) ) );
|
||||
actionQueue = ActionQueue.deserialize( ois, this );
|
||||
}
|
||||
catch (IOException ex) {
|
||||
throw new SerializationException( "could not deserialize the action queue", ex );
|
||||
}
|
||||
catch (ClassNotFoundException ex) {
|
||||
throw new SerializationException( "could not deserialize the action queue", ex );
|
||||
}
|
||||
finally {
|
||||
try {
|
||||
if (ois != null) ois.close();
|
||||
}
|
||||
catch (IOException ex) {}
|
||||
}
|
||||
}
|
||||
|
||||
private static byte[] serializeActionQueue(ActionQueue actionQueue) {
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream( 512 );
|
||||
ObjectOutputStream oos = null;
|
||||
try {
|
||||
oos = new ObjectOutputStream( baos );
|
||||
actionQueue.serialize( oos );
|
||||
}
|
||||
catch (IOException ex) {
|
||||
throw new SerializationException( "could not serialize action queue", ex );
|
||||
}
|
||||
finally {
|
||||
if ( oos != null ) {
|
||||
try {
|
||||
oos.close();
|
||||
}
|
||||
catch( IOException ex ) {
|
||||
//ignore
|
||||
}
|
||||
}
|
||||
}
|
||||
return baos.toByteArray();
|
||||
}
|
||||
|
||||
public boolean shouldAutoClose() {
|
||||
return isAutoCloseSessionEnabled() && !isClosed();
|
||||
}
|
||||
|
|
|
@ -55,6 +55,7 @@ import org.hibernate.engine.QueryParameters;
|
|||
import org.hibernate.engine.StatefulPersistenceContext;
|
||||
import org.hibernate.engine.Versioning;
|
||||
import org.hibernate.engine.LoadQueryInfluencers;
|
||||
import org.hibernate.engine.NonFlushedChanges;
|
||||
import org.hibernate.engine.query.HQLQueryPlan;
|
||||
import org.hibernate.engine.query.NativeSQLQueryPlan;
|
||||
import org.hibernate.engine.query.sql.NativeSQLQuerySpecification;
|
||||
|
@ -621,6 +622,14 @@ public class StatelessSessionImpl extends AbstractSessionImpl
|
|||
|
||||
public void flush() {}
|
||||
|
||||
public NonFlushedChanges getNonFlushedChanges() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
public void applyNonFlushedChanges(NonFlushedChanges nonFlushedChanges) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
public String getFetchProfile() {
|
||||
return null;
|
||||
}
|
||||
|
|
|
@ -24,10 +24,12 @@
|
|||
*/
|
||||
package org.hibernate.util;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* @author Gavin King
|
||||
*/
|
||||
public class MarkerObject {
|
||||
public class MarkerObject implements Serializable {
|
||||
private String name;
|
||||
|
||||
public MarkerObject(String name) {
|
||||
|
|
Loading…
Reference in New Issue