com.caucho.amber.manager.AmberConnection Maven / Gradle / Ivy
/*
* Copyright (c) 1998-2018 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 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.logging.Level;
import java.util.logging.Logger;
import javax.persistence.EntityExistsException;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.EntityNotFoundException;
import javax.persistence.EntityTransaction;
import javax.persistence.FlushModeType;
import javax.persistence.LockModeType;
import javax.persistence.PersistenceException;
import javax.persistence.Query;
import javax.persistence.RollbackException;
import javax.persistence.TransactionRequiredException;
import javax.persistence.TypedQuery;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.metamodel.Metamodel;
import javax.sql.DataSource;
import javax.transaction.Status;
import javax.transaction.Synchronization;
import javax.transaction.Transaction;
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.AmberCompletion;
import com.caucho.amber.entity.AmberEntityHome;
import com.caucho.amber.entity.CacheableEntityItem;
import com.caucho.amber.entity.Entity;
import com.caucho.amber.entity.EntityFactory;
import com.caucho.amber.entity.EntityItem;
import com.caucho.amber.entity.EntityKey;
import com.caucho.amber.entity.EntityState;
import com.caucho.amber.entity.RowInsertCompletion;
import com.caucho.amber.entity.RowInvalidateCompletion;
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.jdbc.JdbcMetaData;
import com.caucho.util.L10N;
import com.caucho.util.LruCache;
/**
* The entity manager from a entity manager proxy.
*/
public class AmberConnection
implements Synchronization, EntityManager
{
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 _completionList
= new ArrayList();
private ArrayList _queries
= new ArrayList();
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 _preparedStatementMap
= new LruCache(32);
private ArrayList _statements = new ArrayList();
private EntityKey _entityKey = new EntityKey();
private QueryCacheKey _queryKey = new QueryCacheKey();
private ArrayList _mergingEntities = new ArrayList();
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 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 find(Class 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 getReference(Class 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);
Class resultClass = nativeQuery.getResultClass();
AmberEntityHome entityHome
= _persistenceUnit.getEntityHome(resultClass.getName());
EntityType entityType = entityHome.getEntityType();
try {
return createNativeQuery(sql, entityType.getInstanceClass());
} catch (Exception e) {
throw new IllegalArgumentException(e);
}
}
/**
* Creates an instance of the named query
*/
public Query createNativeQuery(String sql)
{
sql = sql.trim();
char ch = sql.charAt(0);
if (ch == 'S' || ch == 's')
throw new UnsupportedOperationException(L.l("createNativeQuery(String sql) is not supported for select statements. Please use createNativeQuery(String sql, String map) or createNativeQuery(String sql, Class cl) to map the result to scalar values or bean classes."));
return createInternalNativeQuery(sql);
}
/**
* Creates an instance of the named query
*/
public Query createNativeQuery(String sql, String map)
{
// jpa/0y1-
SqlResultSetMappingConfig resultSet;
resultSet = _persistenceUnit.getSqlResultSetMapping(map);
if (resultSet == null)
throw new IllegalArgumentException(L.l("createNativeQuery() cannot create a native query for a result set named '{0}'", map));
return createInternalNativeQuery(sql, resultSet);
}
/**
* Creates an instance of the native query
*/
public Query createNativeQuery(String sql, Class type)
{
SqlResultSetMappingConfig resultSet
= new SqlResultSetMappingConfig();
EntityResultConfig entityResult
= new EntityResultConfig();
entityResult.setEntityClass(type.getName());
resultSet.addEntityResult(entityResult);
return createInternalNativeQuery(sql, resultSet);
}
/**
* Refresh the state of the instance from the database.
*/
public void refresh(Object entity)
{
try {
if (entity == null)
return;
if (! (entity instanceof Entity))
throw new IllegalArgumentException(L.l("refresh() operation can only be applied to an entity instance. This object is of class '{0}'", entity.getClass().getName()));
checkTransactionRequired("refresh");
Entity instance = (Entity) entity;
String className = instance.getClass().getName();
Object pk = instance.__caucho_getPrimaryKey();
Entity oldEntity = getEntity(instance.getClass(), pk);
if (oldEntity != null) {
EntityState state = instance.__caucho_getEntityState();
if (state.ordinal() <= EntityState.TRANSIENT.ordinal()
|| EntityState.P_DELETING.ordinal() <= state.ordinal()) {
throw new IllegalArgumentException(L.l("refresh() operation can only be applied to a managed entity instance. The entity state is '{0}' for object of class '{0}' with PK '{1}'", className, pk, state == EntityState.TRANSIENT ? "TRANSIENT" : "DELETING or DELETED"));
}
}
else
throw new IllegalArgumentException(L.l("refresh() operation can only be applied to a managed entity instance. There was no managed instance of class '{0}' with PK '{1}'", className, pk));
// Reset and refresh state.
instance.__caucho_expire();
instance.__caucho_makePersistent(this, (EntityType) null);
instance.__caucho_retrieve_eager(this);
} catch (SQLException e) {
throw new AmberRuntimeException(e);
}
}
/**
* Returns the flush mode.
*/
public FlushModeType getFlushMode()
{
return FlushModeType.AUTO;
}
/**
* Sets the extended type.
*/
public void setExtended(boolean isExtended)
{
_isExtended = isExtended;
}
/**
* Returns the flush mode.
*/
public void setFlushMode(FlushModeType mode)
{
throw new UnsupportedOperationException();
}
/**
* Locks the object.
*/
public void lock(Object entity, LockModeType lockMode)
{
throw new UnsupportedOperationException();
}
/**
* Returns the transaction.
*/
public EntityTransaction getTransaction()
{
if (_isXA)
throw new IllegalStateException(L.l("Cannot call EntityManager.getTransaction() inside a distributed transaction."));
if (_trans == null)
_trans = new EntityTransactionImpl();
return _trans;
}
/**
* Returns true if open.
*/
public boolean isOpen()
{
return _persistenceUnit != null;
}
/**
* Registers with the local transaction.
*/
void register()
{
if (! _isRegistered) {
/*
if (! _isAppManaged)
UserTransactionProxy.getInstance().enlistCloseResource(this);
UserTransactionProxy.getInstance().enlistBeginResource(this);
*/
}
_isRegistered = true;
}
/**
* Joins the transaction.
*/
public void joinTransaction()
{
// XXX: jpa/0s46, jpa/0s47
_isInTransaction = true;
}
/**
* Gets the delegate.
*/
public Object getDelegate()
{
throw new UnsupportedOperationException();
}
/**
* Closes the context.
*/
public void close()
{
if (_persistenceUnit == null) {
// jpa/0s45
throw new IllegalStateException("Entity manager is already closed.");
}
try {
if (_isThreadConnection)
_persistenceUnit.removeThreadConnection();
_isRegistered = false;
cleanup();
} catch (Exception e) {
log.log(Level.FINER, e.toString(), e);
} finally {
_persistenceUnit = null;
}
}
/**
* Returns the amber manager.
*/
public AmberPersistenceUnit getAmberManager()
{
return _persistenceUnit;
}
/**
* Registers a collection.
*/
public void register(AmberCollection query)
{
_queries.add(query);
}
/**
* Adds a completion
*/
public void addCompletion(AmberCompletion completion)
{
if (! _completionList.contains(completion))
_completionList.add(completion);
}
/**
* Returns true if a transaction is active or
* this persistence context is extended.
*/
public boolean isActiveTransaction()
{
return _isInTransaction || _isExtended;
}
/**
* Returns true if a transaction is active.
*/
public boolean isInTransaction()
{
return _isInTransaction;
}
/**
* Returns the cache chunk size.
*/
public int getCacheChunkSize()
{
return 32;
}
public Object load(Class cl,
Object key,
boolean isEager)
throws AmberException
{
if (_persistenceUnit == null)
throw new IllegalStateException(L.l("AmberConnection is closed"));
if (log.isLoggable(Level.FINER))
log.finer(L.l("{0}[1] amber loading entity class", cl.getSimpleName(), key));
Entity entity = null;
if (key == null)
return null;
// ejb/0d01, jpa/0gh0, jpa/0g0k, jpa/0j5f
// if (shouldRetrieveFromCache())
entity = getEntity(cl, key);
if (entity != null) {
// jpa/0s2d: if it contains such entity and we have
// PersistenceContextType.TRANSACTION, the entity is
// managed and we can just return it (otherwise it would
// be detached and not be found in _entities).
// XXX: for PersistenceContextType.EXTENDED???
return entity;
}
_entityKey.init(cl, key);
EntityItem cacheItem = loadCacheItem(cl, key, null);
if (cacheItem == null)
return null;
/*
boolean isLoad = true;
// jpa/0h13 as a negative test.
if (isActiveTransaction())
isLoad = isEager;
*/
// jpa/0o03
boolean isLoad = isEager;
try {
entity = cacheItem.createEntity(this, key);
if (entity == null)
return null;
// The entity is added for eager loading
addInternalEntity(entity);
boolean isXA = isActiveTransaction();
// jpa/0l48: inheritance loading optimization.
// jpa/0h20: no transaction, copy from the existing cache item.
// jpa/0l42: loading optimization.
if (isLoad) {
entity.__caucho_retrieve_eager(this);
}
else if (isXA) {
// jpa/0v33: within a transaction, cannot copy from cache.
entity.__caucho_retrieve_self(this);
}
} catch (SQLException e) {
if (_persistenceUnit.isJPA()) {
log.log(Level.FINER, e.toString(), e);
return null;
}
throw new AmberObjectNotFoundException(L.l("{0}[{1}] is an unknown amber object",
cl.getName(), key),
e);
} catch (AmberObjectNotFoundException e) {
// 0g0q: if the entity is not found, removes it from context.
if (entity != null)
removeEntity(entity);
if (_persistenceUnit.isJPA())
return null;
throw e;
}
Entity txEntity = getTransactionEntity(entity.getClass(),
entity.__caucho_getPrimaryKey());
// XXX: jpa/0v33
if (txEntity != null)
setTransactionalState(txEntity);
return entity;
}
public EntityItem loadCacheItem(Class cl, Object key,
AmberEntityHome entityHome)
throws AmberException
{
_entityKey.init(cl, key);
EntityItem cacheItem = _persistenceUnit.getEntity(_entityKey);
if (cacheItem != null)
return cacheItem;
if (entityHome == null)
entityHome = _persistenceUnit.getEntityHome(cl.getName());
if (entityHome == null) {
throw new IllegalArgumentException(L.l("'{0}' is an unknown class in persistence-unit '{1}'. find() operation can only be applied if the entity class is specified in the scope of a persistence unit.",
cl.getName(),
_persistenceUnit.getName()));
}
cacheItem = entityHome.findEntityItem(this, key);
if (cacheItem == null) {
if (_persistenceUnit.isJPA())
return null;
// ejb/0604
throw new AmberObjectNotFoundException("amber find: no matching object " + cl.getName() + "[" + key + "]");
}
if (cacheItem instanceof CacheableEntityItem)
cacheItem = _persistenceUnit.putEntity(cl, key, cacheItem);
return cacheItem;
}
/**
* Loads the object based on the class and primary key.
*/
public Object load(String entityName,
Object key)
throws AmberException
{
AmberEntityHome entityHome = _persistenceUnit.getEntityHome(entityName);
if (entityHome == null)
return null;
Entity entity = null;
// XXX: ejb/0d01
// jpa/0y14 if (shouldRetrieveFromCache())
entity = getEntity(entityHome.getJavaClass(), key);
if (entity != null)
return entity;
try {
entityHome.init();
} catch (ConfigException e) {
throw new AmberException(e);
}
entity = (Entity) find(entityHome.getEntityType().getInstanceClass(), key);
// addEntity(entity);
return entity;
}
/**
* Returns the entity for the connection.
*/
public Entity getEntity(EntityItem item)
{
Entity itemEntity = item.getEntity();
Class cl = itemEntity.getClass();
Object pk = itemEntity.__caucho_getPrimaryKey();
Entity entity = getEntity(cl, pk);
if (entity != null) {
if (entity.__caucho_getEntityState().isManaged())
return entity;
// else
// jpa/0g40: the copy object was created at some point in
// findEntityItem, but it is still not loaded.
}
else {
try {
entity = item.createEntity(this, pk);
} catch (SQLException e) {
throw new AmberRuntimeException(e);
}
/*
// Create a new entity for the given class and primary key.
try {
entity = (Entity) cl.newInstance();
} catch (Exception e) {
throw new AmberRuntimeException(e);
}
*/
// entity.__caucho_setEntityState(EntityState.P_NON_TRANSACTIONAL);
// entity.__caucho_setPrimaryKey(pk);
// jpa/1000: avoids extra allocations.
addInternalEntity(entity);
}
// jpa/0l43
//_persistenceUnit.copyFromCacheItem(this, entity, item);
// jpa/0l4a
entity.__caucho_retrieve_eager(this);
return entity;
}
/**
* Returns the entity for the connection.
*/
public Entity getEntityLazy(EntityItem item)
{
Entity itemEntity = item.getEntity();
Class cl = itemEntity.getClass();
Object pk = itemEntity.__caucho_getPrimaryKey();
Entity entity = getEntity(cl, pk);
if (entity != null) {
if (entity.__caucho_getEntityState().isManaged())
return entity;
// else
// jpa/0g40: the copy object was created at some point in
// findEntityItem, but it is still not loaded.
}
else {
try {
entity = item.createEntity(this, pk);
} catch (SQLException e) {
throw new AmberRuntimeException(e);
}
/*
// Create a new entity for the given class and primary key.
try {
entity = (Entity) cl.newInstance();
} catch (Exception e) {
throw new AmberRuntimeException(e);
}
*/
// entity.__caucho_setEntityState(EntityState.P_NON_TRANSACTIONAL);
// entity.__caucho_setPrimaryKey(pk);
// jpa/1000: avoids extra allocations.
addInternalEntity(entity);
}
return entity;
}
/**
* Loads the object based on itself.
*/
public Object makePersistent(Object obj)
throws SQLException
{
Entity entity = (Entity) obj;
// check to see if exists
if (entity == null)
throw new NullPointerException();
Class cl = entity.getClass();
// Entity oldEntity = getEntity(cl, entity.__caucho_getPrimaryKey());
AmberEntityHome entityHome;
entityHome = _persistenceUnit.getEntityHome(entity.getClass().getName());
if (entityHome == null)
throw new AmberException(L.l("{0}: entity has no matching home",
entity.getClass().getName()));
entityHome.makePersistent(entity, this, false);
return entity;
}
/**
* Loads the object with the given class.
*/
public Entity loadLazy(Class cl, String name, Object key)
{
return loadLazy(cl.getName(), name, key);
}
/**
* Loads the object with the given class.
*/
public Entity loadLazy(String className, String name, Object key)
{
if (key == null)
return null;
try {
AmberEntityHome home = _persistenceUnit.getEntityHome(name);
if (home == null)
throw new RuntimeException(L.l("no matching home for {0}", className));
home.init();
Object obj = load(home.getEntityType().getInstanceClass(), key, false);
Entity entity = (Entity) obj;
return entity;
} catch (SQLException e) {
log.log(Level.WARNING, e.toString(), e);
return null;
} catch (ConfigException e) {
throw new AmberRuntimeException(e);
}
}
/**
* Loads the object with the given class.
*/
public EntityItem findEntityItem(String name, Object key)
{
try {
AmberEntityHome home = _persistenceUnit.getEntityHome(name);
if (home == null)
throw new RuntimeException(L.l("no matching home for {0}", name));
home.init();
return loadCacheItem(home.getJavaClass(), key, home);
} catch (RuntimeException e) {
throw e;
} catch (Exception e) {
throw new AmberRuntimeException(e);
}
}
/**
* Loads the object with the given class.
*/
public EntityItem setEntityItem(String name, Object key, EntityItem item)
{
try {
AmberEntityHome home = _persistenceUnit.getEntityHome(name);
if (home == null)
throw new RuntimeException(L.l("no matching home for {0}", name));
home.init();
return home.setEntityItem(key, item);
} catch (RuntimeException e) {
throw e;
} catch (Exception e) {
throw new AmberRuntimeException(e);
}
}
/**
* Loads the object with the given class.
*
* @param name the class name.
* @param key the key.
*/
public Entity loadFromHome(String name,
Object key)
{
try {
AmberEntityHome home = _persistenceUnit.getEntityHome(name);
if (home == null)
throw new RuntimeException(L.l("no matching home for {0}", name));
home.init();
// jpa/0ge4, jpa/0o04, jpa/0o0b, jpa/0o0c: bidirectional optimization.
return (Entity) load(home.getEntityType().getInstanceClass(),
key, true);
} catch (AmberObjectNotFoundException e) {
if (_persistenceUnit.isJPA()) {
if (log.isLoggable(Level.FINER))
log.log(Level.FINER, e.toString(), e);
// jpa/0h29
return null;
}
throw e;
} catch (RuntimeException e) {
throw e;
} catch (Exception e) {
throw new AmberRuntimeException(e);
}
}
/**
* Loads the object with the given class.
*/
public Object loadProxy(String name,
Object key)
{
if (key == null)
return null;
AmberEntityHome home = _persistenceUnit.getEntityHome(name);
if (home == null)
throw new RuntimeException(L.l("no matching home for {0}", name));
return loadProxy(home.getEntityType(), key);
}
/**
* Loads the object with the given class.
*/
public Object loadProxy(EntityType type,
Object key)
{
if (key == null)
return null;
Entity entity = getEntity(type.getInstanceClass(), key);
if (entity != null) {
// jpa/0m30
return entity;
}
try {
AmberEntityHome home = type.getHome();
EntityItem item = home.findEntityItem(this, key);
if (item == null)
return null;
EntityFactory factory = home.getEntityFactory();
Object newEntity = factory.getEntity(this, item);
if (_persistenceUnit.isJPA()) {
// jpa/0h29: eager loading.
Entity instance = (Entity) newEntity;
setTransactionalState(instance);
}
return newEntity;
} catch (SQLException e) {
log.log(Level.WARNING, e.toString(), e);
return null;
}
}
/**
* Loads the CMP 2.1 object for the given entityItem
*/
public Object loadProxy(EntityItem entityItem)
{
Entity itemEntity = entityItem.getEntity();
/*
Class cl = itemEntity.getClass();
Object pk = itemEntity.__caucho_getPrimaryKey();
Entity entity = getEntity(cl.getName(), pk);
if (entity != null) {
// jpa/0m30
return entity;
}
*/
AmberEntityHome home = entityItem.getEntityHome();
EntityFactory factory = home.getEntityFactory();
Object newEntity = factory.getEntity(this, entityItem);
return newEntity;
}
/**
* Loads the object based on the class and primary key.
*/
public Object load(Class cl, long intKey)
throws AmberException
{
AmberEntityHome entityHome = _persistenceUnit.getEntityHome(cl.getName());
if (entityHome == null)
return null;
Object key = entityHome.toObjectKey(intKey);
return load(cl, key, true);
}
/**
* Loads the object based on the class and primary key.
*/
public Object loadLazy(Class cl, long intKey)
throws AmberException
{
AmberEntityHome entityHome = _persistenceUnit.getEntityHome(cl.getName());
if (entityHome == null)
return null;
Object key = entityHome.toObjectKey(intKey);
return loadLazy(cl, cl.getName(), key);
}
/**
* Matches the entity.
*/
public Entity getEntity(Class cl, Object key)
{
Entity []entities = _entities;
for (int i = _entitiesTop - 1; i >= 0; i--) {
Entity entity = entities[i];
if (entity.__caucho_match(cl, key)) {
return entity;
}
}
return null;
}
public Entity getEntity(int index)
{
return _entities[index];
}
/**
* Returns the context entity that corresponds to the
* entity passed in. The entity passed in is normally a
* cache entity but might be the context entity itself
* when we want to make sure the reference is to an
* entity in the persistence context.
*/
public Entity getEntity(Entity entity)
{
if (entity == null)
return null;
return getEntity(entity.getClass(),
entity.__caucho_getPrimaryKey());
}
public Entity getSubEntity(Class cl, Object key)
{
Entity []entities = _entities;
// jpa/0l43
for (int i = _entitiesTop - 1; i >= 0; i--) {
Entity entity = entities[i];
if (entity.__caucho_getPrimaryKey().equals(key)) {
if (cl.isAssignableFrom(entity.getClass()))
return entity;
}
}
return null;
}
/**
* Gets the cache item referenced by __caucho_item
* from an entity of class/subclass cl.
*/
public EntityItem getSubEntityCacheItem(Class cl, Object key)
{
Entity []entities = _entities;
// jpa/0l4a
for (int i = _entitiesTop - 1; i >= 0; i--) {
Entity entity = entities[i];
if (entity.__caucho_getPrimaryKey().equals(key)) {
if (cl.isAssignableFrom(entity.getClass()))
return entity.__caucho_getCacheItem();
}
}
return null;
}
public Entity getTransactionEntity(Class cl, Object key)
{
Entity []entities = _txEntities;
for (int i = _txEntitiesTop - 1; i >= 0; i--) {
Entity entity = entities[i];
if (entity.__caucho_match(cl, key)) {
return entity;
}
}
return null;
}
public Entity getTransactionEntity(int index)
{
return _txEntities[index];
}
/**
* Adds a new entity for the given class name and key.
* The new entity object is supposed to be used as a
* copy from cache. This avoids the cache entity to
* be added to the context.
*
* @return null - if the entity is already in the context.
* otherwise, it returns the new entity added to
* the context.
*/
public Entity addNewEntity(Class cl, Object key)
throws InstantiationException, IllegalAccessException
{
// jpa/0l43
Entity entity = getSubEntity(cl, key);
// If the entity is already in the context, it returns null.
if (entity != null)
return null;
if (_persistenceUnit.isJPA()) {
// XXX: needs to create based on the discriminator with inheritance.
// Create a new entity for the given class and primary key.
entity = (Entity) cl.newInstance();
// jpa/0s2d
entity.__caucho_setEntityState(EntityState.P_NON_TRANSACTIONAL);
}
else {
// HelperBean__Amber -> HelperBean
String className = cl.getSuperclass().getName();
AmberEntityHome entityHome = _persistenceUnit.getEntityHome(className);
if (entityHome == null) {
if (log.isLoggable(Level.FINER))
log.log(Level.FINER, L.l("Amber.addNewEntity: home not found for entity (class: '{0}' PK: '{1}')",
className, key));
return null;
}
EntityFactory factory = entityHome.getEntityFactory();
// TestBean__EJB
Object value = factory.getEntity(key);
Method cauchoGetBeanMethod = entityHome.getCauchoGetBeanMethod();
if (cauchoGetBeanMethod != null) {
try {
// Bean
entity = (Entity) cauchoGetBeanMethod.invoke(value, new Object[0]);
// entity.__caucho_makePersistent(aConn, item);
} catch (Exception e) {
log.log(Level.FINER, e.toString(), e);
}
}
if (entity == null) {
throw new IllegalStateException(L.l("AmberConnection.addNewEntity unable to instantiate new entity with cauchoGetBeanMethod"));
}
}
entity.__caucho_setPrimaryKey(key);
addInternalEntity(entity);
return entity;
}
/**
* Adds a new entity for the given class name and key.
*/
public Entity loadEntity(Class cl,
Object key,
boolean isEager)
{
if (key == null)
return null;
// jpa/0l43
Entity entity = getSubEntity(cl, key);
// If the entity is already in the context, return it
if (entity != null)
return entity;
if (_persistenceUnit.isJPA()) {
// XXX: needs to create based on the discriminator with inheritance.
// Create a new entity for the given class and primary key.
try {
entity = (Entity) load(cl, key, isEager);
} catch (AmberException e) {
throw new AmberRuntimeException(e);
}
}
else {
// HelperBean__Amber -> HelperBean
String className = cl.getSuperclass().getName();
AmberEntityHome entityHome = _persistenceUnit.getEntityHome(className);
if (entityHome == null) {
if (log.isLoggable(Level.FINER))
log.log(Level.FINER, L.l("Amber.addNewEntity: home not found for entity (class: '{0}' PK: '{1}')",
className, key));
return null;
}
EntityFactory factory = entityHome.getEntityFactory();
// TestBean__EJB
Object value = factory.getEntity(key);
Method cauchoGetBeanMethod = entityHome.getCauchoGetBeanMethod();
if (cauchoGetBeanMethod != null) {
try {
// Bean
entity = (Entity) cauchoGetBeanMethod.invoke(value, new Object[0]);
// entity.__caucho_makePersistent(aConn, item);
} catch (Exception e) {
log.log(Level.FINER, e.toString(), e);
}
}
if (entity == null) {
throw new IllegalStateException(L.l("AmberConnection.addNewEntity unable to instantiate new entity with cauchoGetBeanMethod"));
}
entity.__caucho_setPrimaryKey(key);
addInternalEntity(entity);
}
return entity;
}
/**
* Removes an entity.
*/
public boolean removeEntity(Entity entity)
{
removeEntityImpl(entity);
if (isActiveTransaction())
removeTxEntity(entity);
return true;
}
/**
* Loads the object based on itself.
*/
public boolean contains(Object obj)
{
if (obj == null)
return false;
if (! (obj instanceof Entity))
throw new IllegalArgumentException(L.l("contains() operation can only be applied to an entity instance."));
Entity entity = (Entity) obj;
// jpa/11a8
if (entity.__caucho_getConnection() != this) {
return false;
}
EntityState state = entity.__caucho_getEntityState();
if (isInTransaction() && ! state.isTransactional()) {
// jpa/11a6, jpa/1800
return false;
}
// jpa/0j5f
if (EntityState.P_DELETING.ordinal() <= state.ordinal()) {
return false;
}
return true;
}
/**
* Callback when the user transaction begins
*/
public void begin(Transaction xa)
{
try {
xa.registerSynchronization(this);
_isInTransaction = true;
_isXA = true;
} catch (Exception e) {
log.log(Level.WARNING, e.toString(), e);
}
}
/**
* Starts a transaction.
*/
public void beginTransaction()
throws SQLException
{
_isInTransaction = true;
if (_conn != null && _isAutoCommit) {
_isAutoCommit = false;
_conn.setAutoCommit(false);
}
// _xid = _factory.getXid();
}
/**
* Sets XA.
*/
public void setXA(boolean isXA)
{
_isXA = isXA;
_isInTransaction = isXA;
if (isXA && ! _isRegistered)
register();
}
/**
* Commits a transaction.
*/
public void commit()
throws SQLException
{
if (log.isLoggable(Level.FINER))
log.log(Level.FINER, "AmberConnection.commit");
try {
flushInternal();
_xid = 0;
if (_conn != null) {
_conn.commit();
}
}
catch (RuntimeException e) {
throw e;
}
catch (SQLException e) {
throw new IllegalStateException(e);
}
catch (Exception e) {
throw new EJBExceptionWrapper(e);
}
finally {
if (! _isXA)
_isInTransaction = false;
for (int i = 0; i < _txEntitiesTop; i++) {
Entity entity = _txEntities[i];
entity.__caucho_afterCommit();
}
if (log.isLoggable(Level.FINER))
log.log(Level.FINER, "cleaning up txEntities");
_txEntitiesTop = 0;
}
}
/**
* Callback before a utrans commit.
*/
public void beforeCompletion()
{
if (log.isLoggable(Level.FINER))
log.log(Level.FINER, this + " beforeCompletion");
try {
beforeCommit();
// XXX: need to figure out how to throw JPA exceptions at commit() time.
// } catch (SQLException e) {
// throw e;
} catch (RuntimeException e) {
// jpa/0ga5
throw e;
} catch (Exception e) {
log.log(Level.WARNING, e.toString(), e);
}
}
/**
* Callback after a utrans commit.
*/
public void afterCompletion(int status)
{
if (log.isLoggable(Level.FINER)) {
if (status == Status.STATUS_COMMITTED)
log.finer(this + " afterCompletion(commit)");
else
log.finer(this + " afterCompletion(rollback)");
}
afterCommit(status == Status.STATUS_COMMITTED);
_isXA = false;
_isInTransaction = false;
_isRegistered = false; // ejb/0d19
}
/**
* Called before the commit phase
*/
public void beforeCommit()
throws SQLException
{
if (log.isLoggable(Level.FINER))
log.finer(this + " beforeCommit");
try {
flushInternal();
} catch (SQLException e) {
throw e;
} catch (RuntimeException e) {
throw e;
} catch (Exception e) {
throw new RuntimeException(e);
}
/*
// jpa/0gh0
for (int i = _txEntities.size() - 1; i >= 0; i--) {
Entity entity = _txEntities.get(i);
// jpa/1500
if (entity.__caucho_getEntityState() == EntityState.P_DELETED) {
EntityType entityType = entity.__caucho_getEntityType();
Object key = entity.__caucho_getPrimaryKey();
EntityItem item = _persistenceUnit.getEntity(entityType, key);
if (item == null) {
// jpa/0ga8: entity has been removed and DELETE SQL was already flushed.
continue;
}
}
entity.__caucho_flush();
}
*/
}
/**
* Commits a transaction.
*/
public void afterCommit(boolean isCommit)
{
try {
if (log.isLoggable(Level.FINER))
log.log(Level.FINER, "AmberConnection.afterCommit: " + isCommit);
if (! _isXA)
_isInTransaction = false;
if (isCommit) {
if (_completionList.size() > 0) {
_persistenceUnit.complete(_completionList);
}
}
// jpa/0k20: clears the completion list in the
// finally block so callbacks do not add a completion
// which has been just removed.
//
// _completionList.clear();
for (int i = 0; i < _txEntitiesTop; i++) {
Entity entity = _txEntities[i];
try {
if (isCommit)
entity.__caucho_afterCommit();
else
entity.__caucho_afterRollback();
} catch (Exception e) {
log.log(Level.WARNING, e.toString(), e);
}
}
if (log.isLoggable(Level.FINER))
log.log(Level.FINER, "cleaning up txEntities");
_txEntitiesTop = 0;
// jpa/0s2k
Entity []entities = _entities;
for (int i = _entitiesTop - 1; i >= 0; i--) {
// XXX: needs to check EXTENDED type.
// jpa/0h07: persistence context TRANSACTION type.
entities[i].__caucho_detach();
}
// jpa/0h60
_entitiesTop = 0;
// if (! isCommit) {
// jpa/0j5c
/* XXX: jpa/0k11 - avoids double rollback()
Rollback is done from com.caucho.transaction.TransactionImpl
to the pool item com.caucho.jca.PoolItem
try {
if (_conn != null)
_conn.rollback();
} catch (SQLException e) {
throw new IllegalStateException(e);
}
*/
// }
} finally {
_completionList.clear();
}
}
public PersistenceException rollback(Exception e)
{
try {
rollback();
} catch (Exception e1) {
log.log(Level.FINE, e1.toString(), e1);
}
return new PersistenceException(e);
}
/**
* Rollbacks a transaction.
*/
public void rollback()
throws SQLException
{
if (log.isLoggable(Level.FINER))
log.log(Level.FINER, "AmberConnection.rollback");
try {
flushInternal();
_xid = 0;
if (_conn != null) {
_conn.rollback();
}
}
catch (RuntimeException e) {
throw e;
}
catch (SQLException e) {
throw new IllegalStateException(e);
}
catch (Exception e) {
throw new EJBExceptionWrapper(e);
}
finally {
if (! _isXA)
_isInTransaction = false;
_completionList.clear();
for (int i = 0; i < _txEntitiesTop; i++) {
Entity entity = _txEntities[i];
entity.__caucho_afterRollback();
}
_txEntitiesTop = 0;
}
}
/**
* Flushes managed entities.
*/
public void flush()
{
try {
checkTransactionRequired("flush");
flushInternal();
} catch (RuntimeException e) {
throw e;
} catch (SQLException e) {
throw new IllegalStateException(e);
} catch (Exception e) {
throw new EJBExceptionWrapper(e);
}
}
/**
* Flushes managed entities.
*/
public void flushNoChecks()
{
try {
flushInternal();
} catch (RuntimeException e) {
throw e;
} catch (SQLException e) {
throw new IllegalStateException(e);
} catch (Exception e) {
throw new EJBExceptionWrapper(e);
}
}
/**
* Expires the entities
*/
public void expire()
throws SQLException
{
Entity []entities = _entities;
for (int i = _entitiesTop - 1; i >= 0; i--) {
Entity entity = entities[i];
// jpa/0j5e
if (! entity.__caucho_getEntityState().isPersist())
entity.__caucho_expire();
}
}
/**
* Returns the connection.
*/
public Connection getConnection()
throws SQLException
{
DataSource readDataSource = _persistenceUnit.getReadDataSource();
if (! _isXA && ! _isInTransaction && readDataSource != null) {
if (_readConn == null) {
_readConn = readDataSource.getConnection();
}
else if (_readConn.isClosed()) {
closeConnectionImpl();
_readConn = _persistenceUnit.getDataSource().getConnection();
}
return _readConn;
}
if (_conn == null) {
_conn = _persistenceUnit.getDataSource().getConnection();
_isAutoCommit = true;
}
else if (_conn.isClosed()) {
closeConnectionImpl();
_conn = _persistenceUnit.getDataSource().getConnection();
_isAutoCommit = true;
}
if (_isXA) {
}
else if (_isInTransaction && _isAutoCommit) {
_isAutoCommit = false;
_conn.setAutoCommit(false);
}
else if (! _isInTransaction && ! _isAutoCommit) {
_isAutoCommit = true;
_conn.setAutoCommit(true);
}
return _conn;
}
/**
* Prepares a statement.
*/
public PreparedStatement prepareStatement(String sql)
throws SQLException
{
try {
PreparedStatement pstmt = _preparedStatementMap.get(sql);
if (pstmt == null) {
Connection conn = getConnection();
// XXX: avoids locking issues.
if (_statements.size() > 0) {
conn = _statements.get(0).getConnection();
}
// XXX: avoids locking issues.
// See com.caucho.sql.UserConnection
pstmt = conn.prepareStatement(sql,
ResultSet.TYPE_FORWARD_ONLY,
ResultSet.CONCUR_READ_ONLY);
_statements.add(pstmt);
_preparedStatementMap.put(sql, pstmt);
}
return pstmt;
} catch (SQLException e) {
closeConnectionImpl();
throw e;
}
}
/**
* Closes a statement.
*/
public void closeStatement(String sql)
throws SQLException
{
PreparedStatement pstmt = _preparedStatementMap.remove(sql);
if (pstmt != null) {
_statements.remove(pstmt);
pstmt.close();
}
}
public static void close(ResultSet rs)
{
try {
if (rs != null)
rs.close();
} catch (SQLException e) {
throw new AmberRuntimeException(e);
}
}
/**
* Prepares an insert statement.
*/
public PreparedStatement prepareInsertStatement(String sql,
boolean isGeneratedId)
throws SQLException
{
PreparedStatement pstmt = null;
try {
pstmt = _preparedStatementMap.get(sql);
if (pstmt != null)
return pstmt;
Connection conn = getConnection();
// XXX: avoids locking issues.
if (_statements.size() > 0) {
conn = _statements.get(0).getConnection();
}
if (isGeneratedId && _persistenceUnit.hasReturnGeneratedKeys())
pstmt = conn.prepareStatement(sql, Statement.RETURN_GENERATED_KEYS);
else {
// XXX: avoids locking issues.
// See com.caucho.sql.UserConnection
pstmt = conn.prepareStatement(sql);
}
_statements.add(pstmt);
_preparedStatementMap.put(sql, pstmt);
return pstmt;
} catch (SQLException e) {
closeStatement(sql);
throw e;
}
}
/**
* Updates the database with the values in object. If the object does
* not exist, throws an exception.
*
* @param obj the object to update
*/
public void update(Object obj)
{
}
/**
* Saves the object.
*
* @param obj the object to create
*/
public void create(Object obj)
throws SQLException
{
// ejb/0g22 exception handling
try {
createInternal(obj);
} catch (RuntimeException e) {
throw e;
} catch (Exception e) {
throw new EJBExceptionWrapper(e);
}
}
/**
* Saves the object.
*
* @param obj the object to create
*/
public void create(String homeName, Object obj)
throws SQLException
{
// ejb/0g22 exception handling
try {
createInternal(homeName, obj);
} catch (RuntimeException e) {
throw e;
} catch (Exception e) {
throw new EJBExceptionWrapper(e);
}
}
/**
* Saves the object.
*
* @param obj the object to create
*/
public void create(AmberEntityHome home, Object obj)
throws SQLException
{
// ejb/0g22 exception handling
try {
createInternal(home, obj);
} catch (RuntimeException e) {
throw e;
} catch (Exception e) {
throw new EJBExceptionWrapper(e);
}
}
/**
* Updates the object.
*/
public void update(Entity entity)
{
if (entity == null)
return;
// jpa/0g0i
if (entity.__caucho_getEntityType() == null)
return;
// XXX: also needs to check PersistenceContextType.TRANSACTION/EXTENDED.
// jpa/0k10
if (! isActiveTransaction())
return;
AmberTable table = entity.__caucho_getEntityType().getTable();
Object key = entity.__caucho_getPrimaryKey();
addCompletion(new RowInvalidateCompletion(table.getName(), key));
// jpa/0ga8, jpa/0s2d if (! _txEntities.contains(entity)) {
Entity oldEntity = getTransactionEntity(entity.getClass(), key);
if (oldEntity == null) {
addTxEntity(entity);
}
else {
// XXX:
/*
// jpa/0s2d
Entity oldEntity = _txEntities.get(index);
_txEntities.set(index, entity);
*/
}
}
/**
* Deletes the object.
*
* @param entity the object to delete
*/
public void delete(Entity entity)
throws SQLException
{
Entity oldEntity = getEntity(entity.getClass(),
entity.__caucho_getPrimaryKey());
if (oldEntity == null) {
throw new IllegalStateException(L.l("AmberEntity[{0}:{1}] cannot be deleted since it is not managed",
entity.getClass().getName(),
entity.__caucho_getPrimaryKey()));
/*
EntityType entityType = entity.__caucho_getEntityType();
if (entityType == null)
return;
// throw new AmberException(L.l("entity has no entityType"));
AmberEntityHome entityHome = entityType.getHome();
//entityHome = _persistenceUnit.getEntityHome(entity.getClass().getName());
if (entityHome == null)
throw new AmberException(L.l("entity has no matching home"));
// XXX: this makes no sense
entityHome.makePersistent(entity, this, true);
addEntity(entity);
*/
}
else {
// XXX: jpa/0k12
oldEntity.__caucho_setConnection(this);
entity = oldEntity;
}
entity.__caucho_delete();
}
/**
* Creates a query object from a query string.
*
* @param queryString a Hibernate query
*/
public AmberQuery prepareQuery(String queryString)
throws AmberException
{
return prepareQuery(queryString, false);
}
/**
* Creates a query object from a query string.
*
* @param queryString a Hibernate query
*/
public AmberQuery prepareLazyQuery(String queryString)
throws AmberException
{
return prepareQuery(queryString, true);
}
/**
* Creates a query object from a query string.
*
* @param queryString a Hibernate query
*/
public AmberQuery prepareUpdate(String queryString)
throws AmberException
{
return prepareQuery(queryString, true);
}
/**
* Creates a query object from a query string.
*
* @param queryString a Hibernate query
*/
private AmberQuery prepareQuery(String queryString, boolean isLazy)
throws AmberException
{
AbstractQuery queryProgram = parseQuery(queryString, isLazy);
UserQuery query = new UserQuery(queryProgram);
query.setSession(this);
return query;
}
/**
* Creates a query object from a query string.
*
* @param sql a Hibernate query
*/
public AbstractQuery parseQuery(String sql, boolean isLazy)
throws AmberException
{
try {
_persistenceUnit.initEntityHomes();
} catch (Exception e) {
throw AmberRuntimeException.create(e);
}
AbstractQuery query = _persistenceUnit.getQueryParseCache(sql);
if (query == null) {
QueryParser parser = new QueryParser(sql);
parser.setPersistenceUnit(_persistenceUnit);
parser.setLazyResult(isLazy);
query = parser.parse();
_persistenceUnit.putQueryParseCache(sql, query);
}
return query;
}
/**
* Select a list of objects with a Hibernate query.
*
* @param hsql the hibernate query
*
* @return the query results.
*/
public ResultSet query(String hsql)
throws SQLException
{
AmberQuery query = prepareQuery(hsql);
return query.executeQuery();
}
/**
* Returns the cache chunk.
*
* @param sql the SQL for the cache chunk
* @param args the filled parameters for the cache chunk
* @param startRow the starting row for the cache chunk
*/
public ResultSetCacheChunk getQueryCacheChunk(String sql,
Object []args,
int startRow)
{
_queryKey.init(sql, args, startRow);
return _persistenceUnit.getQueryChunk(_queryKey);
}
/**
* Returns the result set meta data from cache.
*/
public ResultSetMetaData getQueryMetaData()
{
return _persistenceUnit.getQueryMetaData(_queryKey);
}
/**
* Sets the cache chunk.
*
* @param sql the SQL for the cache chunk
* @param args the filled parameters for the cache chunk
* @param startRow the starting row for the cache chunk
* @param cacheChunk the new value of the cache chunk
*/
public void putQueryCacheChunk(String sql,
Object []args,
int startRow,
ResultSetCacheChunk cacheChunk,
ResultSetMetaData cacheMetaData)
{
QueryCacheKey key = new QueryCacheKey();
Object []newArgs = new Object[args.length];
System.arraycopy(args, 0, newArgs, 0, args.length);
key.init(sql, newArgs, startRow);
_persistenceUnit.putQueryChunk(key, cacheChunk);
_persistenceUnit.putQueryMetaData(key, cacheMetaData);
}
/**
* Updates the database with a query
*
* @param hsql the hibernate query
*
* @return the query results.
*/
public int update(String hsql)
throws SQLException
{
AmberQuery query = prepareUpdate(hsql);
return query.executeUpdate();
}
/**
* Select a list of objects with a Hibernate query.
*
* @param hsql the hibernate query
*
* @return the query results.
*/
public List find(String hsql)
throws SQLException
{
AmberQuery query = prepareQuery(hsql);
return query.list();
}
/**
* Cleans up the connection.
*/
public void cleanup()
{
if (log.isLoggable(Level.FINER))
log.log(Level.FINER, "AmberConnection.cleanup");
try {
// XXX: also needs to check PersistenceContextType.TRANSACTION/EXTENDED.
// jpa/0g04
if (isActiveTransaction()) {
flushInternal();
}
}
catch (RuntimeException e) {
throw e;
}
catch (SQLException e) {
throw new IllegalStateException(e);
}
catch (Exception e) {
throw new EJBExceptionWrapper(e);
}
finally {
_depth = 0;
for (int i = _entitiesTop - 1; i >= 0; i--) {
_entities[i].__caucho_detach();
}
_entitiesTop = 0;
_txEntitiesTop = 0;
_completionList.clear();
freeConnection();
}
}
/**
* Pushes the depth.
*/
public void pushDepth()
{
// these aren't necessary because the AmberConnection is added as
// a close callback to the UserTransaction
}
/**
* Pops the depth.
*/
public void popDepth()
{
}
/**
* Frees the connection.
*/
public void freeConnection()
{
closeConnectionImpl();
}
/**
* Frees the connection.
*/
private void closeConnectionImpl()
{
Connection conn = _conn;
_conn = null;
Connection readConn = _readConn;
_readConn = null;
boolean isAutoCommit = _isAutoCommit;
_isAutoCommit = true;
try {
if (conn != null && ! isAutoCommit)
conn.setAutoCommit(true);
} catch (SQLException e) {
}
for (Statement stmt : _statements) {
try {
stmt.close();
} catch (Exception e) {
log.log(Level.WARNING, e.toString(), e);
}
}
try {
_preparedStatementMap.clear();
_statements.clear();
if (conn != null)
conn.close();
if (readConn != null)
readConn.close();
} catch (Exception e) {
log.log(Level.WARNING, e.toString(), e);
}
}
@Override
public String toString()
{
if (_persistenceUnit != null)
return "AmberConnection[" + _persistenceUnit.getName() + "]";
else
return "AmberConnection[closed]";
}
/**
* Finalizer.
*/
@Override
public void finalize()
{
cleanup();
}
/**
* Returns true when cache items can be used.
*/
public boolean shouldRetrieveFromCache()
{
// ejb/0d01
return (! isActiveTransaction());
}
public void setTransactionalState(Entity entity)
{
if (isActiveTransaction()) {
// jpa/0ga8
entity.__caucho_setConnection(this);
// jpa/0j5f
EntityState state = entity.__caucho_getEntityState();
//if (state.ordinal() < EntityState.P_DELETING.ordinal())
if (state == EntityState.P_NON_TRANSACTIONAL)
entity.__caucho_setEntityState(EntityState.P_TRANSACTIONAL);
}
}
public boolean isCacheEntity(Entity entity)
{
return entity == getCacheEntity(entity, true);
}
public Entity getCacheEntity(Entity entity)
{
return getCacheEntity(entity, false);
}
public Entity getCacheEntity(Entity entity,
boolean isDebug)
{
// jpa/0h0a
if (entity == null)
return null;
// XXX: jpa/0h20, the cache entity is only available after commit.
Entity cacheEntity = entity.__caucho_getCacheEntity();
if (cacheEntity != null)
return cacheEntity;
return getCacheEntity(entity.getClass(),
entity.__caucho_getPrimaryKey(),
isDebug);
}
public Entity getCacheEntity(Class cl, Object pk)
{
return getCacheEntity(cl, pk, false);
}
// jpa/0h20
public Entity getCacheEntity(Class cl, Object pk, boolean isDebug)
{
if (pk == null)
return null;
String className = cl.getName();
AmberEntityHome entityHome = _persistenceUnit.getEntityHome(className);
if (entityHome == null) {
if (log.isLoggable(Level.FINER))
log.log(Level.FINER, L.l("Home not found for entity (class: '{0}' PK: '{1}')",
className, pk));
return null;
}
EntityType rootType = entityHome.getRootType();
EntityItem item = _persistenceUnit.getEntity(rootType, pk);
if (item == null)
return null;
// jpa/0o0b
if (isDebug)
return item.getEntity();
// XXX: jpa/0h31, expires the child cache entity.
if (isActiveTransaction()) {
Entity txEntity = getTransactionEntity(cl, pk);
if (txEntity != null)
txEntity.__caucho_getEntityState();
else // jpa/0o0b || ! state.isManaged()) {
item.getEntity().__caucho_expire();
return null;
}
return item.getEntity();
}
//
// private
//
// throws Exception (for jpa)
//
// ejb/0g22 (cmp) expects exception handling in
// the public methods. See public void create(Object) above.
/**
* Adds an entity to the context, assuming it has not been added yet.
* Also, if there is a transaction, adds the entity to the list of
* transactional entities.
*/
private void addInternalEntity(Entity entity)
{
if (log.isLoggable(Level.FINEST)) {
log.log(Level.FINEST, L.l("amber {0}[{1}] addInternalEntity",
entity.getClass().getName(),
entity.__caucho_getPrimaryKey()));
}
addEntity(entity);
// jpa/0g06
if (isActiveTransaction()) {
addTxEntity(entity);
// jpa/0s2d: merge()
setTransactionalState(entity);
}
}
/**
* Saves the object.
*
* @param obj the object to create
*/
private void createInternal(Object obj)
throws Exception
{
AmberEntityHome home = null;
Class cl = obj.getClass();
for (; home == null && cl != null; cl = cl.getSuperclass()) {
home = _persistenceUnit.getHome(cl);
}
if (home == null)
throw new AmberException(L.l("'{0}' is not a known entity class.",
obj.getClass().getName()));
createInternal(home, obj);
}
/**
* Saves the object.
*
* @param obj the object to create
*/
private void createInternal(String homeName, Object obj)
throws Exception
{
AmberEntityHome home = _persistenceUnit.getEntityHome(homeName);
if (home == null)
throw new AmberException(L.l("'{0}' is not a known entity class.",
obj.getClass().getName()));
createInternal(home, obj);
}
/**
* Saves the object.
*
* @param obj the object to create
*/
private void createInternal(AmberEntityHome home, Object obj)
throws Exception
{
// XXX: flushing things like delete might be useful?
// XXX: the issue is a flush can break FK constraints and
// fail prematurely (jpa/0h26).
// commented out: flushInternal();
if (contains(obj))
return;
Entity entity = (Entity) obj;
// jpa/0g0k: cannot call home.save because of jpa exception handling.
if (_persistenceUnit.isJPA()) {
// See persistInternal(): entity.__caucho_cascadePrePersist(this);
addEntity(entity);
// jpa/0ga2
entity.__caucho_lazy_create(this, home.getEntityType());
// See persistInternal(): entity.__caucho_cascadePostPersist(this);
}
else
home.save(this, entity);
// jpa/0h25
// XXX: not correct, since we need to keep the P_PERSIST state around
// and P_PERSIST is a transactional state
// setTransactionalState(entity);
// jpa/0g0i
AmberTable table = home.getEntityType().getTable();
addCompletion(new RowInsertCompletion(table.getName()));
}
private void checkTransactionRequired(String operation)
throws TransactionRequiredException, SQLException
{
// XXX: also needs to check PersistenceContextType.TRANSACTION/EXTENDED.
if (! (_isXA || isActiveTransaction()))
throw new TransactionRequiredException(L.l("{0}() operation can only be executed in the scope of a transaction or with an extended persistence context.", operation));
}
private Entity checkEntityType(Object entity, String operation)
{
if (! (entity instanceof Entity))
throw new IllegalArgumentException(L.l("{0}() operation can only be applied to an entity instance. If the argument is an entity, the corresponding class must be specified in the scope of a persistence unit.", operation));
if (_persistenceUnit.isJPA()) {
String className = entity.getClass().getName();
EntityType entityType
= (EntityType) _persistenceUnit.getEntityType(className);
// jpa/0m08
if (entityType == null) {
throw new IllegalArgumentException(L.l("{0}() operation can only be applied to an entity instance. If the argument is an entity, the class '{1}' must be specified in the orm.xml or annotated with @Entity and must be in the scope of a persistence unit.", operation, className));
}
}
return (Entity) entity;
}
/**
* Detach after non-xa.
*/
public void detach()
{
if (_isXA || _isInTransaction)
throw new IllegalStateException(L.l("detach cannot be called within transaction"));
_completionList.clear();
_txEntitiesTop = 0;
// jpa/1700
for (int i = _entitiesTop - 1; i >= 0; i--) {
_entities[i].__caucho_detach();
}
// jpa/0o0d
_entitiesTop = 0;
}
/**
* Flush managed entities.
*/
private void flushInternal()
throws Exception
{
// Do not flush within merge() or while loading an entity.
if (! _isFlushAllowed)
return;
/* XXX: moved into __caucho_flush
for (int i = _txEntities.size() - 1; i >= 0; i--) {
Entity entity = _txEntities.get(i);
EntityState state = entity.__caucho_getEntityState();
// jpa/0i60
// jpa/0h27: for all entities Y referenced by a *managed*
// entity X, where the relationship has been annotated
// with cascade=PERSIST/ALL, the persist operation is
// applied to Y. It is a lazy cascade as the relationship
// is not always initialized at the time persist(X) was
// called but must be at flush time.
if (state == EntityState.P_PERSIST) {
entity.__caucho_cascadePrePersist(this);
entity.__caucho_cascadePostPersist(this);
}
}
*/
// We avoid breaking FK constraints:
//
// 1. Assume _txEntities has the following order: A <- B <- C
// XXX: Make sure priorities are handled based on owning sides
// even when there are cycles in a graph.
//
// 2. Persist is done in ascending order: A(0) <- B(1) <- C(2)
//
// 3. Delete is done in descending order: C(2) -> B(1) -> A(0)
// Persists in ascending order.
for (int i = 0; i < _txEntitiesTop; i++) {
Entity entity = _txEntities[i];
if (entity.__caucho_getEntityState().isPersist()) {
try {
entity.__caucho_flush();
} catch (SQLException e) {
throwPersistException(e, entity);
}
}
}
// jpa/0h25
// Deletes in descending order.
for (int i = _txEntitiesTop - 1; i >= 0; i--) {
Entity entity = _txEntities[i];
if (! entity.__caucho_getEntityState().isPersist()) {
entity.__caucho_flush();
}
}
if (! isInTransaction()) {
if (_completionList.size() > 0) {
_persistenceUnit.complete(_completionList);
}
_completionList.clear();
for (int i = 0; i < _txEntitiesTop; i++) {
Entity entity = _txEntities[i];
entity.__caucho_afterCommit();
}
_txEntitiesTop = 0;
}
}
private void throwPersistException(SQLException e, Entity entity)
throws SQLException
{
log.log(Level.FINER, e.toString(), e);
String sqlState = e.getSQLState();
JdbcMetaData metaData = _persistenceUnit.getMetaData();
if (metaData.isUniqueConstraintSQLState(sqlState)) {
// jpa/0ga5
throw new EntityExistsException(L.l("Trying to persist an entity '{0}[{1}]' that already exists. Entity state '{2}'", entity.getClass().getName(), entity.__caucho_getPrimaryKey(), entity.__caucho_getEntityState()));
}
else if (metaData.isForeignKeyViolationSQLState(sqlState)) {
// jpa/0o42
throw new IllegalStateException(L.l("Trying to persist an entity of class '{0}' with PK '{1}' would break a foreign key constraint. The entity state is '{2}'. Please make sure there are associated entities for all required relationships. If you are merging an entity make sure the association fields are annotated with cascade=MERGE or cascade=ALL.", entity.getClass().getName(), entity.__caucho_getPrimaryKey(), entity.__caucho_getEntityState()));
}
throw e;
}
/**
* Persists the entity.
*/
private Entity persistInternal(Entity entity)
throws Exception
{
EntityState state = entity.__caucho_getEntityState();
if (state == null)
state = EntityState.TRANSIENT;
switch (state) {
case TRANSIENT:
{
Entity contextEntity = getEntity(entity.getClass(),
entity.__caucho_getPrimaryKey());
// jpa/0ga3
if (contextEntity == null) {
}
else if (contextEntity.__caucho_getEntityState().isDeleting()) {
// jpa/0ga3
contextEntity.__caucho_flush();
}
else if (entity != contextEntity) {
return contextEntity;
/*
// jpa/0ga1: trying to persist a detached entity that already exists.
throw new EntityExistsException(L.l("Trying to persist a detached entity of class '{0}' with PK '{1}' that already exists. Entity state '{2}'", entity.getClass().getName(), entity.__caucho_getPrimaryKey(), state));
*/
}
// jpa/0h24
// Pre-persist child entities.
entity.__caucho_cascadePrePersist(this);
createInternal(entity);
}
break;
case P_DELETING:
case P_DELETED:
{
// jpa/0i60, jpa/1510, jpa/0h25
// jpa/0h26
entity.__caucho_cascadePrePersist(this);
// removed entity instance, reset state and persist.
entity.__caucho_makePersistent(null, (EntityType) null);
createInternal(entity);
}
break;
case P_PERSISTING:
case P_PERSISTED:
{
// jpa/0h26
// Pre-persist child entities.
entity.__caucho_cascadePrePersist(this);
}
break;
default:
if (entity.__caucho_getConnection() == this)
return entity;
else {
// jpa/0ga5 (tck):
// See entitytest.persist.basic.persistBasicTest4 vs.
// callback.inheritance.preUpdateTest
throw new EntityExistsException(L.l("Trying to persist an entity that is detached or already exists. Entity state '{0}'", state));
}
}
// jpa/0j5e
updateFlushPriority(entity);
// jpa/0h27, jpa/0i5c, jpa/0j5g
// Post-persist child entities.
entity.__caucho_cascadePostPersist(this);
return entity;
}
/**
* Updates flush priorities.
*/
private void updateFlushPriority(Entity updateEntity)
{
if (! isActiveTransaction())
return;
removeTxEntity(updateEntity);
int updatePriority
= updateEntity.__caucho_getEntityType().getFlushPriority();
for (int i = _txEntitiesTop - 1; i >= 0; i--) {
Entity entity = _txEntities[i];
int currentPriority = entity.__caucho_getEntityType().getFlushPriority();
if (currentPriority < updatePriority) {
addTxEntity(i + 1, updateEntity);
return;
}
}
addTxEntity(0, updateEntity);
}
/**
* Recursively merges the state of the entity into the current context.
*/
public T recursiveMerge(T entityT)
{
// jpa/0ga3, jpa/0h08, jpa/0i5g, jpa/0s2k
try {
if (entityT == null)
return null;
Entity entity = checkEntityType(entityT, "merge");
if (log.isLoggable(Level.FINER)) {
String className = entity.getClass().getName();
Object pk = entity.__caucho_getPrimaryKey();
EntityState state = entity.__caucho_getEntityState();
log.finer(L.l("recursiveMerge({0}[{1}] state: '{2}'",
className, pk, state));
}
if (containsMergingEntity(entity))
return (T) entity;
else
return (T) mergeDetachedEntity(entity);
} catch (RuntimeException e) {
throw e;
} catch (Exception e) {
throw new EJBExceptionWrapper(e);
}
}
public Entity mergeDetachedEntity(Entity newEntity)
{
try {
if (newEntity == null)
return newEntity;
Class entityClass = newEntity.getClass();
String className = newEntity.getClass().getName();
EntityState state = newEntity.__caucho_getEntityState();
Object pk = newEntity.__caucho_getPrimaryKey();
if (log.isLoggable(Level.FINER))
log.finer(L.l("{0}[{1}] amber merge state='{2}'",
entityClass.getSimpleName(), pk, state));
if (state.isDeleting()) {
// removed entity instance
throw new IllegalArgumentException(L.l("{0}: merge operation cannot be applied to a removed entity instance",
entityClass));
}
// XXX: jpa/0o42 try {
Entity existingEntity = null;
try {
existingEntity = (Entity) load(entityClass, pk, true);
} catch (AmberObjectNotFoundException e) {
if (log.isLoggable(Level.FINER))
log.log(Level.FINER, e.toString(), e);
// JPA: should not throw at all, returns null only.
}
if (existingEntity != null) {
if (containsMergingEntity(existingEntity))
return existingEntity;
_mergingEntities.add(existingEntity);
existingEntity.__caucho_mergeFrom(this, newEntity);
return existingEntity;
}
// XXX: the original entity should remain detached jpa/0s2k
// setTransactionalState(entity);
// new entity instance
persist(newEntity);
return newEntity;
} catch (RuntimeException e) {
throw e;
} catch (Exception e) {
throw new EJBExceptionWrapper(e);
}
}
/**
* Creates an instance of the named query
*/
private Query createInternalNativeQuery(String sql)
{
try {
QueryImpl query = new QueryImpl(this);
query.setNativeSql(sql);
return query;
} catch (RuntimeException e) {
throw new IllegalArgumentException(e);
} catch (Exception e) {
throw new EJBExceptionWrapper(e);
}
}
/**
* Creates an instance of the native query.
*/
private Query createInternalNativeQuery(String sql,
SqlResultSetMappingConfig map)
{
Query query = createInternalNativeQuery(sql);
QueryImpl queryImpl = (QueryImpl) query;
queryImpl.setSqlResultSetMapping(map);
return query;
}
private boolean containsMergingEntity(Entity entity)
{
if (_mergingEntities.contains(entity))
return true;
// jpa/0o42
int index = getEntityMatch(_mergingEntities,
entity.getClass(),
entity.__caucho_getPrimaryKey());
return (index >= 0);
}
public void addEntity(Entity entity)
{
Entity []entities = _entities;
if (_entitiesTop == entities.length) {
entities = new Entity[_entities.length + 32];
System.arraycopy(_entities, 0, entities, 0, _entities.length);
_entities = entities;
}
entities[_entitiesTop++] = entity;
}
private void removeEntityImpl(Entity entity)
{
Entity []entities = _entities;
for (int i = _entitiesTop - 1; i >= 0; i--) {
if (entities[i] == entity) {
System.arraycopy(entities, i + 1, entities, i,
_entitiesTop - i - 1);
_entitiesTop -= 1;
return;
}
}
}
private void addTxEntity(Entity entity)
{
Entity []entities = _txEntities;
if (_txEntitiesTop == entities.length) {
entities = new Entity[entities.length + 32];
System.arraycopy(_txEntities, 0, entities, 0, _txEntities.length);
_txEntities = entities;
}
entities[_txEntitiesTop++] = entity;
}
private void removeTxEntity(Entity entity)
{
Entity []entities = _txEntities;
for (int i = _txEntitiesTop - 1; i >= 0; i--) {
if (entities[i] == entity) {
System.arraycopy(entities, i + 1, entities, i,
_txEntitiesTop - i - 1);
_txEntitiesTop -= 1;
return;
}
}
}
private void addTxEntity(int index, Entity entity)
{
Entity []entities = _txEntities;
if (_txEntitiesTop == entities.length) {
entities = new Entity[_txEntities.length + 32];
System.arraycopy(_txEntities, 0, entities, 0, _txEntities.length);
_txEntities = entities;
}
if (index < _txEntitiesTop)
System.arraycopy(entities, index, entities, index + 1,
_txEntitiesTop - index);
entities[index] = entity;
_txEntitiesTop += 1;
}
private static int getEntityMatch(ArrayList list,
Class cl,
Object key)
{
// See also: getEntity() and getTransactionEntity().
// jpa/0o42
for (int i = list.size() - 1; i >= 0; i--) {
Entity entity = list.get(i);
if (entity.__caucho_match(cl, key)) {
return i;
}
}
return -1;
}
private class EntityTransactionImpl implements EntityTransaction {
private boolean _rollbackOnly;
/**
* Starts a resource transaction.
*/
public void begin()
{
// jpa/1522
if (isActiveTransaction())
throw new IllegalStateException("begin() cannot be called when the entity transaction is already active.");
_rollbackOnly = false;
try {
AmberConnection.this.beginTransaction();
} catch (SQLException e) {
throw new PersistenceException(e);
}
}
/**
* Commits a resource transaction.
*/
public void commit()
{
// jpa/1523
if (! isActiveTransaction())
throw new IllegalStateException("commit() cannot be called when the entity transaction is not active.");
// jpa/1525
if (getRollbackOnly())
throw new RollbackException("commit() cannot be called when the entity transaction is marked for rollback only.");
try {
// jpa/11a7
AmberConnection.this.beforeCommit();
_isInTransaction = false;
// jpa/11a7 AmberConnection.this.commit();
if (AmberConnection.this._conn != null) {
AmberConnection.this._conn.commit();
}
// XXX: missing finally issues if _conn.commit fails
// jpa/11a7
AmberConnection.this.afterCommit(true);
if (AmberConnection.this._conn != null) {
closeConnectionImpl();
}
} catch (SQLException e) {
throw new PersistenceException(e);
}
}
/**
* Rolls the current transaction back.
*/
public void rollback()
{
// jpa/1524
if (! isActiveTransaction())
throw new IllegalStateException("rollback() cannot be called when the entity transaction is not active.");
setRollbackOnly();
PersistenceException exn = null;
try {
AmberConnection.this.rollback();
} catch (Exception e) {
exn = new PersistenceException(e);
} finally {
try {
// jpa/1501
AmberConnection.this.afterCommit(false);
} catch (PersistenceException e) {
exn = e;
} catch (Exception e) {
exn = new PersistenceException(e);
} finally {
// jpa/1525
if (AmberConnection.this._conn != null) {
closeConnectionImpl();
}
}
}
if (exn != null)
throw exn;
}
/**
* Marks the current transaction for rollback only.
*/
public void setRollbackOnly()
{
// jpa/1521
if (! isActiveTransaction())
throw new IllegalStateException("setRollbackOnly() cannot be called when the entity transaction is not active.");
_rollbackOnly = true;
}
/**
* Returns true if the transaction is for rollback only.
*/
public boolean getRollbackOnly()
{
// jpa/1520
if (! isActiveTransaction())
throw new IllegalStateException("getRollbackOnly() cannot be called when the entity transaction is not active.");
return _rollbackOnly;
}
/**
* Test if a transaction is in progress.
*/
public boolean isActive()
{
return _isInTransaction;
}
}
/* (non-Javadoc)
* @see javax.persistence.EntityManager#createNamedQuery(java.lang.String, java.lang.Class)
*/
@Override
public TypedQuery createNamedQuery(String name, Class resultClass)
{
// TODO Auto-generated method stub
return null;
}
/* (non-Javadoc)
* @see javax.persistence.EntityManager#createQuery(javax.persistence.criteria.CriteriaQuery)
*/
@Override
public TypedQuery createQuery(CriteriaQuery criteriaQuery)
{
// TODO Auto-generated method stub
return null;
}
@Override
public TypedQuery createQuery(String qlString,
Class resultClass)
{
// TODO Auto-generated method stub
return null;
}
/* (non-Javadoc)
* @see javax.persistence.EntityManager#detach(java.lang.Object)
*/
@Override
public void detach(Object entity)
{
// TODO Auto-generated method stub
}
/* (non-Javadoc)
* @see javax.persistence.EntityManager#find(java.lang.Class, java.lang.Object, java.util.Map)
*/
@Override
public T find(Class entityCLass, Object primaryKey,
Map properties)
{
// TODO Auto-generated method stub
return null;
}
/* (non-Javadoc)
* @see javax.persistence.EntityManager#find(java.lang.Class, java.lang.Object, javax.persistence.LockModeType)
*/
@Override
public T find(Class entityCLass, Object primaryKey,
LockModeType lockMode)
{
// TODO Auto-generated method stub
return null;
}
/* (non-Javadoc)
* @see javax.persistence.EntityManager#find(java.lang.Class, java.lang.Object, javax.persistence.LockModeType, java.util.Map)
*/
@Override
public T find(Class entityCLass, Object primaryKey,
LockModeType lockMode, Map properties)
{
// TODO Auto-generated method stub
return null;
}
/* (non-Javadoc)
* @see javax.persistence.EntityManager#getCriteriaBuilder()
*/
@Override
public CriteriaBuilder getCriteriaBuilder()
{
// TODO Auto-generated method stub
return null;
}
/* (non-Javadoc)
* @see javax.persistence.EntityManager#getEntityManagerFactory()
*/
@Override
public EntityManagerFactory getEntityManagerFactory()
{
// TODO Auto-generated method stub
return null;
}
/* (non-Javadoc)
* @see javax.persistence.EntityManager#getLockMode(java.lang.Object)
*/
@Override
public LockModeType getLockMode(Object entity)
{
// TODO Auto-generated method stub
return null;
}
/* (non-Javadoc)
* @see javax.persistence.EntityManager#getMetamodel()
*/
@Override
public Metamodel getMetamodel()
{
// TODO Auto-generated method stub
return null;
}
/* (non-Javadoc)
* @see javax.persistence.EntityManager#getProperties()
*/
@Override
public Map getProperties()
{
// TODO Auto-generated method stub
return null;
}
/* (non-Javadoc)
* @see javax.persistence.EntityManager#lock(java.lang.Object, javax.persistence.LockModeType, java.util.Map)
*/
@Override
public void lock(Object entity, LockModeType lockMode,
Map properties)
{
// TODO Auto-generated method stub
}
/* (non-Javadoc)
* @see javax.persistence.EntityManager#refresh(java.lang.Object, java.util.Map)
*/
@Override
public void refresh(Object entity, Map properties)
{
// TODO Auto-generated method stub
}
/* (non-Javadoc)
* @see javax.persistence.EntityManager#refresh(java.lang.Object, javax.persistence.LockModeType)
*/
@Override
public void refresh(Object entity, LockModeType lockMode)
{
// TODO Auto-generated method stub
}
/* (non-Javadoc)
* @see javax.persistence.EntityManager#refresh(java.lang.Object, javax.persistence.LockModeType, java.util.Map)
*/
@Override
public void refresh(Object entity, LockModeType lockMode,
Map properties)
{
// TODO Auto-generated method stub
}
/* (non-Javadoc)
* @see javax.persistence.EntityManager#setProperty(java.lang.String, java.lang.Object)
*/
@Override
public void setProperty(String propertyName, Object value)
{
// TODO Auto-generated method stub
}
/* (non-Javadoc)
* @see javax.persistence.EntityManager#unwrap(java.lang.Class)
*/
@Override
public T unwrap(Class cls)
{
// TODO Auto-generated method stub
return null;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy