Skip to content

Commit 159be18

Browse files
committed
HHH-16383 - NaturalIdClass
1 parent 70e476b commit 159be18

File tree

14 files changed

+2016
-1564
lines changed

14 files changed

+2016
-1564
lines changed
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
/*
2+
* SPDX-License-Identifier: Apache-2.0
3+
* Copyright Red Hat Inc. and Hibernate Authors
4+
*/
5+
package org.hibernate;
6+
7+
import jakarta.persistence.FindOption;
8+
9+
/// Indicates whether to perform synchronization (a sort of flush)
10+
/// before a [find by natural-id][FindBy#NATURAL_ID].
11+
///
12+
/// @author Steve Ebersole
13+
public enum NaturalIdSynchronization implements FindOption {
14+
/// Perform the synchronization.
15+
ENABLED,
16+
17+
/// Do not perform the synchronization.
18+
DISABLED;
19+
}

hibernate-core/src/main/java/org/hibernate/Session.java

Lines changed: 1127 additions & 1351 deletions
Large diffs are not rendered by default.

hibernate-core/src/main/java/org/hibernate/Timeouts.java

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -146,4 +146,17 @@ static int fromHint(Object factoryHint) {
146146
}
147147
return Integer.parseInt( factoryHint.toString() );
148148
}
149+
150+
static Timeout fromHintTimeout(Object factoryHint) {
151+
if ( factoryHint == null ) {
152+
return WAIT_FOREVER;
153+
}
154+
if ( factoryHint instanceof Timeout timeout ) {
155+
return timeout;
156+
}
157+
if ( factoryHint instanceof Integer number ) {
158+
return Timeout.milliseconds( number );
159+
}
160+
return Timeout.milliseconds( Integer.parseInt( factoryHint.toString() ) );
161+
}
149162
}

hibernate-core/src/main/java/org/hibernate/engine/spi/SessionDelegatorBaseImpl.java

Lines changed: 0 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -906,26 +906,6 @@ public Object find(String entityName, Object primaryKey, FindOption... options)
906906
return delegate.find( entityName, primaryKey, options );
907907
}
908908

909-
@Override
910-
public <T> T findByNaturalId(Class<T> entityType, Object naturalId, FindOption... options) {
911-
return delegate.findByNaturalId( entityType, naturalId, options );
912-
}
913-
914-
@Override
915-
public Object findByNaturalId(String entityName, Object naturalId, FindOption... options) {
916-
return delegate.findByNaturalId( entityName, naturalId, options );
917-
}
918-
919-
@Override
920-
public <T> List<T> findMultipleByNaturalId(Class<T> entityType, List<?> naturalIds, FindOption... options) {
921-
return delegate.findMultipleByNaturalId( entityType, naturalIds, options );
922-
}
923-
924-
@Override
925-
public List<Object> findMultipleByNaturalId(String entityName, List<?> naturalIds, FindOption... options) {
926-
return delegate.findMultipleByNaturalId( entityName, naturalIds, options );
927-
}
928-
929909
@Override
930910
public <T> T getReference(Class<T> entityClass, Object id) {
931911
return delegate.getReference( entityClass, id );

hibernate-core/src/main/java/org/hibernate/engine/spi/SessionLazyDelegator.java

Lines changed: 0 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -820,26 +820,6 @@ public Object find(String entityName, Object primaryKey, FindOption... options)
820820
return this.lazySession.get().find( entityName, primaryKey, options );
821821
}
822822

