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 + -
显示快捷键?