FileDocCategorySizeDatePackage
EntityManagerImpl.javaAPI DocGlassfish v2 API27740Wed Jul 11 07:15:20 BST 2007oracle.toplink.essentials.internal.ejb.cmp3.base

EntityManagerImpl

public abstract class EntityManagerImpl extends Object

Purpose: Contains the implementation of the EntityManager.

Description: This class provides the implementation for the combined TopLink and EJB3.0 EntityManager class.

Responsibilities:It is responcible for tracking transaction state and the objects within that transaction.

see
javax.persistence.EntityManager
see
oracle.toplink.essentials.ejb.cmp3.EntityManager

Fields Summary
protected TransactionWrapperImpl
transaction
protected boolean
isOpen
protected RepeatableWriteUnitOfWork
extendedPersistenceContext
protected ServerSession
serverSession
protected EntityManagerFactoryImpl
factory
protected boolean
extended
protected boolean
propagatePersistenceContext
Constructors Summary
public EntityManagerImpl(String sessionName, boolean propagatePersistenceContext, boolean extended)
Constructor returns an EntityManager assigned to the a particular ServerSession.

param
sessionName the ServerSession name that should be used. This constructor can potentially throw TopLink exceptions regarding the existence, or errors with the specified session.


       
       
                 
       
    
                                            
          
        this((ServerSession) SessionManager.getManager().getSession(sessionName), null, propagatePersistenceContext, extended);
    
public EntityManagerImpl(ServerSession serverSession, boolean propagatePersistenceContext, boolean extended)
Constructor called from the EntityManagerFactory to create an EntityManager

param
serverSession the serverSession assigned to this deployment.

        this(serverSession, null, propagatePersistenceContext, extended);
    
public EntityManagerImpl(ServerSession serverSession, Map properties, boolean propagatePersistenceContext, boolean extended)
Constructor called from the EntityManagerFactory to create an EntityManager

param
serverSession the serverSession assigned to this deployment. Note: The properties argument is provided to allow properties to be passed into this EntityManager, but there are currently no such properties implemented

        this.serverSession = serverSession;
        detectTransactionWrapper();
        this.extended = true;
        this.propagatePersistenceContext = false;
    
public EntityManagerImpl(EntityManagerFactoryImpl factory, Map properties, boolean propagatePersistenceContext, boolean extended)
Constructor called from the EntityManagerFactory to create an EntityManager

param
factory the EntityMangerFactoryImpl that created this entity manager. Note: The properties argument is provided to allow properties to be passed into this EntityManager, but there are currently no such properties implemented

        this.factory = factory;
        this.serverSession = factory.getServerSession();
        detectTransactionWrapper();
        this.extended = true;
        this.propagatePersistenceContext = false;
    
Methods Summary
protected java.lang.ObjectcheckForTransaction(boolean validateExistence)

        return transaction.checkForTransaction(validateExistence);    
    
public voidclear()
Clear the persistence context, causing all managed entities to become detached. Changes made to entities that have not been flushed to the database will not be persisted.

        try {
            verifyOpen();
            if (this.isExtended()){
                if(this.extendedPersistenceContext != null){
                    if (checkForTransaction(false) == null){
                        // clear all change sets and cache
                        this.extendedPersistenceContext.clearForClose(true);
                        this.extendedPersistenceContext = null;
                    } else {
                        // clear all change sets created after the last flush and cache
                        this.extendedPersistenceContext.clear(true);
                    }
                }

            } else {
                transaction.clear();
            }
        } catch (RuntimeException e) {
            this.setRollbackOnly();
            throw e;
        }
    
public voidclose()

Closes this EntityManager.

