Skip to content

Commit e9223cb

Browse files
committed
finally sort out handling of @id and @Version in query validator
also remove 'this' hacks made obsolete by Steve's work on core
1 parent d029547 commit e9223cb

File tree

14 files changed

+284
-57
lines changed

14 files changed

+284
-57
lines changed

hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/AbstractIdentifiableType.java

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -420,11 +420,10 @@ else if ( id != null ) {
420420
}
421421
else {
422422
assert type instanceof EmbeddableDomainType;
423-
final EmbeddableDomainType<?> compositeType = (EmbeddableDomainType<?>) type;
424423
return new EmbeddedSqmPathSource<>(
425424
EntityIdentifierMapping.ID_ROLE_NAME,
426425
(SqmPathSource) id,
427-
compositeType,
426+
(EmbeddableDomainType<?>) type,
428427
Bindable.BindableType.SINGULAR_ATTRIBUTE,
429428
id.isGeneric()
430429
);

hibernate-core/src/main/java/org/hibernate/query/hql/internal/SemanticQueryBuilder.java

Lines changed: 30 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -2971,17 +2971,23 @@ public SqmPath<?> visitEntityIdReference(HqlParser.EntityIdReferenceContext ctx)
29712971

29722972
final SqmPath<?> sqmPath = consumeDomainPath( ctx.path() );
29732973
final DomainType<?> sqmPathType = sqmPath.getReferencedPathSource().getSqmPathType();
2974-
29752974
if ( sqmPathType instanceof IdentifiableDomainType<?> ) {
2976-
final SqmPathSource<?> identifierDescriptor = ( (IdentifiableDomainType<?>) sqmPathType ).getIdentifierDescriptor();
2975+
final IdentifiableDomainType<?> identifiableType = (IdentifiableDomainType<?>) sqmPathType;
2976+
final SqmPathSource<?> identifierDescriptor = identifiableType.getIdentifierDescriptor();
2977+
if ( identifierDescriptor == null ) {
2978+
// mainly for benefit of Hibernate Processor
2979+
throw new FunctionArgumentException( "Argument '" + sqmPath.getNavigablePath()
2980+
+ "' of 'id()' is a '" + identifiableType.getTypeName()
2981+
+ "' and does not have a well-defined '@Id' attribute" );
2982+
}
29772983
return sqmPath.get( identifierDescriptor.getPathName() );
29782984
}
29792985
else if ( sqmPath instanceof SqmAnyValuedSimplePath<?> ) {
29802986
return sqmPath.resolvePathPart( AnyKeyPart.KEY_NAME, true, processingStateStack.getCurrent().getCreationState() );
29812987
}
29822988
else {
29832989
throw new FunctionArgumentException( "Argument '" + sqmPath.getNavigablePath()
2984-
+ "' of 'id()' function does not resolve to an entity type" );
2990+
+ "' of 'id()' does not resolve to an entity type" );
29852991
}
29862992
}
29872993

