org.hibernate.internal.StatelessSessionImpl Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of beangle-hibernate-core Show documentation
Show all versions of beangle-hibernate-core Show documentation
Hibernate Orm Core Shade,Support Scala Collection
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or .
*/
package org.hibernate.internal;
import java.io.Serializable;
import java.sql.Connection;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import javax.transaction.SystemException;
import org.hibernate.CacheMode;
import org.hibernate.Criteria;
import org.hibernate.EntityMode;
import org.hibernate.FlushMode;
import org.hibernate.HibernateException;
import org.hibernate.LockMode;
import org.hibernate.MappingException;
import org.hibernate.ScrollMode;
import org.hibernate.SessionException;
import org.hibernate.StatelessSession;
import org.hibernate.UnresolvableObjectException;
import org.hibernate.bytecode.spi.BytecodeEnhancementMetadata;
import org.hibernate.cache.spi.access.EntityDataAccess;
import org.hibernate.collection.spi.PersistentCollection;
import org.hibernate.engine.internal.StatefulPersistenceContext;
import org.hibernate.engine.internal.Versioning;
import org.hibernate.engine.query.spi.HQLQueryPlan;
import org.hibernate.engine.query.spi.NativeSQLQueryPlan;
import org.hibernate.engine.query.spi.sql.NativeSQLQuerySpecification;
import org.hibernate.engine.spi.EntityKey;
import org.hibernate.engine.spi.LoadQueryInfluencers;
import org.hibernate.engine.spi.PersistenceContext;
import org.hibernate.engine.spi.QueryParameters;
import org.hibernate.engine.transaction.internal.jta.JtaStatusHelper;
import org.hibernate.engine.transaction.jta.platform.spi.JtaPlatform;
import org.hibernate.id.IdentifierGeneratorHelper;
import org.hibernate.loader.criteria.CriteriaLoader;
import org.hibernate.loader.custom.CustomLoader;
import org.hibernate.loader.custom.CustomQuery;
import org.hibernate.persister.entity.EntityPersister;
import org.hibernate.persister.entity.OuterJoinLoadable;
import org.hibernate.pretty.MessageHelper;
import org.hibernate.proxy.HibernateProxy;
import org.hibernate.query.spi.ScrollableResultsImplementor;
import org.hibernate.tuple.entity.EntityMetamodel;
/**
* @author Gavin King
* @author Steve Ebersole
*/
public class StatelessSessionImpl extends AbstractSharedSessionContract implements StatelessSession {
private static final CoreMessageLogger LOG = CoreLogging.messageLogger( StatelessSessionImpl.class );
private static LoadQueryInfluencers NO_INFLUENCERS = new LoadQueryInfluencers( null ) {
@Override
public String getInternalFetchProfile() {
return null;
}
@Override
public void setInternalFetchProfile(String internalFetchProfile) {
}
};
private final PersistenceContext temporaryPersistenceContext = new StatefulPersistenceContext( this );
private final boolean connectionProvided;
private final boolean allowBytecodeProxy;
public StatelessSessionImpl(SessionFactoryImpl factory, SessionCreationOptions options) {
super( factory, options );
connectionProvided = options.getConnection() != null;
allowBytecodeProxy = getFactory().getSessionFactoryOptions().isEnhancementAsProxyEnabled();
}
@Override
public boolean shouldAutoJoinTransaction() {
return true;
}
// inserts ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@Override
public Serializable insert(Object entity) {
checkOpen();
return insert( null, entity );
}
@Override
public Serializable insert(String entityName, Object entity) {
checkOpen();
EntityPersister persister = getEntityPersister( entityName, entity );
Serializable id = persister.getIdentifierGenerator().generate( this, entity );
Object[] state = persister.getPropertyValues( entity );
if ( persister.isVersioned() ) {
boolean substitute = Versioning.seedVersion(
state,
persister.getVersionProperty(),
persister.getVersionType(),
this
);
if ( substitute ) {
persister.setPropertyValues( entity, state );
}
}
if ( id == IdentifierGeneratorHelper.POST_INSERT_INDICATOR ) {
id = persister.insert( state, entity, this );
}
else {
persister.insert( id, state, entity, this );
}
persister.setIdentifier( entity, id, this );
return id;
}
// deletes ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@Override
public void delete(Object entity) {
checkOpen();
delete( null, entity );
}
@Override
public void delete(String entityName, Object entity) {
checkOpen();
EntityPersister persister = getEntityPersister( entityName, entity );
Serializable id = persister.getIdentifier( entity, this );
Object version = persister.getVersion( entity );
persister.delete( id, version, entity, this );
}
// updates ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@Override
public void update(Object entity) {
checkOpen();
update( null, entity );
}
@Override
public void update(String entityName, Object entity) {
checkOpen();
EntityPersister persister = getEntityPersister( entityName, entity );
Serializable id = persister.getIdentifier( entity, this );
Object[] state = persister.getPropertyValues( entity );
Object oldVersion;
if ( persister.isVersioned() ) {
oldVersion = persister.getVersion( entity );
Object newVersion = Versioning.increment( oldVersion, persister.getVersionType(), this );
Versioning.setVersion( state, newVersion, persister );
persister.setPropertyValues( entity, state );
}
else {
oldVersion = null;
}
persister.update( id, state, null, false, null, oldVersion, entity, null, this );
}
// loading ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@Override
public Object get(Class entityClass, Serializable id) {
return get( entityClass.getName(), id );
}
@Override
public Object get(Class entityClass, Serializable id, LockMode lockMode) {
return get( entityClass.getName(), id, lockMode );
}
@Override
public Object get(String entityName, Serializable id) {
return get( entityName, id, LockMode.NONE );
}
@Override
public Object get(String entityName, Serializable id, LockMode lockMode) {
checkOpen();
Object result = getFactory().getMetamodel().entityPersister( entityName )
.load( id, null, getNullSafeLockMode( lockMode ), this );
if ( temporaryPersistenceContext.isLoadFinished() ) {
temporaryPersistenceContext.clear();
}
return result;
}
@Override
public void refresh(Object entity) {
refresh( bestGuessEntityName( entity ), entity, LockMode.NONE );
}
@Override
public void refresh(String entityName, Object entity) {
refresh( entityName, entity, LockMode.NONE );
}
@Override
public void refresh(Object entity, LockMode lockMode) {
refresh( bestGuessEntityName( entity ), entity, lockMode );
}
@Override
public void refresh(String entityName, Object entity, LockMode lockMode) {
final EntityPersister persister = this.getEntityPersister( entityName, entity );
final Serializable id = persister.getIdentifier( entity, this );
if ( LOG.isTraceEnabled() ) {
LOG.tracev( "Refreshing transient {0}", MessageHelper.infoString( persister, id, this.getFactory() ) );
}
// TODO : can this ever happen???
// EntityKey key = new EntityKey( id, persister, source.getEntityMode() );
// if ( source.getPersistenceContext().getEntry( key ) != null ) {
// throw new PersistentObjectException(
// "attempted to refresh transient instance when persistent " +
// "instance was already associated with the Session: " +
// MessageHelper.infoString( persister, id, source.getFactory() )
// );
// }
if ( persister.canWriteToCache() ) {
final EntityDataAccess cacheAccess = persister.getCacheAccessStrategy();
if ( cacheAccess != null ) {
final Object ck = cacheAccess.generateCacheKey(
id,
persister,
getFactory(),
getTenantIdentifier()
);
cacheAccess.evict( ck );
}
}
String previousFetchProfile = this.getLoadQueryInfluencers().getInternalFetchProfile();
Object result = null;
try {
this.getLoadQueryInfluencers().setInternalFetchProfile( "refresh" );
result = persister.load( id, entity, getNullSafeLockMode( lockMode ), this );
}
finally {
this.getLoadQueryInfluencers().setInternalFetchProfile( previousFetchProfile );
}
UnresolvableObjectException.throwIfNull( result, id, persister.getEntityName() );
if ( temporaryPersistenceContext.isLoadFinished() ) {
temporaryPersistenceContext.clear();
}
}
@Override
public Object immediateLoad(String entityName, Serializable id) throws HibernateException {
if ( getPersistenceContextInternal().isLoadFinished() ) {
throw new SessionException( "proxies cannot be fetched by a stateless session" );
}
// unless we are still in the process of handling a top-level load
return get( entityName, id );
}
@Override
public void initializeCollection(
PersistentCollection collection,
boolean writing) throws HibernateException {
throw new SessionException( "collections cannot be fetched by a stateless session" );
}
@Override
public Object instantiate(
String entityName,
Serializable id) throws HibernateException {
checkOpen();
return getFactory().getMetamodel().entityPersister( entityName ).instantiate( id, this );
}
@Override
public Object internalLoad(
String entityName,
Serializable id,
boolean eager,
boolean nullable) throws HibernateException {
checkOpen();
final EntityPersister persister = getFactory().getMetamodel().entityPersister( entityName );
final EntityKey entityKey = generateEntityKey( id, persister );
// first, try to load it from the temp PC associated to this SS
final PersistenceContext persistenceContext = getPersistenceContext();
Object loaded = persistenceContext.getEntity( entityKey );
if ( loaded != null ) {
// we found it in the temp PC. Should indicate we are in the midst of processing a result set
// containing eager fetches via join fetch
return loaded;
}
if ( !eager ) {
// caller did not request forceful eager loading, see if we can create
// some form of proxy
// first, check to see if we can use "bytecode proxies"
final EntityMetamodel entityMetamodel = persister.getEntityMetamodel();
final BytecodeEnhancementMetadata bytecodeEnhancementMetadata = entityMetamodel.getBytecodeEnhancementMetadata();
if ( allowBytecodeProxy && bytecodeEnhancementMetadata.isEnhancedForLazyLoading() ) {
// if the entity defines a HibernateProxy factory, see if there is an
// existing proxy associated with the PC - and if so, use it
if ( persister.getEntityMetamodel().getTuplizer().getProxyFactory() != null ) {
final Object proxy = persistenceContext.getProxy( entityKey );
if ( proxy != null ) {
if ( LOG.isTraceEnabled() ) {
LOG.trace( "Entity proxy found in session cache" );
}
if ( LOG.isDebugEnabled() && ( (HibernateProxy) proxy ).getHibernateLazyInitializer().isUnwrap() ) {
LOG.debug( "Ignoring NO_PROXY to honor laziness" );
}
return persistenceContext.narrowProxy( proxy, persister, entityKey, null );
}
// specialized handling for entities with subclasses with a HibernateProxy factory
if ( entityMetamodel.hasSubclasses() ) {
// entities with subclasses that define a ProxyFactory can create
// a HibernateProxy.
LOG.debugf( "Creating a HibernateProxy for to-one association with subclasses to honor laziness" );
return createProxy( entityKey );
}
return bytecodeEnhancementMetadata.createEnhancedProxy( entityKey, false, this );
}
else if ( !entityMetamodel.hasSubclasses() ) {
return bytecodeEnhancementMetadata.createEnhancedProxy( entityKey, false, this );
}
// If we get here, then the entity class has subclasses and there is no HibernateProxy factory.
// The entity will get loaded below.
}
else {
if ( persister.hasProxy() ) {
final Object existingProxy = persistenceContext.getProxy( entityKey );
if ( existingProxy != null ) {
return persistenceContext.narrowProxy( existingProxy, persister, entityKey, null );
}
else {
return createProxy( entityKey );
}
}
}
}
// otherwise immediately materialize it
// IMPLEMENTATION NOTE: increment/decrement the load count before/after getting the value
// to ensure that #get does not clear the PersistenceContext.
persistenceContext.beforeLoad();
try {
return get( entityName, id );
}
finally {
persistenceContext.afterLoad();
}
}
private Object createProxy(EntityKey entityKey) {
final Object proxy = entityKey.getPersister().createProxy( entityKey.getIdentifier(), this );
getPersistenceContext().addProxy( entityKey, proxy );
return proxy;
}
@Override
public Iterator iterate(String query, QueryParameters queryParameters) throws HibernateException {
throw new UnsupportedOperationException();
}
@Override
public Iterator iterateFilter(Object collection, String filter, QueryParameters queryParameters)
throws HibernateException {
throw new UnsupportedOperationException();
}
@Override
public List listFilter(Object collection, String filter, QueryParameters queryParameters)
throws HibernateException {
throw new UnsupportedOperationException();
}
@Override
public boolean isAutoCloseSessionEnabled() {
return getFactory().getSessionFactoryOptions().isAutoCloseSessionEnabled();
}
@Override
public boolean shouldAutoClose() {
return isAutoCloseSessionEnabled() && !isClosed();
}
private boolean isFlushModeNever() {
return false;
}
private void managedClose() {
if ( isClosed() ) {
throw new SessionException( "Session was already closed!" );
}
close();
}
private void managedFlush() {
checkOpen();
getJdbcCoordinator().executeBatch();
}
@Override
public String bestGuessEntityName(Object object) {
if ( object instanceof HibernateProxy ) {
object = ( (HibernateProxy) object ).getHibernateLazyInitializer().getImplementation();
}
return guessEntityName( object );
}
@Override
public Connection connection() {
checkOpen();
return getJdbcCoordinator().getLogicalConnection().getPhysicalConnection();
}
@Override
public int executeUpdate(String query, QueryParameters queryParameters) throws HibernateException {
checkOpen();
queryParameters.validateParameters();
HQLQueryPlan plan = getQueryPlan( query, false );
boolean success = false;
int result = 0;
try {
result = plan.performExecuteUpdate( queryParameters, this );
success = true;
}
finally {
afterOperation( success );
}
temporaryPersistenceContext.clear();
return result;
}
@Override
public CacheMode getCacheMode() {
return CacheMode.IGNORE;
}
@Override
public void setCacheMode(CacheMode cm) {
throw new UnsupportedOperationException();
}
@Override
public void setFlushMode(FlushMode fm) {
throw new UnsupportedOperationException();
}
@Override
public void setHibernateFlushMode(FlushMode flushMode) {
throw new UnsupportedOperationException();
}
@Override
public int getDontFlushFromFind() {
return 0;
}
@Override
public Serializable getContextEntityIdentifier(Object object) {
checkOpen();
return null;
}
public EntityMode getEntityMode() {
return EntityMode.POJO;
}
@Override
public String guessEntityName(Object entity) throws HibernateException {
checkOpen();
return entity.getClass().getName();
}
@Override
public EntityPersister getEntityPersister(String entityName, Object object)
throws HibernateException {
checkOpen();
if ( entityName == null ) {
return getFactory().getMetamodel().entityPersister( guessEntityName( object ) );
}
else {
return getFactory().getMetamodel().entityPersister( entityName ).getSubclassEntityPersister( object, getFactory() );
}
}
@Override
public Object getEntityUsingInterceptor(EntityKey key) throws HibernateException {
checkOpen();
final PersistenceContext persistenceContext = getPersistenceContext();
final Object result = persistenceContext.getEntity( key );
if ( result != null ) {
return result;
}
final Object newObject = getInterceptor().getEntity( key.getEntityName(), key.getIdentifier() );
if ( newObject != null ) {
persistenceContext.addEntity( key, newObject );
return newObject;
}
return null;
}
@Override
public PersistenceContext getPersistenceContext() {
return temporaryPersistenceContext;
}
@Override
public void setAutoClear(boolean enabled) {
throw new UnsupportedOperationException();
}
@Override
protected Object load(String entityName, Serializable identifier) {
return null;
}
@Override
public boolean isEventSource() {
return false;
}
public boolean isDefaultReadOnly() {
return false;
}
public void setDefaultReadOnly(boolean readOnly) throws HibernateException {
if ( readOnly ) {
throw new UnsupportedOperationException();
}
}
/////////////////////////////////////////////////////////////////////////////////////////////////////
//TODO: COPY/PASTE FROM SessionImpl, pull up!
@Override
public List list(String query, QueryParameters queryParameters) throws HibernateException {
checkOpen();
queryParameters.validateParameters();
HQLQueryPlan plan = getQueryPlan( query, false );
boolean success = false;
List results = Collections.EMPTY_LIST;
try {
results = plan.performList( queryParameters, this );
success = true;
}
finally {
afterOperation( success );
}
temporaryPersistenceContext.clear();
return results;
}
public void afterOperation(boolean success) {
if ( !isTransactionInProgress() ) {
getJdbcCoordinator().afterTransaction();
}
}
@Override
public Criteria createCriteria(Class persistentClass, String alias) {
checkOpen();
return new CriteriaImpl( persistentClass.getName(), alias, this );
}
@Override
public Criteria createCriteria(String entityName, String alias) {
checkOpen();
return new CriteriaImpl( entityName, alias, this );
}
@Override
public Criteria createCriteria(Class persistentClass) {
checkOpen();
return new CriteriaImpl( persistentClass.getName(), this );
}
@Override
public Criteria createCriteria(String entityName) {
checkOpen();
return new CriteriaImpl( entityName, this );
}
@Override
public ScrollableResultsImplementor scroll(Criteria criteria, ScrollMode scrollMode) {
// TODO: Is this guaranteed to always be CriteriaImpl?
CriteriaImpl criteriaImpl = (CriteriaImpl) criteria;
checkOpen();
String entityName = criteriaImpl.getEntityOrClassName();
CriteriaLoader loader = new CriteriaLoader(
getOuterJoinLoadable( entityName ),
getFactory(),
criteriaImpl,
entityName,
getLoadQueryInfluencers()
);
return loader.scroll( this, scrollMode );
}
@Override
@SuppressWarnings({"unchecked"})
public List list(Criteria criteria) throws HibernateException {
// TODO: Is this guaranteed to always be CriteriaImpl?
CriteriaImpl criteriaImpl = (CriteriaImpl) criteria;
checkOpen();
String[] implementors = getFactory().getMetamodel().getImplementors( criteriaImpl.getEntityOrClassName() );
int size = implementors.length;
CriteriaLoader[] loaders = new CriteriaLoader[size];
for ( int i = 0; i < size; i++ ) {
loaders[i] = new CriteriaLoader(
getOuterJoinLoadable( implementors[i] ),
getFactory(),
criteriaImpl,
implementors[i],
getLoadQueryInfluencers()
);
}
List results = Collections.EMPTY_LIST;
boolean success = false;
try {
for ( int i = 0; i < size; i++ ) {
final List currentResults = loaders[i].list( this );
currentResults.addAll( results );
results = currentResults;
}
success = true;
}
finally {
afterOperation( success );
}
temporaryPersistenceContext.clear();
return results;
}
private OuterJoinLoadable getOuterJoinLoadable(String entityName) throws MappingException {
EntityPersister persister = getFactory().getMetamodel().entityPersister( entityName );
if ( !( persister instanceof OuterJoinLoadable ) ) {
throw new MappingException( "class persister is not OuterJoinLoadable: " + entityName );
}
return (OuterJoinLoadable) persister;
}
@Override
public List listCustomQuery(CustomQuery customQuery, QueryParameters queryParameters)
throws HibernateException {
checkOpen();
CustomLoader loader = new CustomLoader( customQuery, getFactory() );
boolean success = false;
List results;
try {
results = loader.list( this, queryParameters );
success = true;
}
finally {
afterOperation( success );
}
temporaryPersistenceContext.clear();
return results;
}
@Override
public ScrollableResultsImplementor scrollCustomQuery(CustomQuery customQuery, QueryParameters queryParameters)
throws HibernateException {
checkOpen();
CustomLoader loader = new CustomLoader( customQuery, getFactory() );
return loader.scroll( queryParameters, this );
}
@Override
public ScrollableResultsImplementor scroll(String query, QueryParameters queryParameters) throws HibernateException {
checkOpen();
HQLQueryPlan plan = getQueryPlan( query, false );
return plan.performScroll( queryParameters, this );
}
@Override
public void afterScrollOperation() {
temporaryPersistenceContext.clear();
}
@Override
public void flush() {
}
@Override
public LoadQueryInfluencers getLoadQueryInfluencers() {
return NO_INFLUENCERS;
}
@Override
public PersistenceContext getPersistenceContextInternal() {
//In this case implemented the same as #getPersistenceContext
return temporaryPersistenceContext;
}
@Override
public int executeNativeUpdate(
NativeSQLQuerySpecification nativeSQLQuerySpecification,
QueryParameters queryParameters) throws HibernateException {
checkOpen();
queryParameters.validateParameters();
NativeSQLQueryPlan plan = getNativeQueryPlan( nativeSQLQuerySpecification );
boolean success = false;
int result = 0;
try {
result = plan.performExecuteUpdate( queryParameters, this );
success = true;
}
finally {
afterOperation( success );
}
temporaryPersistenceContext.clear();
return result;
}
@Override
public void afterTransactionBegin() {
}
@Override
public void beforeTransactionCompletion() {
flushBeforeTransactionCompletion();
}
@Override
public void afterTransactionCompletion(boolean successful, boolean delayed) {
if ( shouldAutoClose() && !isClosed() ) {
managedClose();
}
}
@Override
public boolean isTransactionInProgress() {
return connectionProvided || super.isTransactionInProgress();
}
@Override
public void flushBeforeTransactionCompletion() {
boolean flush = false;
try {
flush = (
!isClosed()
&& !isFlushModeNever()
&& !JtaStatusHelper.isRollback(
getJtaPlatform().getCurrentStatus()
) );
}
catch (SystemException se) {
throw new HibernateException( "could not determine transaction status in beforeCompletion()", se );
}
if ( flush ) {
managedFlush();
}
}
private JtaPlatform getJtaPlatform() {
return getFactory().getServiceRegistry().getService( JtaPlatform.class );
}
private LockMode getNullSafeLockMode(LockMode lockMode) {
return lockMode == null ? LockMode.NONE : lockMode;
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy