diff --git a/hibernate-core/src/main/java/org/hibernate/Session.java b/hibernate-core/src/main/java/org/hibernate/Session.java index 3dd61212d8..c7a0a9d79f 100644 --- a/hibernate-core/src/main/java/org/hibernate/Session.java +++ b/hibernate-core/src/main/java/org/hibernate/Session.java @@ -15,8 +15,6 @@ import org.hibernate.stat.SessionStatistics; import jakarta.persistence.CacheRetrieveMode; import jakarta.persistence.CacheStoreMode; -import jakarta.persistence.ConnectionConsumer; -import jakarta.persistence.ConnectionFunction; import jakarta.persistence.EntityGraph; import jakarta.persistence.EntityManager; import jakarta.persistence.FlushModeType; @@ -194,6 +192,7 @@ public interface Session extends SharedSessionContract, EntityManager { * * @throws HibernateException if changes could not be synchronized with the database */ + @Override void flush(); /** @@ -205,7 +204,7 @@ public interface Session extends SharedSessionContract, EntityManager { * * @param flushMode the new {@link FlushModeType} * - * @see #setHibernateFlushMode(FlushMode) for additional options + * @see #setHibernateFlushMode(FlushMode) */ @Override void setFlushMode(FlushModeType flushMode); @@ -232,6 +231,8 @@ public interface Session extends SharedSessionContract, EntityManager { * Get the current {@linkplain FlushModeType JPA flush mode} for this session. * * @return the {@link FlushModeType} currently in effect + * + * @see #getHibernateFlushMode() */ @Override FlushModeType getFlushMode(); @@ -267,6 +268,7 @@ public interface Session extends SharedSessionContract, EntityManager { * * @since 6.2 */ + @Override CacheStoreMode getCacheStoreMode(); /** @@ -276,6 +278,7 @@ public interface Session extends SharedSessionContract, EntityManager { * * @since 6.2 */ + @Override CacheRetrieveMode getCacheRetrieveMode(); /** @@ -287,6 +290,7 @@ public interface Session extends SharedSessionContract, EntityManager { * * @since 6.2 */ + @Override void setCacheStoreMode(CacheStoreMode cacheStoreMode); /** @@ -298,6 +302,7 @@ public interface Session extends SharedSessionContract, EntityManager { * * @since 6.2 */ + @Override void setCacheRetrieveMode(CacheRetrieveMode cacheRetrieveMode); /** @@ -474,9 +479,109 @@ public interface Session extends SharedSessionContract, EntityManager { */ void evict(Object object); + /** + * Return the persistent instance of the given entity class with the given identifier, + * or null if there is no such persistent instance. If the instance is already associated + * with the session, return that instance. This method never returns an uninitialized + * instance. + *

+ * The object returned by {@code get()} or {@code find()} is either an unproxied instance + * of the given entity class, or a fully-fetched proxy object. + *

+ * This operation requests {@link LockMode#NONE}, that is, no lock, allowing the object + * to be retrieved from the cache without the cost of database access. However, if it is + * necessary to read the state from the database, the object will be returned with the + * lock mode {@link LockMode#READ}. + *

+ * To bypass the {@linkplain Cache second-level cache}, and ensure that the state of the + * requested instance is read directly from the database, either: + *

+ * + * @apiNote This operation is very similar to {@link #get(Class, Object)}. + * + * @param entityType the entity type + * @param id an identifier + * + * @return a fully-fetched persistent instance or null + */ + @Override + T find(Class entityType, Object id); + + /** + * Return the persistent instance of the given entity class with the given identifier, + * or null if there is no such persistent instance. If the instance is already associated + * with the session, return that instance. This method never returns an uninitialized + * instance. Obtain the specified lock mode if the instance exists. + *

+ * Convenient form of {@link #find(Class, Object, LockOptions)}. + * + * @param entityType the entity type + * @param id an identifier + * @param lockMode the lock mode + * + * @return a fully-fetched persistent instance or null + * + * @since 7.0 + * + * @see #find(Class, Object, LockOptions) + */ + T find(Class entityType, Object id, LockMode lockMode); + + /** + * Return the persistent instance of the given entity class with the given identifier, + * or null if there is no such persistent instance. If the instance is already associated + * with the session, return that instance. This method never returns an uninitialized + * instance. Obtain the specified lock mode if the instance exists. + * + * @param entityType the entity type + * @param id an identifier + * @param lockOptions the lock mode + * + * @return a fully-fetched persistent instance or null + * + * @since 7.0 + */ + T find(Class entityType, Object id, LockOptions lockOptions); + + /** + * Return the persistent instances of the given entity class with the given identifiers + * as a list. The position of an instance in the returned list matches the position of its + * identifier in the given list of identifiers, and the returned list contains a null value + * if there is no persistent instance matching a given identifier. If an instance is already + * associated with the session, that instance is returned. This method never returns an + * uninitialized instance. + *

+ * Every object returned by {@code findMultiple()} is either an unproxied instance of the + * given entity class, or a fully-fetched proxy object. + *

+ * For more advanced cases, use {@link #byMultipleIds(Class)}, which returns an instance of + * {@link MultiIdentifierLoadAccess}. + * + * @param entityType the entity type + * @param ids the list of identifiers + * @param options options, if any + * + * @return an ordered list of persistent instances, with null elements representing missing + * entities, whose positions in the list match the positions of their ids in the + * given list of identifiers + * @see #byMultipleIds(Class) + * @since 7.0 + */ + List findMultiple(Class entityType, List ids, FindOption... options); + /** * Read the persistent state associated with the given identifier into the given * transient instance. + * + * @param object a transient instance of an entity class + * @param id an identifier */ void load(Object object, Object id); @@ -524,6 +629,7 @@ public interface Session extends SharedSessionContract, EntityManager { * * @return an updated persistent instance */ + @Override T merge(T object); /** @@ -554,6 +660,7 @@ public interface Session extends SharedSessionContract, EntityManager { * * @param object a transient instance to be made persistent */ + @Override void persist(Object object); /** @@ -635,6 +742,7 @@ public interface Session extends SharedSessionContract, EntityManager { * * @param object a persistent instance associated with this session */ + @Override void refresh(Object object); /** @@ -688,39 +796,15 @@ public interface Session extends SharedSessionContract, EntityManager { * saves, updates and deletions. Do not close open iterators or instances of * {@link ScrollableResults}. */ + @Override void clear(); - /** - * Return the persistent instances of the given entity class with the given identifiers - * as a list. The position of an instance in the list matches the position of its identifier - * in the given array, and the list contains a null value if there is no persistent instance - * matching a given identifier. If an instance is already associated with the session, that - * instance is returned. This method never returns an uninitialized instance. - *

- * Every object returned by {@code findMultiple()} is either an unproxied instance of the - * given entity class, or a fully-fetched proxy object. - *

- * For more advanced cases, use {@link #byMultipleIds(Class)}, which returns an instance of - * {@link MultiIdentifierLoadAccess}. - * - * @param entityType the entity type - * @param ids the identifiers - * @param options options, if any - * @return an ordered list of persistent instances, with null elements representing missing - * entities - * @see #byMultipleIds(Class) - * @since 7.0 - */ - List findMultiple(Class entityType, List ids, FindOption... options); - /** * Return the persistent instance of the given entity class with the given identifier, * or null if there is no such persistent instance. If the instance is already associated * with the session, return that instance. This method never returns an uninitialized * instance. *

- * This operation is very similar to {@link #find(Class, Object)}. - *

* The object returned by {@code get()} or {@code find()} is either an unproxied instance * of the given entity class, or a fully-fetched proxy object. *

@@ -734,10 +818,12 @@ public interface Session extends SharedSessionContract, EntityManager { *

    *
  • call {@link #get(Class, Object, LockMode)} with the explicit lock mode * {@link LockMode#READ}, or - *
  • {@linkplain #setCacheMode(CacheMode) set the cache mode} to {@link CacheMode#IGNORE} + *
  • {@linkplain #setCacheMode set the cache mode} to {@link CacheMode#IGNORE} * before calling this method. *
* + * @apiNote This operation is very similar to {@link #find(Class, Object)}. + * * @param entityType the entity type * @param id an identifier * @@ -752,8 +838,8 @@ public interface Session extends SharedSessionContract, EntityManager { * instance. Obtain the specified lock mode if the instance exists. *

* Convenient form of {@link #get(Class, Object, LockOptions)}. - *

- * This operation is very similar to {@link #find(Class, Object, jakarta.persistence.LockModeType)}. + * + * @apiNote This operation is very similar to {@link #find(Class, Object, LockModeType)}. * * @param entityType the entity type * @param id an identifier @@ -886,6 +972,7 @@ public interface Session extends SharedSessionContract, EntityManager { * * @since 6.0 */ + @Override T getReference(T object); /** @@ -1026,15 +1113,6 @@ public interface Session extends SharedSessionContract, EntityManager { */ NaturalIdMultiLoadAccess byMultipleNaturalId(String entityName); - @Override - Filter enableFilter(String filterName); - - @Override - Filter getEnabledFilter(String filterName); - - @Override - void disableFilter(String filterName); - /** * Get the {@linkplain SessionStatistics statistics} for this session. * @@ -1196,32 +1274,4 @@ public interface Session extends SharedSessionContract, EntityManager { */ @Override @Deprecated(since = "6.0") @SuppressWarnings("rawtypes") Query createQuery(CriteriaUpdate updateQuery); - - - @Override - default void runWithConnection(ConnectionConsumer action) { - doWork( connection -> { - try { - //noinspection unchecked - action.accept( (C) connection ); - } - catch (Exception e) { - throw new RuntimeException( e ); - } - } ); - } - - @Override - default T callWithConnection(ConnectionFunction function) { - return doReturningWork( (connection) -> { - try { - //noinspection unchecked - return function.apply( (C) connection ); - } - catch (Exception e) { - throw new RuntimeException( e ); - } - } ); - } - } diff --git a/hibernate-core/src/main/java/org/hibernate/SessionFactory.java b/hibernate-core/src/main/java/org/hibernate/SessionFactory.java index bdf1558146..6ae33f1a94 100644 --- a/hibernate-core/src/main/java/org/hibernate/SessionFactory.java +++ b/hibernate-core/src/main/java/org/hibernate/SessionFactory.java @@ -302,6 +302,7 @@ public interface SessionFactory extends EntityManagerFactory, Referenceable, Ser * * @since 6.2 */ + @Override SchemaManager getSchemaManager(); /** @@ -327,6 +328,7 @@ public interface SessionFactory extends EntityManagerFactory, Referenceable, Ser * * @throws HibernateException Indicates an issue closing the factory. */ + @Override void close() throws HibernateException; /** diff --git a/hibernate-core/src/main/java/org/hibernate/engine/spi/SessionDelegatorBaseImpl.java b/hibernate-core/src/main/java/org/hibernate/engine/spi/SessionDelegatorBaseImpl.java index df9fef34ef..d4ac73bf68 100644 --- a/hibernate-core/src/main/java/org/hibernate/engine/spi/SessionDelegatorBaseImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/engine/spi/SessionDelegatorBaseImpl.java @@ -871,6 +871,16 @@ public class SessionDelegatorBaseImpl implements SessionImplementor { return delegate.find( entityGraph, primaryKey, options ); } + @Override + public T find(Class entityType, Object id, LockMode lockMode) { + return delegate.find( entityType, id, lockMode ); + } + + @Override + public T find(Class entityType, Object id, LockOptions lockOptions) { + return delegate.find( entityType, id, lockOptions ); + } + @Override public T getReference(Class entityClass, Object id) { return delegate.getReference( entityClass, id ); diff --git a/hibernate-core/src/main/java/org/hibernate/engine/spi/SessionImplementor.java b/hibernate-core/src/main/java/org/hibernate/engine/spi/SessionImplementor.java index 797650a555..6e04cbef2a 100644 --- a/hibernate-core/src/main/java/org/hibernate/engine/spi/SessionImplementor.java +++ b/hibernate-core/src/main/java/org/hibernate/engine/spi/SessionImplementor.java @@ -4,6 +4,8 @@ */ package org.hibernate.engine.spi; +import jakarta.persistence.ConnectionConsumer; +import jakarta.persistence.ConnectionFunction; import org.hibernate.HibernateException; import org.hibernate.LockOptions; import org.hibernate.Session; @@ -108,4 +110,29 @@ public interface SessionImplementor extends Session, SharedSessionContractImplem return true; } + @Override + default void runWithConnection(ConnectionConsumer action) { + doWork( connection -> { + try { + //noinspection unchecked + action.accept( (C) connection ); + } + catch (Exception e) { + throw new RuntimeException( e ); + } + } ); + } + + @Override + default T callWithConnection(ConnectionFunction function) { + return doReturningWork( connection -> { + try { + //noinspection unchecked + return function.apply( (C) connection ); + } + catch (Exception e) { + throw new RuntimeException( e ); + } + } ); + } } diff --git a/hibernate-core/src/main/java/org/hibernate/engine/spi/SessionLazyDelegator.java b/hibernate-core/src/main/java/org/hibernate/engine/spi/SessionLazyDelegator.java index 7f5d4334bf..e31c63a7a5 100644 --- a/hibernate-core/src/main/java/org/hibernate/engine/spi/SessionLazyDelegator.java +++ b/hibernate-core/src/main/java/org/hibernate/engine/spi/SessionLazyDelegator.java @@ -774,6 +774,16 @@ public class SessionLazyDelegator implements Session { return this.lazySession.get().find( entityGraph, primaryKey, options ); } + @Override + public T find(Class entityType, Object id, LockMode lockMode) { + return this.lazySession.get().find( entityType, id, lockMode ); + } + + @Override + public T find(Class entityType, Object id, LockOptions lockOptions) { + return this.lazySession.get().find( entityType, id, lockOptions ); + } + @Override public void lock(Object entity, LockModeType lockMode) { this.lazySession.get().lock( entity, lockMode ); diff --git a/hibernate-core/src/main/java/org/hibernate/internal/SessionImpl.java b/hibernate-core/src/main/java/org/hibernate/internal/SessionImpl.java index 23aa2d869a..e3dd9532d4 100644 --- a/hibernate-core/src/main/java/org/hibernate/internal/SessionImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/internal/SessionImpl.java @@ -2292,12 +2292,12 @@ public class SessionImpl @Override public T find(Class entityClass, Object primaryKey) { - return find( entityClass, primaryKey, null, null ); + return find( entityClass, primaryKey, (LockOptions) null, null ); } @Override public T find(Class entityClass, Object primaryKey, Map properties) { - return find( entityClass, primaryKey, null, properties ); + return find( entityClass, primaryKey, (LockOptions) null, properties ); } @Override @@ -2305,20 +2305,35 @@ public class SessionImpl return find( entityClass, primaryKey, lockModeType, null ); } + @Override + public T find(Class entityType, Object id, LockMode lockMode) { + checkTransactionNeededForLock( lockMode ); + final LockOptions lockOptions = copySessionLockOptions(); + lockOptions.setLockMode( lockMode ); + return find( entityType, id, lockOptions, null ); + } + + @Override + public T find(Class entityType, Object id, LockOptions lockOptions) { + checkTransactionNeededForLock( lockOptions.getLockMode() ); + return find( entityType, id, lockOptions, null ); + } + @Override public T find(Class entityClass, Object primaryKey, LockModeType lockModeType, Map properties) { checkOpen(); + if ( lockModeType == null ) { + throw new IllegalArgumentException("Given LockModeType was null"); + } + final LockMode lockMode = LockModeTypeHelper.getLockMode( lockModeType ); + checkTransactionNeededForLock( lockMode ); + return find( entityClass, primaryKey, buildLockOptions( lockMode, properties ), properties ); + } - final LockOptions lockOptions = lockModeType == null ? null : buildLockOptions( lockModeType, properties ); + private T find(Class entityClass, Object primaryKey, LockOptions lockOptions, Map properties) { try { - if ( lockModeType != null ) { - checkTransactionNeededForLock( LockModeTypeHelper.getLockMode( lockModeType ) ); - } - - final EffectiveEntityGraph effectiveEntityGraph = loadQueryInfluencers.getEffectiveEntityGraph(); - effectiveEntityGraph.applyConfiguredGraph( properties ); + loadQueryInfluencers.getEffectiveEntityGraph().applyConfiguredGraph( properties ); loadQueryInfluencers.setReadOnly( readOnlyHint( properties ) ); - return byId( entityClass ) .with( determineAppropriateLocalCacheMode( properties ) ) .with( lockOptions ) @@ -2531,17 +2546,17 @@ public class SessionImpl @Override public void lock(Object entity, LockModeType lockModeType, Map properties) { - lock( entity, buildLockOptions( lockModeType, properties ) ); + lock( entity, buildLockOptions( LockModeTypeHelper.getLockMode( lockModeType ), properties ) ); } @Override - public void lock(Object entity, LockModeType lockMode, LockOption... options) { - lock( entity, buildLockOptions( lockMode, options ) ); + public void lock(Object entity, LockModeType lockModeType, LockOption... options) { + lock( entity, buildLockOptions( LockModeTypeHelper.getLockMode( lockModeType ), options ) ); } - private LockOptions buildLockOptions(LockModeType lockModeType, LockOption[] options) { + private LockOptions buildLockOptions(LockMode lockMode, LockOption[] options) { final LockOptions lockOptions = copySessionLockOptions(); - lockOptions.setLockMode( LockModeTypeHelper.getLockMode( lockModeType ) ); + lockOptions.setLockMode( lockMode ); for ( LockOption option : options ) { if ( option instanceof PessimisticLockScope lockScope ) { lockOptions.setLockScope( lockScope ); @@ -2553,9 +2568,9 @@ public class SessionImpl return lockOptions; } - private LockOptions buildLockOptions(LockModeType lockModeType, Map properties) { + private LockOptions buildLockOptions(LockMode lockMode, Map properties) { final LockOptions lockOptions = copySessionLockOptions(); - lockOptions.setLockMode( LockModeTypeHelper.getLockMode( lockModeType ) ); + lockOptions.setLockMode( lockMode ); if ( properties != null ) { applyPropertiesToLockOptions( properties, () -> lockOptions ); } @@ -2591,7 +2606,7 @@ public class SessionImpl refresh( entity ); } else { - refresh( entity, buildLockOptions( lockModeType, properties ) ); + refresh( entity, buildLockOptions( LockModeTypeHelper.getLockMode( lockModeType ), properties ) ); } } finally { diff --git a/hibernate-core/src/main/java/org/hibernate/internal/util/LockModeConverter.java b/hibernate-core/src/main/java/org/hibernate/internal/util/LockModeConverter.java index cb029aeb29..f7016cf6ec 100644 --- a/hibernate-core/src/main/java/org/hibernate/internal/util/LockModeConverter.java +++ b/hibernate-core/src/main/java/org/hibernate/internal/util/LockModeConverter.java @@ -6,7 +6,6 @@ package org.hibernate.internal.util; import jakarta.persistence.LockModeType; -import org.hibernate.AssertionFailure; import org.hibernate.LockMode; /** @@ -26,26 +25,14 @@ public final class LockModeConverter { * @return The JPA {@link LockModeType} */ public static LockModeType convertToLockModeType(LockMode lockMode) { - switch (lockMode) { - case NONE: - case READ: // no exact equivalent in JPA - return LockModeType.NONE; - case OPTIMISTIC: - return LockModeType.OPTIMISTIC; - case OPTIMISTIC_FORCE_INCREMENT: - return LockModeType.OPTIMISTIC_FORCE_INCREMENT; - case PESSIMISTIC_READ: - return LockModeType.PESSIMISTIC_READ; - case PESSIMISTIC_WRITE: - case UPGRADE_NOWAIT: - case UPGRADE_SKIPLOCKED: - return LockModeType.PESSIMISTIC_WRITE; - case WRITE: // no exact equivalent in JPA - case PESSIMISTIC_FORCE_INCREMENT: - return LockModeType.PESSIMISTIC_FORCE_INCREMENT; - default: - throw new AssertionFailure( "unhandled lock mode " + lockMode ); - } + return switch ( lockMode ) { + case NONE, READ -> LockModeType.NONE; // no exact equivalent in JPA + case OPTIMISTIC -> LockModeType.OPTIMISTIC; + case OPTIMISTIC_FORCE_INCREMENT -> LockModeType.OPTIMISTIC_FORCE_INCREMENT; + case PESSIMISTIC_READ -> LockModeType.PESSIMISTIC_READ; + case PESSIMISTIC_WRITE, UPGRADE_NOWAIT, UPGRADE_SKIPLOCKED -> LockModeType.PESSIMISTIC_WRITE; // no exact equivalent in JPA + case WRITE, PESSIMISTIC_FORCE_INCREMENT -> LockModeType.PESSIMISTIC_FORCE_INCREMENT; + }; } @@ -56,23 +43,13 @@ public final class LockModeConverter { * @return The Hibernate {@link LockMode}. */ public static LockMode convertToLockMode(LockModeType lockModeType) { - switch ( lockModeType ) { - case NONE: - return LockMode.NONE; - case READ: - case OPTIMISTIC: - return LockMode.OPTIMISTIC; - case WRITE: - case OPTIMISTIC_FORCE_INCREMENT: - return LockMode.OPTIMISTIC_FORCE_INCREMENT; - case PESSIMISTIC_READ: - return LockMode.PESSIMISTIC_READ; - case PESSIMISTIC_WRITE: - return LockMode.PESSIMISTIC_WRITE; - case PESSIMISTIC_FORCE_INCREMENT: - return LockMode.PESSIMISTIC_FORCE_INCREMENT; - default: - throw new AssertionFailure( "Unknown LockModeType: " + lockModeType ); - } + return switch ( lockModeType ) { + case NONE -> LockMode.NONE; + case READ, OPTIMISTIC -> LockMode.OPTIMISTIC; + case WRITE, OPTIMISTIC_FORCE_INCREMENT -> LockMode.OPTIMISTIC_FORCE_INCREMENT; + case PESSIMISTIC_READ -> LockMode.PESSIMISTIC_READ; + case PESSIMISTIC_WRITE -> LockMode.PESSIMISTIC_WRITE; + case PESSIMISTIC_FORCE_INCREMENT -> LockMode.PESSIMISTIC_FORCE_INCREMENT; + }; } }