@@ -2994,26 +3000,22 @@ public SqmExpression<?> visitEntityVersionExpression(HqlParser.EntityVersionExpr
29943000
public SqmPath<?> visitEntityVersionReference(HqlParser.EntityVersionReferenceContext ctx) {
29953001
final SqmPath<?> sqmPath = consumeDomainPath( ctx.path() );
29963002
final DomainType<?> sqmPathType = sqmPath.getReferencedPathSource().getSqmPathType();
2997-
29983003
if ( sqmPathType instanceof IdentifiableDomainType<?> ) {
2999-
@SuppressWarnings("unchecked")
3000-
final IdentifiableDomainType<Object> identifiableType = (IdentifiableDomainType<Object>) sqmPathType;
3001-
final SingularPersistentAttribute<Object, ?> versionAttribute = identifiableType.findVersionAttribute();
3002-
if ( versionAttribute == null ) {
3003-
throw new FunctionArgumentException(
3004-
String.format(
3005-
"Argument '%s' of 'version()' function resolved to entity type '%s' which does not have a '@Version' attribute",
3006-
sqmPath.getNavigablePath(),
3007-
identifiableType.getTypeName()
3008-
)
3009-
);
3004+
final IdentifiableDomainType<?> identifiableType = (IdentifiableDomainType<?>) sqmPathType;
3005+
if ( !identifiableType.hasVersionAttribute() ) {
3006+
throw new FunctionArgumentException( "Argument '" + sqmPath.getNavigablePath()
3007+
+ "' of 'version()' is a '" + identifiableType.getTypeName()
3008+
+ "' and does not have a '@Version' attribute" );
30103009
}
3011-
3010+
@SuppressWarnings("unchecked")
3011+
final SingularPersistentAttribute<Object, ?> versionAttribute =
3012+
(SingularPersistentAttribute<Object, ?>) identifiableType.findVersionAttribute();
30123013
return sqmPath.get( versionAttribute );
30133014
}
3014-
3015-
throw new FunctionArgumentException( "Argument '" + sqmPath.getNavigablePath()
3016-
+ "' of 'version()' function does not resolve to an entity type" );
3015+
else {
3016+
throw new FunctionArgumentException( "Argument '" + sqmPath.getNavigablePath()
3017+
+ "' of 'version()' does not resolve to an entity type" );
3018+
}
30173019
}
30183020

30193021
@Override
@@ -3032,35 +3034,29 @@ public SqmPath<?> visitEntityNaturalIdReference(HqlParser.EntityNaturalIdReferen
30323034

30333035
if ( sqmPathType instanceof IdentifiableDomainType<?> ) {
30343036
@SuppressWarnings("unchecked")
3035-
final IdentifiableDomainType<Object> identifiableType = (IdentifiableDomainType<? super Object>) sqmPathType;
3037+
final IdentifiableDomainType<Object> identifiableType = (IdentifiableDomainType<Object>) sqmPathType;
30363038
final List<? extends PersistentAttribute<Object, ?>> attributes = identifiableType.findNaturalIdAttributes();
30373039
if ( attributes == null ) {
3038-
throw new FunctionArgumentException(
3039-
String.format(
3040-
"Argument '%s' of 'naturalid()' function resolved to entity type '%s' which does not have a natural id",
3041-
sqmPath.getNavigablePath(),
3042-
identifiableType.getTypeName()
3043-
)
3040+
throw new FunctionArgumentException( "Argument '" + sqmPath.getNavigablePath()
3041+
+ "' of 'naturalid()' is a '" + identifiableType.getTypeName()
3042+
+ "' and does not have a natural id"
30443043
);
30453044
}
30463045
else if ( attributes.size() >1 ) {
3047-
throw new FunctionArgumentException(
3048-
String.format(
3049-
"Argument '%s' of 'naturalid()' function resolved to entity type '%s' which has a composite natural id",
3050-
sqmPath.getNavigablePath(),
3051-
identifiableType.getTypeName()
3052-
)
3046+
throw new FunctionArgumentException( "Argument '" + sqmPath.getNavigablePath()
3047+
+ "' of 'naturalid()' is a '" + identifiableType.getTypeName()
3048+
+ "' and has a composite natural id"
30533049
);
30543050
}
30553051

30563052
@SuppressWarnings("unchecked")
3057-
SingularAttribute<Object, ?> naturalIdAttribute
3053+
final SingularAttribute<Object, ?> naturalIdAttribute
30583054
= (SingularAttribute<Object, ?>) attributes.get(0);
30593055
return sqmPath.get( naturalIdAttribute );
30603056
}
30613057

30623058
throw new FunctionArgumentException( "Argument '" + sqmPath.getNavigablePath()
3063-
+ "' of 'naturalid()' function does not resolve to an entity type" );
3059+
+ "' of 'naturalid()' does not resolve to an entity type" );
30643060
}
30653061
//
30663062
// @Override

tooling/metamodel-generator/src/jakartaData/java/org/hibernate/processor/test/data/basic/Concrete.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,5 +3,5 @@
33
import jakarta.data.repository.Repository;
44

55
@Repository
6-
public interface Concrete extends IdOperations<Book> {
6+
public interface Concrete extends IdOperations<Thing> {
77
}

tooling/metamodel-generator/src/jakartaData/java/org/hibernate/processor/test/data/basic/DataTest.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919
*/
2020
public class DataTest extends CompilationTest {
2121
@Test
22-
@WithClasses({ Author.class, Book.class, BookAuthorRepository.class, IdOperations.class, Concrete.class })
22+
@WithClasses({ Author.class, Book.class, BookAuthorRepository.class, IdOperations.class, Concrete.class, Thing.class })
2323
public void test() {
2424
System.out.println( getMetaModelSourceAsString( Author.class ) );
2525
System.out.println( getMetaModelSourceAsString( Book.class ) );

tooling/metamodel-generator/src/jakartaData/java/org/hibernate/processor/test/data/basic/IdOperations.java

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -23,11 +23,6 @@
2323
import jakarta.data.Sort;
2424
import jakarta.data.repository.Query;
2525

26-
/**
27-
* This interface contains common operations for the NaturalNumbers and AsciiCharacters repositories.
28-
*
29-
* @param <T> type of entity.
30-
*/
3126
public interface IdOperations<T> {
3227
@Query("where id(this) between ?1 and ?2")
3328
Stream<T> findByIdBetween(long minimum, long maximum, Sort<T> sort);
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
package org.hibernate.processor.test.data.basic;
2+
3+
import jakarta.persistence.Entity;
4+
import jakarta.persistence.Id;
5+
6+
@Entity
7+
public class Thing {
8+
@Id long id;
9+
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
package org.hibernate.processor.test.data.versioned;
2+
3+
import jakarta.persistence.Entity;
4+
5+
@Entity
6+
public class SpecialVersioned extends Versioned {
7+
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
package org.hibernate.processor.test.data.versioned;
2+
3+
import jakarta.data.repository.Query;
4+
import jakarta.data.repository.Repository;
5+
6+
@Repository
7+
public interface SpecialVersionedRepo {
8+
@Query("where id(this) = ?1")
9+
SpecialVersioned forId(long id);
10+
11+
@Query("where id(this) = ?1 and version(this) = ?2")
12+
SpecialVersioned forIdAndVersion(long id, int version);
13+
14+
@Query("select count(this) from SpecialVersioned")
15+
long count();
16+
17+
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
package org.hibernate.processor.test.data.versioned;
2+
3+
import jakarta.persistence.Entity;
4+
import jakarta.persistence.Id;
5+
import jakarta.persistence.Version;
6+
7+
@Entity
8+
public class Versioned {
9+
@Id long id;
10+
@Version int version;
11+
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
package org.hibernate.processor.test.data.versioned;
2+
3+
import jakarta.data.repository.Query;
4+
import jakarta.data.repository.Repository;
5+
6+
@Repository
7+
public interface VersionedRepo {
8+
@Query("where id(this) = ?1")
9+
Versioned forId(long id);
10+
11+
@Query("where id(this) = ?1 and version(this) = ?2")
12+
Versioned forIdAndVersion(long id, int version);
13+
14+
@Query("select count(this) from Versioned")
15+
long count();
16+
17+
}

0 commit comments

Comments
 (0)