amberconnection.java

来自「RESIN 3.2 最新源码」· Java 代码 · 共 2,682 行 · 第 1/5 页

JAVA
2,682
字号
/* * Copyright (c) 1998-2008 Caucho Technology -- all rights reserved * * This file is part of Resin(R) Open Source * * Each copy or derived work must preserve the copyright notice and this * notice unmodified. * * Resin Open Source is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * Resin Open Source 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, or any warranty * of NON-INFRINGEMENT.  See the GNU General Public License for more * details. * * You should have received a copy of the GNU General Public License * along with Resin Open Source; if not, write to the * *   Free Software Foundation, Inc. *   59 Temple Place, Suite 330 *   Boston, MA 02111-1307  USA * * @author Scott Ferguson */package com.caucho.amber.manager;import com.caucho.amber.AmberException;import com.caucho.amber.AmberObjectNotFoundException;import com.caucho.amber.AmberQuery;import com.caucho.amber.AmberRuntimeException;import com.caucho.amber.cfg.EntityResultConfig;import com.caucho.amber.cfg.NamedNativeQueryConfig;import com.caucho.amber.cfg.SqlResultSetMappingConfig;import com.caucho.amber.collection.AmberCollection;import com.caucho.amber.entity.*;import com.caucho.amber.query.AbstractQuery;import com.caucho.amber.query.QueryCacheKey;import com.caucho.amber.query.QueryParser;import com.caucho.amber.query.ResultSetCacheChunk;import com.caucho.amber.query.UserQuery;import com.caucho.amber.table.AmberTable;import com.caucho.amber.type.EntityType;import com.caucho.config.ConfigException;import com.caucho.ejb.EJBExceptionWrapper;import com.caucho.jca.BeginResource;import com.caucho.jca.CloseResource;import com.caucho.jca.UserTransactionProxy;import com.caucho.jdbc.JdbcMetaData;import com.caucho.util.L10N;import com.caucho.util.LruCache;import javax.persistence.EntityExistsException;import javax.persistence.EntityManagerFactory;import javax.persistence.EntityNotFoundException;import javax.persistence.EntityTransaction;import javax.persistence.FlushModeType;import javax.persistence.LockModeType;import javax.persistence.Query;import javax.persistence.PersistenceException;import javax.persistence.RollbackException;import javax.persistence.TransactionRequiredException;import javax.sql.DataSource;import javax.transaction.Status;import javax.transaction.Synchronization;import javax.transaction.Transaction;import java.lang.reflect.Method;import java.sql.Connection;import java.sql.PreparedStatement;import java.sql.ResultSet;import java.sql.ResultSetMetaData;import java.sql.SQLException;import java.sql.Statement;import java.util.ArrayList;import java.util.List;import java.util.Map;import java.util.Set;import java.util.logging.Level;import java.util.logging.Logger;/** * The entity manager from a entity manager proxy. */public class AmberConnection  implements BeginResource, CloseResource, Synchronization{  private static final L10N L = new L10N(AmberConnection.class);  private static final Logger log    = Logger.getLogger(AmberConnection.class.getName());  private static final Entity []NULL_ENTITIES = new Entity[0];  private AmberPersistenceUnit _persistenceUnit;  private boolean _isRegistered;  private boolean _isThreadConnection;  private Entity []_entities = new Entity[32];  private int _entitiesTop;  private Entity []_txEntities = NULL_ENTITIES;  private int _txEntitiesTop;  private ArrayList<AmberCompletion> _completionList    = new ArrayList<AmberCompletion>();  private ArrayList<AmberCollection> _queries    = new ArrayList<AmberCollection>();  private EntityTransaction _trans;  private long _xid;  private boolean _isInTransaction;  private boolean _isXA;  private boolean _isExtended;  private boolean _isAppManaged;  private Connection _conn;  private Connection _readConn;  private boolean _isAutoCommit = true;  private int _depth;  private LruCache<String,PreparedStatement> _preparedStatementMap    = new LruCache<String,PreparedStatement>(32);  private ArrayList<Statement> _statements = new ArrayList<Statement>();  private EntityKey _entityKey = new EntityKey();  private QueryCacheKey _queryKey = new QueryCacheKey();  private ArrayList<Entity> _mergingEntities = new ArrayList<Entity>();  private boolean _isFlushAllowed = true;  /**   * Creates a manager instance.   */  AmberConnection(AmberPersistenceUnit persistenceUnit,                  boolean isExtended,                  boolean isAppManaged)  {    _persistenceUnit = persistenceUnit;    _isExtended = isExtended;    _isAppManaged = isAppManaged;  }  /**   * Creates a manager instance.   */  AmberConnection(AmberPersistenceUnit persistenceUnit,                  boolean isExtended)  {    this(persistenceUnit, isExtended, false);  }  /**   * Returns the persistence unit.   */  public AmberPersistenceUnit getPersistenceUnit()  {    return _persistenceUnit;  }  /**   * Returns true for JPA.   */  public boolean isJPA()  {    return _persistenceUnit.isJPA();  }  /**   * Set true for a threaded connection.   */  public void initThreadConnection()  {    _isThreadConnection = true;    initJta();  }  public void initJta()  {    // non-jta connections do not register with the local transaction    if (_persistenceUnit.isJta())      register();  }  /**   * Makes the instance managed.   */  public void persist(Object entityObject)  {    RuntimeException exn = null;    try {      if (entityObject == null)        return;      Entity entity = checkEntityType(entityObject, "persist");      checkTransactionRequired("persist");      persistInternal(entity);      // XXX: check spec. for JTA vs. non-JTA behavior and add QA.      // ejb30/persistence/ee/packaging/ejb/resource_local/test14      if (! _persistenceUnit.isJta())        flushInternal();    } catch (RuntimeException e) {      exn = e;    } catch (SQLException e) {      exn = new IllegalStateException(e);    } catch (Exception e) {      exn = new EJBExceptionWrapper(e);    }    if (exn != null) {      if (! _persistenceUnit.isJta()) {        if (_trans != null)          _trans.setRollbackOnly();      }      throw exn;    }  }  /**   * Makes the instance managed called   * from cascading operations.   */  public Object persistFromCascade(Object o)  {    // jpa/0h25, jpa/0i5e    try {      if (o == null)        return null;      Entity entity = (Entity) o;      // jpa/0h25      return persistInternal(entity);    } catch (EntityExistsException e) {      log.log(Level.FINER, e.toString(), e);      // This is not an issue. It is the cascading      // operation trying to persist the source      // entity from the destination end.      return o;    } catch (RuntimeException e) {      throw e;    } catch (SQLException e) {      throw new IllegalStateException(e);    } catch (Exception e) {      throw new EJBExceptionWrapper(e);    }  }  /**   * Merges the state of the entity into the current context.   */  public <T> T merge(T entityT)  {    RuntimeException exn = null;    try {      flushInternal();      // Cannot flush before the merge is complete.      _isFlushAllowed = false;      entityT = recursiveMerge(entityT);    } catch (RuntimeException e) {      exn = e;    } catch (Exception e) {      exn = new EJBExceptionWrapper(e);    } finally {      _isFlushAllowed = true;      try {        flushInternal();      } catch (RuntimeException e) {        if (exn == null)          exn = e;      } catch (Exception e) {        if (exn == null)          exn = new EJBExceptionWrapper(e);      } finally {        _mergingEntities.clear();      }    }    // jpa/0o42, jpa/0o44    if (exn != null)      throw exn;    return entityT;  }  /**   * Remove the instance.   */  public void remove(Object entity)  {    try {      if (entity == null)        return;      Entity instance = checkEntityType(entity, "remove");      checkTransactionRequired("remove");      if (log.isLoggable(Level.FINER))        log.log(Level.FINER, L.l("removing entity class " + instance.getClass().getName() +                                 " PK: " + instance.__caucho_getPrimaryKey() +                                 " state: " + instance.__caucho_getEntityState()));      EntityState state = instance.__caucho_getEntityState();      if (EntityState.P_DELETING.ordinal() <= state.ordinal()) {        if (log.isLoggable(Level.FINER))          log.log(Level.FINER, L.l("remove is ignoring entity in state " + state));        return;      }      // jpa/0k12      if (instance.__caucho_getConnection() == null) {        if (instance.__caucho_getEntityType() == null) {          if (log.isLoggable(Level.FINER))            log.log(Level.FINER, L.l("remove is ignoring entity; performing only cascade post-remove"));          // Ignore this entity; only post-remove child entities.          instance.__caucho_cascadePostRemove(this);          // jpa/0ga7          return;        }        else          throw new IllegalArgumentException(L.l("remove() operation can only be applied to a managed entity. This entity instance '{0}' PK: '{1}' is detached which means it was probably removed or needs to be merged.", instance.getClass().getName(), instance.__caucho_getPrimaryKey()));      }      // jpa/0h25, jpa/0i5e      // Do not flush dependent objects for cascading persistence      // when this entity is being removed.      instance.__caucho_setEntityState(EntityState.P_DELETING);      if (log.isLoggable(Level.FINER))        log.log(Level.FINER, L.l("remove is flushing any lazy cascading operation"));      // jpa/1620      // In particular, required for cascading persistence, since the cascade      // is lazy until flush      // jpa/0h25 flushInternal();      // Cannot flush since the delete is lazy until flush, i.e.:      // remove(A); // (*) __caucho_flush()      // remove(B);      // (*) would break a FK constraint if B has a reference to A.      // jpa/0h26      updateFlushPriority(instance);      // jpa/0h25, jpa/0i5e      // Restores original state.      instance.__caucho_setEntityState(state);      Object oldEntity;      oldEntity = getEntity(instance.getClass(),                            instance.__caucho_getPrimaryKey());      // jpa/0ga4      if (oldEntity == null)        throw new IllegalArgumentException(L.l("remove() operation can only be applied to a managed entity instance."));      if (log.isLoggable(Level.FINER))        log.log(Level.FINER, L.l("remove is performing cascade pre-remove"));      // Pre-remove child entities.      instance.__caucho_cascadePreRemove(this);      if (log.isLoggable(Level.FINER))        log.log(Level.FINER, L.l("remove is performing delete on the target entity"));      delete(instance);      // jpa/0o30: flushes the owning side delete.      // XXX: Cannot flush since the delete is lazy until flush.      // jpa/0h25      // instance.__caucho_flush();      if (log.isLoggable(Level.FINER))        log.log(Level.FINER, L.l("remove is performing cascade post-remove"));      // jpa/0o30      // Post-remove child entities.      instance.__caucho_cascadePostRemove(this);      if (log.isLoggable(Level.FINER))        log.log(Level.FINER, L.l("DONE successful remove for entity class " +                                 instance.getClass().getName() +                                 " PK: " + instance.__caucho_getPrimaryKey()));    } catch (RuntimeException e) {      throw e;    } catch (Exception e) {      throw new EJBExceptionWrapper(e);    }  }  /**   * Find by the primary key.   */  public <T> T find(Class<T> entityClass,                    Object primaryKey)  {    // Do not flush while an entity is being loaded or merged.    boolean oldIsFlushAllowed = _isFlushAllowed;    try {      // Do not flush while loading an entity.      // Broken relationships would not pass the flush validation.      _isFlushAllowed = false;      T entity = (T) load(entityClass, primaryKey, true);      // jpa/0j07      /*      if (! isActiveTransaction()) {        // jpa/0o00        detach();      }      */      return entity;    } catch (AmberObjectNotFoundException e) {      // JPA: should not throw at all, returns null only.      // log.log(Level.FINER, e.toString(), e);      return null;    } catch (RuntimeException e) {      throw e;    } catch (Exception e) {      throw new EJBExceptionWrapper(e);    } finally {      _isFlushAllowed = oldIsFlushAllowed;    }  }  /**   * Find by the primary key.   */  public <T> T getReference(Class<T> entityClass, Object primaryKey)    throws EntityNotFoundException, IllegalArgumentException  {    T reference = null;    try {      // XXX: only needs to get a reference.      reference = (T) load(entityClass, primaryKey, false);      if (reference == null)        throw new EntityNotFoundException(L.l("entity with primary key {0} not found in getReference()", primaryKey));      /*        if (! (entityClass.isAssignableFrom(Entity.class)))          throw new IllegalArgumentException(L.l("getReference() operation can only be applied to an entity class"));      */      return reference;    } catch (EntityNotFoundException e) {      throw e;    } catch (RuntimeException e) {      throw new IllegalArgumentException(e);    } catch (Exception e) {      throw new EJBExceptionWrapper(e);    }  }  /**   * Clears the connection   */  public void clear()  {    _entitiesTop = 0;    _txEntitiesTop = 0;  }  /**   * Creates a query.   */  public Query createQuery(String sql)  {    try {      AbstractQuery queryProgram = parseQuery(sql, false);      return new QueryImpl(queryProgram, this);    } catch (RuntimeException e) {      throw new IllegalArgumentException(e);    } catch (Exception e) {      throw new EJBExceptionWrapper(e);    }  }  /**   * Creates an instance of the named query   */  public Query createNamedQuery(String name)  {    String sql = _persistenceUnit.getNamedQuery(name);    if (sql != null)      return createQuery(sql);    NamedNativeQueryConfig nativeQuery      = _persistenceUnit.getNamedNativeQuery(name);    sql = nativeQuery.getQuery();    String resultSetMapping = nativeQuery.getResultSetMapping();    if (! ((resultSetMapping == null) || "".equals(resultSetMapping)))      return createNativeQuery(sql, resultSetMapping);

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?