Skip to content

Commit 63883b8

Browse files
committed
HHH-16383 - NaturalIdClass
1 parent 16eaf9d commit 63883b8

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;
@@ -990,30 +991,45 @@ else if ( option instanceof RemovalsMode ) {
990991
}
991992

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

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

10191035
@Override
@@ -2330,28 +2346,22 @@ else if ( option instanceof FindMultipleOption findMultipleOption ) {
23302346

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

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

23572367
// Hibernate Reactive may need to use this
@@ -2414,115 +2424,34 @@ private void checkTransactionNeededForUpdateOperation() {
24142424
}
24152425

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

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

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

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

25282457
@Override

0 commit comments

Comments
 (0)