823-
@Override
824-
public <T> T findByNaturalId(Class<T> entityType, Object naturalId, FindOption... options) {
825-
return lazySession.get().findByNaturalId( entityType, naturalId, options );
826-
}
827-
828-
@Override
829-
public Object findByNaturalId(String entityName, Object naturalId, FindOption... options) {
830-
return lazySession.get().findByNaturalId( entityName, naturalId, options );
831-
}
832-
833-
@Override
834-
public <T> List<T> findMultipleByNaturalId(Class<T> entityType, List<?> naturalIds, FindOption... options) {
835-
return lazySession.get().findMultipleByNaturalId( entityType, naturalIds, options );
836-
}
837-
838-
@Override
839-
public List<Object> findMultipleByNaturalId(String entityName, List<?> naturalIds, FindOption... options) {
840-
return lazySession.get().findMultipleByNaturalId( entityName, naturalIds, options );
841-
}
842-
843823
@Override
844824
public void lock(Object entity, LockModeType lockMode) {
845825
this.lazySession.get().lock( entity, lockMode );

hibernate-core/src/main/java/org/hibernate/internal/NaturalIdMultiLoadAccessStandard.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@
2828
/**
2929
* @author Steve Ebersole
3030
*/
31-
class NaturalIdMultiLoadAccessStandard<T> implements NaturalIdMultiLoadAccess<T>, MultiNaturalIdLoadOptions {
31+
public class NaturalIdMultiLoadAccessStandard<T> implements NaturalIdMultiLoadAccess<T>, MultiNaturalIdLoadOptions {
3232
private final EntityPersister entityDescriptor;
3333
private final SharedSessionContractImplementor session;
3434

@@ -42,7 +42,7 @@ class NaturalIdMultiLoadAccessStandard<T> implements NaturalIdMultiLoadAccess<T>
4242
private RemovalsMode removalsMode = RemovalsMode.REPLACE;
4343
private OrderingMode orderingMode = OrderingMode.ORDERED;
4444

45-
NaturalIdMultiLoadAccessStandard(EntityPersister entityDescriptor, SharedSessionContractImplementor session) {
45+
public NaturalIdMultiLoadAccessStandard(EntityPersister entityDescriptor, SharedSessionContractImplementor session) {
4646
this.entityDescriptor = entityDescriptor;
4747
this.session = session;
4848
}

hibernate-core/src/main/java/org/hibernate/internal/SessionImpl.java

Lines changed: 70 additions & 141 deletions
Original file line numberDiff line numberDiff line change
@@ -41,8 +41,9 @@
4141
import org.hibernate.event.spi.*;
4242
import org.hibernate.event.spi.LoadEventListener.LoadType;
4343
import org.hibernate.graph.GraphSemantic;
44-
import org.hibernate.graph.RootGraph;
4544
import org.hibernate.graph.spi.RootGraphImplementor;
45+
import org.hibernate.internal.find.FindByKeyOperation;
46+
import org.hibernate.internal.find.FindMultipleByKeyOperation;
4647
import org.hibernate.internal.util.ExceptionHelper;
4748
import org.hibernate.jpa.internal.LegacySpecHelper;
4849
import org.hibernate.jpa.internal.util.ConfigurationHelper;
@@ -991,30 +992,45 @@ else if ( option instanceof RemovalsMode ) {
991992
}
992993

993994
@Override
994-
public <E> List<E> findMultiple(Class<E> entityType, List<?> ids, FindOption... options) {
995-
final var loadAccess = byMultipleIds( entityType );
996-
final boolean isFindByNaturalId = setMultiIdentifierLoadAccessOptions( options, loadAccess );
997-
if ( isFindByNaturalId ) {
998-
return findMultipleByNaturalId( entityType, ids, options );
999-
}
1000-
return loadAccess.multiLoad( ids );
995+
public <E> List<E> findMultiple(Class<E> entityType, List<?> keys, FindOption... options) {
996+
//noinspection unchecked
997+
return findMultiple(
998+
requireEntityPersister( entityType ),
999+
loadQueryInfluencers.getEffectiveEntityGraph().getSemantic(),
1000+
(RootGraphImplementor<E>) loadQueryInfluencers.getEffectiveEntityGraph().getGraph(),
1001+
(List<Object>) keys,
1002+
options
1003+
);
1004+
}
1005+
1006+
private <E> List<E> findMultiple(
1007+
EntityPersister entityDescriptor,
1008+
GraphSemantic graphSemantic,
1009+
RootGraphImplementor<E> rootGraph,
1010+
List<Object> keys,
1011+
FindOption... options) {
1012+
final var operation = new FindMultipleByKeyOperation<E>(
1013+
entityDescriptor,
1014+
lockOptions,
1015+
getCacheMode(),
1016+
isDefaultReadOnly(),
1017+
getFactory(),
1018+
options
1019+
);
1020+
return operation.performFind( keys, graphSemantic, rootGraph, this );
10011021
}
10021022

10031023
@Override
1004-
public <E> List<E> findMultiple(EntityGraph<E> entityGraph, List<?> ids, FindOption... options) {
1005-
final var rootGraph = (RootGraph<E>) entityGraph;
1024+
public <E> List<E> findMultiple(EntityGraph<E> entityGraph, List<?> keys, FindOption... options) {
1025+
final var rootGraph = (RootGraphImplementor<E>) entityGraph;
10061026
final var type = rootGraph.getGraphedType();
1007-
final MultiIdentifierLoadAccess<E> loadAccess =
1008-
switch ( type.getRepresentationMode() ) {
1009-
case MAP -> byMultipleIds( type.getTypeName() );
1010-
case POJO -> byMultipleIds( type.getJavaType() );
1011-
};
1012-
loadAccess.withLoadGraph( rootGraph );
1013-
final boolean isFindByNaturalId = setMultiIdentifierLoadAccessOptions( options, loadAccess );
1014-
if ( isFindByNaturalId ) {
1015-
throw new UnsupportedOperationException( "Find by natural-id with entity-graph is not supported" );
1016-
}
1017-
return loadAccess.multiLoad( ids );
1027+
final var entityDescriptor = switch ( type.getRepresentationMode() ) {
1028+
case POJO -> requireEntityPersister( type.getJavaType() );
1029+
case MAP -> requireEntityPersister( type.getTypeName() );
1030+
};
1031+
1032+
//noinspection unchecked
1033+
return findMultiple( entityDescriptor, GraphSemantic.LOAD, rootGraph, (List<Object>) keys, options );
10181034
}
10191035

10201036
@Override
@@ -2331,28 +2347,22 @@ else if ( option instanceof FindMultipleOption findMultipleOption ) {
23312347

23322348
@Override
23332349
public <T> T find(Class<T> entityClass, Object key, FindOption... options) {
2334-
final IdentifierLoadAccessImpl<T> loadAccess = byId( entityClass );
2335-
final boolean isFindByNaturalId = setLoadAccessOptions( options, loadAccess );
2336-
if ( isFindByNaturalId ) {
2337-
return findByNaturalId( entityClass, key, options );
2338-
}
2339-
return loadAccess.load( key );
2350+
//noinspection unchecked
2351+
return (T) byKey( requireEntityPersister( entityClass ), options ).performFind( key, this );
23402352
}
23412353

23422354
@Override
2343-
public <T> T find(EntityGraph<T> entityGraph, Object primaryKey, FindOption... options) {
2344-
final var graph = (RootGraph<T>) entityGraph;
2355+
public <T> T find(EntityGraph<T> entityGraph, Object key, FindOption... options) {
2356+
final var graph = (RootGraphImplementor<T>) entityGraph;
23452357
final var type = graph.getGraphedType();
2346-
final IdentifierLoadAccessImpl<T> loadAccess =
2347-
switch ( type.getRepresentationMode() ) {
2348-
case MAP -> byId( type.getTypeName() );
2349-
case POJO -> byId( type.getJavaType() );
2350-
};
2351-
final boolean isFindByNaturalId = setLoadAccessOptions( options, loadAccess );
2352-
if ( isFindByNaturalId ) {
2353-
throw new UnsupportedOperationException( "Find by natural-id with entity-graph is not supported" );
2354-
}
2355-
return loadAccess.withLoadGraph( graph ).load( primaryKey );
2358+
2359+
final EntityPersister entityDescriptor = switch ( type.getRepresentationMode() ) {
2360+
case POJO -> requireEntityPersister( type.getJavaType() );
2361+
case MAP -> requireEntityPersister( type.getTypeName() );
2362+
};
2363+
2364+
//noinspection unchecked
2365+
return (T) byKey( entityDescriptor, GraphSemantic.LOAD, graph, options ).performFind( key, this );
23562366
}
23572367

23582368
// Hibernate Reactive may need to use this
@@ -2415,115 +2425,34 @@ private void checkTransactionNeededForUpdateOperation() {
24152425
}
24162426

24172427
@Override
2418-
public Object find(String entityName, Object primaryKey) {
2419-
final IdentifierLoadAccessImpl<?> loadAccess = byId( entityName );
2420-
return loadAccess.load( primaryKey );
2421-
}
2422-
2423-
@Override
2424-
public Object find(String entityName, Object primaryKey, FindOption... options) {
2425-
final IdentifierLoadAccessImpl<?> loadAccess = byId( entityName );
2426-
final boolean isFindByNaturalId = setLoadAccessOptions( options, loadAccess );
2427-
if ( isFindByNaturalId ) {
2428-
return findByNaturalId( entityName, primaryKey, options );
2429-
}
2430-
return loadAccess.load( primaryKey );
2431-
}
2432-
2433-
@Override
2434-
public <T> T findByNaturalId(Class<T> entityType, Object naturalId, FindOption... options) {
2435-
final SimpleNaturalIdLoadAccessImpl<T> access = (SimpleNaturalIdLoadAccessImpl<T>) bySimpleNaturalId( entityType );
2436-
setOptions( options, access );
2437-
return access.load( naturalId );
2438-
}
2439-
2440-
private <T> void setOptions(FindOption[] options, SimpleNaturalIdLoadAccessImpl<T> access) {
2441-
for ( FindOption option : options ) {
2442-
if ( option instanceof FindBy findBy ) {
2443-
if ( findBy == FindBy.ID ) {
2444-
throw new IllegalArgumentException( "Cannot use FindBy#ID with findByNaturalId" );
2445-
}
2446-
}
2447-
else if ( option instanceof LockMode lockMode ) {
2448-
access.with( lockMode );
2449-
}
2450-
else if ( option instanceof LockModeType lockModeType ) {
2451-
access.with( LockMode.fromJpaLockMode( lockModeType ) );
2452-
}
2453-
else if ( option instanceof Locking.Scope scope ) {
2454-
access.with( scope );
2455-
}
2456-
else if ( option instanceof PessimisticLockScope scope ) {
2457-
access.with( Locking.Scope.fromJpaScope( scope ) );
2458-
}
2459-
else if ( option instanceof Timeout timeout ) {
2460-
access.with( timeout );
2461-
}
2462-
else {
2463-
throw new IllegalArgumentException( "Illegal option: " + option );
2464-
}
2465-
}
2466-
}
2467-
2468-
@Override
2469-
public Object findByNaturalId(String entityName, Object naturalId, FindOption... options) {
2470-
final SimpleNaturalIdLoadAccessImpl<?> access = (SimpleNaturalIdLoadAccessImpl<?>) bySimpleNaturalId( entityName );
2471-
setOptions( options, access );
2472-
return access.load( naturalId );
2428+
public Object find(String entityName, Object key) {
2429+
return byKey( requireEntityPersister( entityName ) ).performFind( key, this );
24732430
}
24742431

24752432
@Override
2476-
public <T> List<T> findMultipleByNaturalId(Class<T> entityType, List<?> naturalIds, FindOption... options) {
2477-
final NaturalIdMultiLoadAccessStandard<T> access = (NaturalIdMultiLoadAccessStandard<T>) byMultipleNaturalId( entityType );
2478-
setOptions( options, access );
2479-
return access.multiLoad( naturalIds );
2433+
public Object find(String entityName, Object key, FindOption... options) {
2434+
return byKey( requireEntityPersister( entityName ), options ).performFind( key, this );
24802435
}
24812436

2482-
private <T> void setOptions(FindOption[] options, NaturalIdMultiLoadAccessStandard<T> access) {
2483-
for ( FindOption option : options ) {
2484-
if ( option instanceof FindBy findBy ) {
2485-
if ( findBy == FindBy.ID ) {
2486-
throw new IllegalArgumentException( "Cannot use FindBy#ID with findMultipleByNaturalId" );
2487-
}
2488-
}
2489-
else if ( option instanceof LockMode lockMode ) {
2490-
access.with( lockMode );
2491-
}
2492-
else if ( option instanceof LockModeType lockModeType ) {
2493-
access.with( LockMode.fromJpaLockMode( lockModeType ) );
2494-
}
2495-
else if ( option instanceof Locking.Scope scope ) {
2496-
access.with( scope );
2497-
}
2498-
else if ( option instanceof PessimisticLockScope scope ) {
2499-
access.with( Locking.Scope.fromJpaScope( scope ) );
2500-
}
2501-
else if ( option instanceof Timeout timeout ) {
2502-
access.with( timeout );
2503-
}
2504-
else if ( option instanceof CacheMode cacheMode ) {
2505-
access.with( cacheMode );
2506-
}
2507-
else if ( option instanceof BatchSize batchSize ) {
2508-
access.withBatchSize( batchSize.batchSize() );
2509-
}
2510-
else if ( option instanceof RemovalsMode removalsMode ) {
2511-
access.with( removalsMode );
2512-
}
2513-
else if ( option instanceof OrderingMode orderingMode ) {
2514-
access.with( orderingMode );
2515-
}
2516-
else {
2517-
throw new IllegalArgumentException( "Illegal option: " + option );
2518-
}
2519-
}
2437+
private <T> FindByKeyOperation<T> byKey(EntityPersister entityDescriptor, FindOption... options) {
2438+
return byKey( entityDescriptor, null, null, options );
25202439
}
25212440

2522-
@Override
2523-
public List<Object> findMultipleByNaturalId(String entityName, List<?> naturalIds, FindOption... options) {
2524-
final NaturalIdMultiLoadAccessStandard<Object> access = (NaturalIdMultiLoadAccessStandard<Object>) byMultipleNaturalId( entityName );
2525-
setOptions( options, access );
2526-
return access.multiLoad( naturalIds );
2441+
private <T> FindByKeyOperation<T> byKey(
2442+
EntityPersister entityDescriptor,
2443+
GraphSemantic graphSemantic,
2444+
RootGraphImplementor<?> rootGraph,
2445+
FindOption... options) {
2446+
return new FindByKeyOperation<>(
2447+
entityDescriptor,
2448+
graphSemantic,
2449+
rootGraph,
2450+
lockOptions,
2451+
getCacheMode(),
2452+
isReadOnly(),
2453+
getFactory(),
2454+
options
2455+
);
25272456
}
25282457

25292458
@Override

0 commit comments

Comments
 (0)