After invoking this method, all methods on the instance will throw an {@link IllegalStateException} except for {@link #isOpen}, which will return false .

This should be called when a method is finished with the EntityManager in a bean-managed transaction environment or when executed outside a container. Closing of the EntityManager is handled by the container when using container-managed transactions.

        try {
            verifyOpen();
            isOpen = false;
            factory = null;
            serverSession = null;
            if(extendedPersistenceContext != null) {
                if (checkForTransaction(false) == null){
                    // clear change sets but keep the cache
                    extendedPersistenceContext.clearForClose(false);
                } else {
                    // when commit will be called, all change sets will be cleared, but the cache will be kept
                    extendedPersistenceContext.setShouldClearForCloseInsteadOfResume(true);
                }
                extendedPersistenceContext = null;
            }
        } catch (RuntimeException e) {
            this.setRollbackOnly();
            throw e;
        }
    
public booleancontains(java.lang.Object entity)
Check if the instance belongs to the current persistence context.

param
entity
return
throws
IllegalArgumentException if given Object is not an entity

        try {
            verifyOpen();               
            if (entity == null){
                throw new IllegalArgumentException(ExceptionLocalization.buildMessage("not_an_entity", new Object[] {entity}));
            }
            ClassDescriptor descriptor = (ClassDescriptor)getServerSession().getDescriptors().get(entity.getClass());
            if (descriptor == null  || descriptor.isAggregateDescriptor() || descriptor.isAggregateCollectionDescriptor()){
                throw new IllegalArgumentException(ExceptionLocalization.buildMessage("not_an_entity", new Object[]{entity}));
            }       	
            
            if( (!hasActivePersistenceContext())) {
                return false;
            }
            
            return contains(entity,getActivePersistenceContext(checkForTransaction(false)));
        } catch (RuntimeException e) {
            this.setRollbackOnly();
            throw e;
        }
	
protected booleancontains(java.lang.Object entity, oracle.toplink.essentials.sessions.UnitOfWork uow)
Check if the instance belongs to the current persistence context.

param
entity
param
uow
return

        
        return ((oracle.toplink.essentials.internal.sessions.UnitOfWorkImpl)uow).isObjectRegistered(entity) && 
                !((oracle.toplink.essentials.internal.sessions.UnitOfWorkImpl)uow).isObjectDeleted(entity);
    
protected oracle.toplink.essentials.queryframework.DatabaseQuerycreateNativeQueryInternal(java.lang.String sqlString, java.lang.Class resultType)
This method is used to create a query using SQL. The class, must be the expected return type.

        ReadAllQuery query = new ReadAllQuery(resultType);
        query.setSQLString(sqlString);
        query.setIsUserDefined(true);
        return query;
    
protected oracle.toplink.essentials.queryframework.DatabaseQuerycreateQueryInternal(oracle.toplink.essentials.expressions.Expression expression, java.lang.Class resultType)
This method is used to create a query using a Toplink Expression and the return type.

        ReadAllQuery query = new ReadAllQuery(resultType);
        query.setSelectionCriteria(expression);
        return query;
    
protected voiddetectTransactionWrapper()

        if (this.serverSession.hasExternalTransactionController()){
            setJTATransactionWrapper();
        } else {
            setEntityTransactionWrapper();
        }
     
public java.lang.Objectfind(java.lang.String entityName, java.lang.Object primaryKey)
Find by primary key.

param
entityName
param
primaryKey
return
the found entity instance
throws
IllegalArgumentException if the first argument does not indicate an entity or if the second argument is not a valid type for that entity's primaryKey

        try {
            verifyOpen();
            Session session = getActiveSession();
            ClassDescriptor descriptor = session.getDescriptorForAlias(entityName);
            if (descriptor == null || descriptor.isAggregateDescriptor() || descriptor.isAggregateCollectionDescriptor()){
                throw new IllegalArgumentException(ExceptionLocalization.buildMessage("unknown_entitybean_name", new Object[] {entityName}));
            }
            if (primaryKey == null){ //gf721 - check for null PK
                throw new IllegalArgumentException(ExceptionLocalization.buildMessage("null_pk"));
            }
            if ( ((CMP3Policy)descriptor.getCMPPolicy()).getPKClass() != null && !((CMP3Policy)descriptor.getCMPPolicy()).getPKClass().isAssignableFrom(primaryKey.getClass())){
                throw new IllegalArgumentException(ExceptionLocalization.buildMessage("invalid_pk_class", new Object[] {((CMP3Policy)descriptor.getCMPPolicy()).getPKClass(), primaryKey.getClass()}));
            }
            return findInternal(descriptor, session, primaryKey);
        } catch (RuntimeException e) {
            this.setRollbackOnly();
            throw e;
        }
	
protected java.lang.ObjectfindInternal(java.lang.Class entityClass, java.lang.Object primaryKey)
Find by primary key.

param
entityClass
param
primaryKey
return
the found entity instance or null if the entity does not exist
throws
IllegalArgumentException if the first argument does not denote an entity type or the second argument is not a valid type for that entity's primary key

	    Session session = getActiveSession();
	    ClassDescriptor descriptor = session.getDescriptor(entityClass);
	    if (descriptor == null || descriptor.isAggregateDescriptor() || descriptor.isAggregateCollectionDescriptor()){
	        throw new IllegalArgumentException(ExceptionLocalization.buildMessage("unknown_bean_class", new Object[]{ entityClass}));
	    }
	    if (primaryKey == null){ //gf721 - check for null PK
	    	throw new IllegalArgumentException(ExceptionLocalization.buildMessage("null_pk"));
	    }
        if ( ((CMP3Policy)descriptor.getCMPPolicy()).getPKClass() != null && !((CMP3Policy)descriptor.getCMPPolicy()).getPKClass().isAssignableFrom(primaryKey.getClass())){
            throw new IllegalArgumentException(ExceptionLocalization.buildMessage("invalid_pk_class", new Object[] {((CMP3Policy)descriptor.getCMPPolicy()).getPKClass(), primaryKey.getClass()}));
        }
        return findInternal(descriptor, session, primaryKey);
	
protected static java.lang.ObjectfindInternal(oracle.toplink.essentials.descriptors.ClassDescriptor descriptor, oracle.toplink.essentials.sessions.Session session, java.lang.Object primaryKey)
Find by primary key.

param
descriptor
param
session
param
primaryKey
return
the found entity instance or null if the entity does not exist
throws
IllegalArgumentException if the first argument does not denote an entity type or the second argument is not a valid type for that entity's primary key

        Vector pk;
        if(primaryKey instanceof Vector) {
            pk = (Vector)primaryKey;
        } else {
            pk = ((CMP3Policy) descriptor.getCMPPolicy()).createPkVectorFromKey(primaryKey, (oracle.toplink.essentials.internal.sessions.AbstractSession)session);
        }
	    ReadObjectQuery query = new ReadObjectQuery(descriptor.getJavaClass());
	    query.setSelectionKey(pk);
        query.conformResultsInUnitOfWork();
	    return session.executeQuery(query);
	
public voidflush()
Synchronize the persistence context with the underlying database.

        try {
            verifyOpen();        
        
            try {
                getActivePersistenceContext(checkForTransaction(true)).writeChanges();
            }catch (RuntimeException e) {
                if (TopLinkException.class.isAssignableFrom(e.getClass())){
                    throw new PersistenceException(e);
                }
                throw e;
            }        
        } catch (RuntimeException e) {
            this.setRollbackOnly();
            throw e;
        }
	
public oracle.toplink.essentials.internal.ejb.cmp3.base.RepeatableWriteUnitOfWorkgetActivePersistenceContext(java.lang.Object txn)

        if (this.isExtended()){
            // use local uow as it will be local to this EM and not on the txn
            if (this.extendedPersistenceContext == null || !this.extendedPersistenceContext.isActive()){
                this.extendedPersistenceContext = new RepeatableWriteUnitOfWork(this.serverSession.acquireClientSession());
                this.extendedPersistenceContext.setResumeUnitOfWorkOnTransactionCompletion(true);
                this.extendedPersistenceContext.setShouldCascadeCloneToJoinedRelationship(true);
                if (txn != null) {
                    // if there is an active txn we must register with it on creation of PC
                    transaction.registerUnitOfWorkWithTxn(this.extendedPersistenceContext);
                }
            }
            return this.extendedPersistenceContext;
        }else{
            return getTransactionalUnitOfWork_new(txn);
        }
    
public oracle.toplink.essentials.sessions.SessiongetActiveSession()
This method returns the current session to the requestor. The current session will be a the active UnitOfWork within a transaction and will be a 'scrap' UnitOfWork outside of a transaction. The caller is conserned about the results then the getSession() or getUnitOfWork() API should be called.

        Object txn = checkForTransaction(false);
        if ( txn == null && ! this.isExtended() ){
            return this.serverSession.acquireNonSynchronizedUnitOfWork();
        }else{
            return getActivePersistenceContext(txn);
        }
        
    
public java.lang.ObjectgetDelegate()
Return the underlying provider object for the EntityManager, if available. The result of this method is implementation specific.

        try {
            verifyOpen();
            return this;
        } catch (RuntimeException e) {
            this.setRollbackOnly();
            throw e;
        }
    
public oracle.toplink.essentials.threetier.ServerSessiongetServerSession()
Return the underlying server session

        return this.serverSession;
    
public oracle.toplink.essentials.sessions.SessiongetSession()
This method will return a Session outside of a transaction and null within a transaction.

        if (checkForTransaction(false) == null){
            return this.serverSession.acquireNonSynchronizedUnitOfWork();
        }
        return null;
    
protected oracle.toplink.essentials.internal.ejb.cmp3.base.RepeatableWriteUnitOfWorkgetTransactionalUnitOfWork_new(java.lang.Object tnx)

        return transaction.getTransactionalUnitOfWork(tnx);
    
public oracle.toplink.essentials.sessions.UnitOfWorkgetUnitOfWork()
This method will return the active UnitOfWork

        return getActivePersistenceContext(checkForTransaction(false));
    
private booleanhasActivePersistenceContext()

        if (isExtended() && (this.extendedPersistenceContext == null || !this.extendedPersistenceContext.isActive())) 
            return false;
        else 
            return true;
    
public booleanisExtended()
Indicates if this EntityManager is an extended Persistence Context

        return this.extended;
    
public abstract booleanisFlushModeAUTO()
Internal method. Indicates whether flushMode is AUTO.

return
boolean

public booleanisOpen()
Indicates whether or not this entity manager is open. Returns true until a call to {@link #close} is made.

        return isOpen && factory.isOpen();
    
public voidjoinTransaction()
Indicate to the EntityManager that a JTA transaction is active. This method should be called on a JTA application managed EntityManager that was created outside the scope of the active transaction to associate it with the current JTA transaction.

throws
TransactionRequiredException if there is no transaction.

        try {
            verifyOpen();               
            transaction.registerUnitOfWorkWithTxn(getActivePersistenceContext(checkForTransaction(true)));
        } catch (RuntimeException e) {
            this.setRollbackOnly();
            throw e;
        }
    
public voidlock(java.lang.Object entity, javax.persistence.LockModeType lockMode)
Set the lock mode for an entity object contained in the persistence context.

param
entity
param
lockMode
throws
PersistenceException if an unsupported lock call is made
throws
IllegalArgumentException if the instance is not an entity or is a detached entity
throws
TransactionRequiredException if there is no transaction

        try {
            verifyOpen();
            RepeatableWriteUnitOfWork context = getActivePersistenceContext(checkForTransaction(!isExtended()));
            ClassDescriptor descriptor = context.getDescriptor(entity);
            OptimisticLockingPolicy lockingPolicy = descriptor.getOptimisticLockingPolicy();
            if ((lockingPolicy == null) || !(lockingPolicy instanceof VersionLockingPolicy)){
                throw new PersistenceException(ExceptionLocalization.buildMessage("ejb30-wrong-lock_called_without_version_locking-index", null));
            }
            context.forceUpdateToVersionField(entity, (lockMode == LockModeType.WRITE));
        } catch (RuntimeException e) {
            this.setRollbackOnly();
            throw e;
        }
    
protected java.lang.ObjectmergeInternal(java.lang.Object entity)
Merge the state of the given entity into the current persistence context, using the unqualified class name as the entity name.

param
entity
return
the instance that the state was merged to
throws
IllegalArgumentException if given Object is not an entity or is a removed entity

        if (entity == null){
        	throw new IllegalArgumentException(ExceptionLocalization.buildMessage("not_an_entity", new Object[] {entity}));
        }
        //gf830 - merging a removed entity should throw exception
        if (getActivePersistenceContext(checkForTransaction(!isExtended())).getDeletedObjects().contains(entity)){ 
        	throw new IllegalArgumentException(ExceptionLocalization.buildMessage("cannot_merge_removed_entity", new Object[]{entity}));
        }
        try {
        	return getActivePersistenceContext(checkForTransaction(!isExtended())).mergeCloneWithReferences(entity, MergeManager.CASCADE_BY_MAPPING, true);
        } catch (oracle.toplink.essentials.exceptions.OptimisticLockException ole) {
            throw new javax.persistence.OptimisticLockException(ole);
        }
	
public voidpersist(java.lang.Object entity)
If in a transaction this method will check for existence and register the object if it is new. The instance of the entity provided will become managed.

param
entity
throws
IllegalArgumentException if the given Object is not an entity

        try {
            verifyOpen();
            if (entity == null){
                throw new IllegalArgumentException(ExceptionLocalization.buildMessage("not_an_entity", new Object[] {entity}));
            }
            try {
                getActivePersistenceContext(checkForTransaction(!isExtended())).registerNewObjectForPersist(entity, new IdentityHashtable());
            } catch (RuntimeException e) {
                if (ValidationException.class.isAssignableFrom(e.getClass())){
                    throw new EntityExistsException(e.getLocalizedMessage() , e);
                }
                throw e;
            }         
        } catch (RuntimeException e) {
            this.setRollbackOnly();
            throw e;
        }
    
public voidrefresh(java.lang.Object entity)
Refresh the state of the instance from the database.

param
entity

        try {
            verifyOpen();
            UnitOfWork uow = getActivePersistenceContext(checkForTransaction(!isExtended()));
            if(!contains(entity, uow)) {
                throw new IllegalArgumentException(ExceptionLocalization.buildMessage("cant_refresh_not_managed_object", new Object[]{entity}));
            }
            ReadObjectQuery query = new ReadObjectQuery();
            query.setSelectionObject(entity);
            query.refreshIdentityMapResult();
            query.cascadeByMapping();
            query.setLockMode(ObjectBuildingQuery.NO_LOCK);
            Object refreshedEntity = null;
            refreshedEntity = uow.executeQuery(query);
            if(refreshedEntity == null) {
                //bug3323, should also invalidate the shared cached object if object not exists in DB.
                uow.getParent().getIdentityMapAccessor().invalidateObject(entity);
                throw new EntityNotFoundException(ExceptionLocalization.buildMessage("entity_no_longer_exists_in_db", new Object[]{entity}));
            }
        } catch (RuntimeException e) {
            this.setRollbackOnly();
            throw e;
        }
	
public voidremove(java.lang.Object entity)
Remove the instance.

param
entity
throws
IllegalArgumentException if Object passed in is not an entity

        try {
            verifyOpen();
			if (entity == null){ //gf732 - check for null
            	throw new IllegalArgumentException(ExceptionLocalization.buildMessage("not_an_entity", new Object[] {entity}));
            }
            try{
                getActivePersistenceContext(checkForTransaction(!isExtended())).performRemove(entity, new IdentityHashtable());
            }catch (RuntimeException e){
                throw e;
            }
        } catch (RuntimeException e) {
            this.setRollbackOnly();
            throw e;
        }
	
public voidremoveExtendedPersistenceContext()
Internal method called by EntityTransactionImpl class in case of transaction rollback. The caller is responsible for releasing extendedPersistenceContext and it's parent.

        this.extendedPersistenceContext = null;
    
protected abstract voidsetEntityTransactionWrapper()

protected abstract voidsetJTATransactionWrapper()

protected voidsetRollbackOnly()
Internal method. Sets transaction to rollback only.

        this.transaction.setRollbackOnlyInternal();        
    
public booleanshouldFlushBeforeQuery()

        Object foundTransaction = checkForTransaction(false);
        if ((foundTransaction!=null) && transaction.shouldFlushBeforeQuery(getActivePersistenceContext(foundTransaction))){
            return true;
        }
        return false;
    
public booleanshouldPropagatePersistenceContext()

        return this.propagatePersistenceContext;
    
public voidverifyOpen()

        if (!isOpen()){
            throw new IllegalStateException(ExceptionLocalization.buildMessage("operation_on_closed_entity_manager"));
        }