finally sort out handling of @Id and @Version in query validator
also remove 'this' hacks made obsolete by Steve's work on core
This commit is contained in:
parent
d6ab2fd110
commit
19d5895dd6
|
@ -423,11 +423,10 @@ public abstract class AbstractIdentifiableType<J>
|
|||
}
|
||||
else {
|
||||
assert type instanceof EmbeddableDomainType;
|
||||
final EmbeddableDomainType<?> compositeType = (EmbeddableDomainType<?>) type;
|
||||
return new EmbeddedSqmPathSource<>(
|
||||
EntityIdentifierMapping.ID_ROLE_NAME,
|
||||
(SqmPathSource) id,
|
||||
compositeType,
|
||||
(EmbeddableDomainType<?>) type,
|
||||
Bindable.BindableType.SINGULAR_ATTRIBUTE,
|
||||
id.isGeneric()
|
||||
);
|
||||
|
|
|
@ -2999,9 +2999,14 @@ public class SemanticQueryBuilder<R> extends HqlParserBaseVisitor<Object> implem
|
|||
|
||||
final SqmPath<?> sqmPath = consumeDomainPath( ctx.path() );
|
||||
final DomainType<?> sqmPathType = sqmPath.getReferencedPathSource().getSqmPathType();
|
||||
|
||||
if ( sqmPathType instanceof IdentifiableDomainType<?> ) {
|
||||
final SqmPathSource<?> identifierDescriptor = ( (IdentifiableDomainType<?>) sqmPathType ).getIdentifierDescriptor();
|
||||
if ( sqmPathType instanceof IdentifiableDomainType<?> identifiableType ) {
|
||||
final SqmPathSource<?> identifierDescriptor = identifiableType.getIdentifierDescriptor();
|
||||
if ( identifierDescriptor == null ) {
|
||||
// mainly for benefit of Hibernate Processor
|
||||
throw new FunctionArgumentException( "Argument '" + sqmPath.getNavigablePath()
|
||||
+ "' of 'id()' is a '" + identifiableType.getTypeName()
|
||||
+ "' and does not have a well-defined '@Id' attribute" );
|
||||
}
|
||||
return sqmPath.get( identifierDescriptor.getPathName() );
|
||||
}
|
||||
else if ( sqmPath instanceof SqmAnyValuedSimplePath<?> ) {
|
||||
|
@ -3009,7 +3014,7 @@ public class SemanticQueryBuilder<R> extends HqlParserBaseVisitor<Object> implem
|
|||
}
|
||||
else {
|
||||
throw new FunctionArgumentException( "Argument '" + sqmPath.getNavigablePath()
|
||||
+ "' of 'id()' function does not resolve to an entity type" );
|
||||
+ "' of 'id()' does not resolve to an entity type" );
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3022,26 +3027,21 @@ public class SemanticQueryBuilder<R> extends HqlParserBaseVisitor<Object> implem
|
|||
public SqmPath<?> visitEntityVersionReference(HqlParser.EntityVersionReferenceContext ctx) {
|
||||
final SqmPath<?> sqmPath = consumeDomainPath( ctx.path() );
|
||||
final DomainType<?> sqmPathType = sqmPath.getReferencedPathSource().getSqmPathType();
|
||||
|
||||
if ( sqmPathType instanceof IdentifiableDomainType<?> ) {
|
||||
@SuppressWarnings("unchecked")
|
||||
final IdentifiableDomainType<Object> identifiableType = (IdentifiableDomainType<Object>) sqmPathType;
|
||||
final SingularPersistentAttribute<Object, ?> versionAttribute = identifiableType.findVersionAttribute();
|
||||
if ( versionAttribute == null ) {
|
||||
throw new FunctionArgumentException(
|
||||
String.format(
|
||||
"Argument '%s' of 'version()' function resolved to entity type '%s' which does not have a '@Version' attribute",
|
||||
sqmPath.getNavigablePath(),
|
||||
identifiableType.getTypeName()
|
||||
)
|
||||
);
|
||||
if ( sqmPathType instanceof IdentifiableDomainType<?> identifiableType ) {
|
||||
if ( !identifiableType.hasVersionAttribute() ) {
|
||||
throw new FunctionArgumentException( "Argument '" + sqmPath.getNavigablePath()
|
||||
+ "' of 'version()' is a '" + identifiableType.getTypeName()
|
||||
+ "' and does not have a '@Version' attribute" );
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
final SingularPersistentAttribute<Object, ?> versionAttribute =
|
||||
(SingularPersistentAttribute<Object, ?>) identifiableType.findVersionAttribute();
|
||||
return sqmPath.get( versionAttribute );
|
||||
}
|
||||
|
||||
throw new FunctionArgumentException( "Argument '" + sqmPath.getNavigablePath()
|
||||
+ "' of 'version()' function does not resolve to an entity type" );
|
||||
else {
|
||||
throw new FunctionArgumentException( "Argument '" + sqmPath.getNavigablePath()
|
||||
+ "' of 'version()' does not resolve to an entity type" );
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -3060,35 +3060,29 @@ public class SemanticQueryBuilder<R> extends HqlParserBaseVisitor<Object> implem
|
|||
|
||||
if ( sqmPathType instanceof IdentifiableDomainType<?> ) {
|
||||
@SuppressWarnings("unchecked")
|
||||
final IdentifiableDomainType<Object> identifiableType = (IdentifiableDomainType<? super Object>) sqmPathType;
|
||||
final IdentifiableDomainType<Object> identifiableType = (IdentifiableDomainType<Object>) sqmPathType;
|
||||
final List<? extends PersistentAttribute<Object, ?>> attributes = identifiableType.findNaturalIdAttributes();
|
||||
if ( attributes == null ) {
|
||||
throw new FunctionArgumentException(
|
||||
String.format(
|
||||
"Argument '%s' of 'naturalid()' function resolved to entity type '%s' which does not have a natural id",
|
||||
sqmPath.getNavigablePath(),
|
||||
identifiableType.getTypeName()
|
||||
)
|
||||
throw new FunctionArgumentException( "Argument '" + sqmPath.getNavigablePath()
|
||||
+ "' of 'naturalid()' is a '" + identifiableType.getTypeName()
|
||||
+ "' and does not have a natural id"
|
||||
);
|
||||
}
|
||||
else if ( attributes.size() >1 ) {
|
||||
throw new FunctionArgumentException(
|
||||
String.format(
|
||||
"Argument '%s' of 'naturalid()' function resolved to entity type '%s' which has a composite natural id",
|
||||
sqmPath.getNavigablePath(),
|
||||
identifiableType.getTypeName()
|
||||
)
|
||||
throw new FunctionArgumentException( "Argument '" + sqmPath.getNavigablePath()
|
||||
+ "' of 'naturalid()' is a '" + identifiableType.getTypeName()
|
||||
+ "' and has a composite natural id"
|
||||
);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
SingularAttribute<Object, ?> naturalIdAttribute
|
||||
final SingularAttribute<Object, ?> naturalIdAttribute
|
||||
= (SingularAttribute<Object, ?>) attributes.get(0);
|
||||
return sqmPath.get( naturalIdAttribute );
|
||||
}
|
||||
|
||||
throw new FunctionArgumentException( "Argument '" + sqmPath.getNavigablePath()
|
||||
+ "' of 'naturalid()' function does not resolve to an entity type" );
|
||||
+ "' of 'naturalid()' does not resolve to an entity type" );
|
||||
}
|
||||
//
|
||||
// @Override
|
||||
|
|
|
@ -3,5 +3,5 @@ package org.hibernate.processor.test.data.basic;
|
|||
import jakarta.data.repository.Repository;
|
||||
|
||||
@Repository
|
||||
public interface Concrete extends IdOperations<Book> {
|
||||
public interface Concrete extends IdOperations<Thing> {
|
||||
}
|
||||
|
|
|
@ -19,7 +19,7 @@ import static org.hibernate.processor.test.util.TestUtil.getMetaModelSourceAsStr
|
|||
*/
|
||||
public class DataTest extends CompilationTest {
|
||||
@Test
|
||||
@WithClasses({ Author.class, Book.class, BookAuthorRepository.class, IdOperations.class, Concrete.class })
|
||||
@WithClasses({ Author.class, Book.class, BookAuthorRepository.class, IdOperations.class, Concrete.class, Thing.class })
|
||||
public void test() {
|
||||
System.out.println( getMetaModelSourceAsString( Author.class ) );
|
||||
System.out.println( getMetaModelSourceAsString( Book.class ) );
|
||||
|
|
|
@ -23,11 +23,6 @@ import jakarta.data.Order;
|
|||
import jakarta.data.Sort;
|
||||
import jakarta.data.repository.Query;
|
||||
|
||||
/**
|
||||
* This interface contains common operations for the NaturalNumbers and AsciiCharacters repositories.
|
||||
*
|
||||
* @param <T> type of entity.
|
||||
*/
|
||||
public interface IdOperations<T> {
|
||||
@Query("where id(this) between ?1 and ?2")
|
||||
Stream<T> findByIdBetween(long minimum, long maximum, Sort<T> sort);
|
||||
|
|
|
@ -0,0 +1,9 @@
|
|||
package org.hibernate.processor.test.data.basic;
|
||||
|
||||
import jakarta.persistence.Entity;
|
||||
import jakarta.persistence.Id;
|
||||
|
||||
@Entity
|
||||
public class Thing {
|
||||
@Id long id;
|
||||
}
|
|
@ -0,0 +1,7 @@
|
|||
package org.hibernate.processor.test.data.versioned;
|
||||
|
||||
import jakarta.persistence.Entity;
|
||||
|
||||
@Entity
|
||||
public class SpecialVersioned extends Versioned {
|
||||
}
|
|
@ -0,0 +1,17 @@
|
|||
package org.hibernate.processor.test.data.versioned;
|
||||
|
||||
import jakarta.data.repository.Query;
|
||||
import jakarta.data.repository.Repository;
|
||||
|
||||
@Repository
|
||||
public interface SpecialVersionedRepo {
|
||||
@Query("where id(this) = ?1")
|
||||
SpecialVersioned forId(long id);
|
||||
|
||||
@Query("where id(this) = ?1 and version(this) = ?2")
|
||||
SpecialVersioned forIdAndVersion(long id, int version);
|
||||
|
||||
@Query("select count(this) from SpecialVersioned")
|
||||
long count();
|
||||
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
package org.hibernate.processor.test.data.versioned;
|
||||
|
||||
import jakarta.persistence.Entity;
|
||||
import jakarta.persistence.Id;
|
||||
import jakarta.persistence.Version;
|
||||
|
||||
@Entity
|
||||
public class Versioned {
|
||||
@Id long id;
|
||||
@Version int version;
|
||||
}
|
|
@ -0,0 +1,17 @@
|
|||
package org.hibernate.processor.test.data.versioned;
|
||||
|
||||
import jakarta.data.repository.Query;
|
||||
import jakarta.data.repository.Repository;
|
||||
|
||||
@Repository
|
||||
public interface VersionedRepo {
|
||||
@Query("where id(this) = ?1")
|
||||
Versioned forId(long id);
|
||||
|
||||
@Query("where id(this) = ?1 and version(this) = ?2")
|
||||
Versioned forIdAndVersion(long id, int version);
|
||||
|
||||
@Query("select count(this) from Versioned")
|
||||
long count();
|
||||
|
||||
}
|
|
@ -0,0 +1,31 @@
|
|||
/*
|
||||
* 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 <http://www.gnu.org/licenses/lgpl-2.1.html>.
|
||||
*/
|
||||
package org.hibernate.processor.test.data.versioned;
|
||||
|
||||
import org.hibernate.processor.test.util.CompilationTest;
|
||||
import org.hibernate.processor.test.util.WithClasses;
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.hibernate.processor.test.util.TestUtil.assertMetamodelClassGeneratedFor;
|
||||
import static org.hibernate.processor.test.util.TestUtil.getMetaModelSourceAsString;
|
||||
|
||||
/**
|
||||
* @author Gavin King
|
||||
*/
|
||||
public class VersionedTest extends CompilationTest {
|
||||
@Test
|
||||
@WithClasses({ Versioned.class, VersionedRepo.class, SpecialVersioned.class, SpecialVersionedRepo.class })
|
||||
public void test() {
|
||||
System.out.println( getMetaModelSourceAsString( VersionedRepo.class ) );
|
||||
assertMetamodelClassGeneratedFor( Versioned.class, true );
|
||||
assertMetamodelClassGeneratedFor( Versioned.class );
|
||||
assertMetamodelClassGeneratedFor( SpecialVersioned.class, true );
|
||||
assertMetamodelClassGeneratedFor( SpecialVersioned.class );
|
||||
assertMetamodelClassGeneratedFor( VersionedRepo.class );
|
||||
assertMetamodelClassGeneratedFor( SpecialVersionedRepo.class );
|
||||
}
|
||||
}
|
|
@ -71,11 +71,9 @@ import static java.util.Collections.emptyList;
|
|||
import static java.util.stream.Collectors.toList;
|
||||
import static javax.lang.model.util.ElementFilter.fieldsIn;
|
||||
import static javax.lang.model.util.ElementFilter.methodsIn;
|
||||
import static org.hibernate.grammars.hql.HqlLexer.AS;
|
||||
import static org.hibernate.grammars.hql.HqlLexer.FROM;
|
||||
import static org.hibernate.grammars.hql.HqlLexer.GROUP;
|
||||
import static org.hibernate.grammars.hql.HqlLexer.HAVING;
|
||||
import static org.hibernate.grammars.hql.HqlLexer.IDENTIFIER;
|
||||
import static org.hibernate.grammars.hql.HqlLexer.ORDER;
|
||||
import static org.hibernate.grammars.hql.HqlLexer.WHERE;
|
||||
import static org.hibernate.internal.util.StringHelper.qualify;
|
||||
|
@ -2408,47 +2406,22 @@ public class AnnotationMetaEntity extends AnnotationMeta {
|
|||
}
|
||||
else {
|
||||
final HqlLexer hqlLexer = HqlParseTreeBuilder.INSTANCE.buildHqlLexer( hql );
|
||||
String thisText = "";
|
||||
final List<? extends Token> allTokens = hqlLexer.getAllTokens();
|
||||
for (Token token : allTokens) {
|
||||
if ( token.getType() == IDENTIFIER ) {
|
||||
//TEMPORARY until HQL gets support for 'this'
|
||||
final String text = token.getText();
|
||||
if ( text.equalsIgnoreCase("this") ) {
|
||||
thisText = " as " + text;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
for (int i = 0; i < allTokens.size(); i++) {
|
||||
final Token token = allTokens.get(i);
|
||||
switch ( token.getType() ) {
|
||||
case FROM:
|
||||
return thisText.isEmpty() || hasAlias(i, allTokens) ? hql
|
||||
: new StringBuilder(hql)
|
||||
.insert(allTokens.get(i+1).getStopIndex() + 1, thisText)
|
||||
.toString();
|
||||
return hql;
|
||||
case WHERE:
|
||||
case HAVING:
|
||||
case GROUP:
|
||||
case ORDER:
|
||||
return new StringBuilder(hql)
|
||||
.insert(token.getStartIndex(), "from " + entityType + thisText + " ")
|
||||
.insert(token.getStartIndex(), "from " + entityType + " ")
|
||||
.toString();
|
||||
}
|
||||
}
|
||||
return hql + " from " + entityType + thisText;
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean hasAlias(int i, List<? extends Token> allTokens) {
|
||||
if ( allTokens.size() <= i+2 ) {
|
||||
return false;
|
||||
}
|
||||
else {
|
||||
final int nextTokenType = allTokens.get(i+2).getType();
|
||||
return nextTokenType == IDENTIFIER
|
||||
|| nextTokenType == AS;
|
||||
return hql + " from " + entityType;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -12,6 +12,7 @@ import org.hibernate.persister.entity.DiscriminatorMetadata;
|
|||
import org.hibernate.persister.entity.EntityPersister;
|
||||
import org.hibernate.persister.entity.Joinable;
|
||||
import org.hibernate.tuple.entity.EntityMetamodel;
|
||||
import org.hibernate.type.BasicType;
|
||||
import org.hibernate.type.Type;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
@ -113,27 +114,41 @@ public abstract class MockEntityPersister implements EntityPersister, Joinable,
|
|||
|
||||
abstract Type createPropertyType(String propertyPath);
|
||||
|
||||
@Override
|
||||
public Type getIdentifierType() {
|
||||
//TODO: propertyType(getIdentifierPropertyName())
|
||||
return typeConfiguration.getBasicTypeForJavaType(Long.class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Override on subclasses!
|
||||
*/
|
||||
@Override
|
||||
public String getIdentifierPropertyName() {
|
||||
//TODO: return the correct @Id property name
|
||||
return "id";
|
||||
return getRootEntityPersister().identifierPropertyName();
|
||||
}
|
||||
|
||||
protected abstract String identifierPropertyName();
|
||||
|
||||
/**
|
||||
* Override on subclasses!
|
||||
*/
|
||||
@Override
|
||||
public String getRootEntityName() {
|
||||
for (MockEntityPersister persister : factory.getMockEntityPersisters()) {
|
||||
if (this != persister && !persister.isSamePersister(this)
|
||||
&& persister.isSubclassPersister(this)) {
|
||||
return persister.getRootEntityName();
|
||||
}
|
||||
}
|
||||
return entityName;
|
||||
public Type getIdentifierType() {
|
||||
return getRootEntityPersister().identifierType();
|
||||
}
|
||||
|
||||
protected abstract Type identifierType();
|
||||
|
||||
/**
|
||||
* Override on subclasses!
|
||||
*/
|
||||
@Override
|
||||
public BasicType<?> getVersionType() {
|
||||
return getRootEntityPersister().versionType();
|
||||
}
|
||||
|
||||
protected abstract BasicType<?> versionType();
|
||||
|
||||
@Override
|
||||
public abstract String getRootEntityName();
|
||||
|
||||
public MockEntityPersister getRootEntityPersister() {
|
||||
return factory.createMockEntityPersister(getRootEntityName());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -195,7 +210,12 @@ public abstract class MockEntityPersister implements EntityPersister, Joinable,
|
|||
|
||||
@Override
|
||||
public int getVersionProperty() {
|
||||
return -66;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isVersioned() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
*/
|
||||
package org.hibernate.processor.validation;
|
||||
|
||||
import jakarta.persistence.metamodel.Bindable;
|
||||
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||
import org.hibernate.CustomEntityDirtinessStrategy;
|
||||
import org.hibernate.EntityNameResolver;
|
||||
|
@ -56,17 +57,24 @@ import org.hibernate.metamodel.internal.JpaMetaModelPopulationSetting;
|
|||
import org.hibernate.metamodel.internal.JpaStaticMetaModelPopulationSetting;
|
||||
import org.hibernate.metamodel.internal.MetadataContext;
|
||||
import org.hibernate.metamodel.internal.RuntimeMetamodelsImpl;
|
||||
import org.hibernate.metamodel.mapping.EntityIdentifierMapping;
|
||||
import org.hibernate.metamodel.mapping.JdbcMapping;
|
||||
import org.hibernate.metamodel.model.domain.BasicDomainType;
|
||||
import org.hibernate.metamodel.model.domain.DomainType;
|
||||
import org.hibernate.metamodel.model.domain.EmbeddableDomainType;
|
||||
import org.hibernate.metamodel.model.domain.EntityDomainType;
|
||||
import org.hibernate.metamodel.model.domain.JpaMetamodel;
|
||||
import org.hibernate.metamodel.model.domain.ManagedDomainType;
|
||||
import org.hibernate.metamodel.model.domain.PersistentAttribute;
|
||||
import org.hibernate.metamodel.model.domain.SimpleDomainType;
|
||||
import org.hibernate.metamodel.model.domain.SingularPersistentAttribute;
|
||||
import org.hibernate.metamodel.model.domain.internal.AbstractAttribute;
|
||||
import org.hibernate.metamodel.model.domain.internal.AbstractPluralAttribute;
|
||||
import org.hibernate.metamodel.model.domain.internal.BagAttributeImpl;
|
||||
import org.hibernate.metamodel.model.domain.internal.BasicSqmPathSource;
|
||||
import org.hibernate.metamodel.model.domain.internal.BasicTypeImpl;
|
||||
import org.hibernate.metamodel.model.domain.internal.EmbeddableTypeImpl;
|
||||
import org.hibernate.metamodel.model.domain.internal.EmbeddedSqmPathSource;
|
||||
import org.hibernate.metamodel.model.domain.internal.EntityTypeImpl;
|
||||
import org.hibernate.metamodel.model.domain.internal.JpaMetamodelImpl;
|
||||
import org.hibernate.metamodel.model.domain.internal.ListAttributeImpl;
|
||||
|
@ -101,6 +109,7 @@ import org.hibernate.query.sqm.sql.StandardSqmTranslatorFactory;
|
|||
import org.hibernate.stat.internal.StatisticsImpl;
|
||||
import org.hibernate.stat.spi.StatisticsImplementor;
|
||||
import org.hibernate.type.BagType;
|
||||
import org.hibernate.type.BasicType;
|
||||
import org.hibernate.type.CollectionType;
|
||||
import org.hibernate.type.CompositeType;
|
||||
import org.hibernate.type.ListType;
|
||||
|
@ -341,6 +350,12 @@ public abstract class MockSessionFactory
|
|||
.getIdentifierType();
|
||||
}
|
||||
|
||||
public BasicType<?> getVersionType(String className)
|
||||
throws MappingException {
|
||||
return createEntityPersister(className)
|
||||
.getVersionType();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getIdentifierPropertyName(String className)
|
||||
throws MappingException {
|
||||
|
@ -915,9 +930,73 @@ public abstract class MockSessionFactory
|
|||
metamodel.getJpaMetamodel());
|
||||
}
|
||||
|
||||
@Override
|
||||
public SingularPersistentAttribute<? super X, ?> findVersionAttribute() {
|
||||
final BasicType<?> type = getVersionType(getHibernateEntityName());
|
||||
if (type == null) {
|
||||
return null;
|
||||
}
|
||||
else {
|
||||
return new SingularAttributeImpl<>(
|
||||
MockEntityDomainType.this,
|
||||
"{version}",
|
||||
AttributeClassification.BASIC,
|
||||
type,
|
||||
type.getRelationalJavaType(),
|
||||
null,
|
||||
false,
|
||||
true,
|
||||
false,
|
||||
false,
|
||||
metadataContext
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasVersionAttribute() {
|
||||
return getVersionType(getHibernateEntityName()) != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SqmPathSource<?> getIdentifierDescriptor() {
|
||||
final Type type = getIdentifierType(getHibernateEntityName());
|
||||
if (type == null) {
|
||||
return null;
|
||||
}
|
||||
else if (type instanceof BasicDomainType) {
|
||||
return new BasicSqmPathSource<>(
|
||||
EntityIdentifierMapping.ID_ROLE_NAME,
|
||||
null,
|
||||
(BasicDomainType<?>) type,
|
||||
MockEntityDomainType.this.getExpressibleJavaType(),
|
||||
Bindable.BindableType.SINGULAR_ATTRIBUTE,
|
||||
false
|
||||
);
|
||||
}
|
||||
else if (type instanceof EmbeddableDomainType) {
|
||||
return new EmbeddedSqmPathSource<>(
|
||||
EntityIdentifierMapping.ID_ROLE_NAME,
|
||||
null,
|
||||
(EmbeddableDomainType<?>) type,
|
||||
Bindable.BindableType.SINGULAR_ATTRIBUTE,
|
||||
false
|
||||
);
|
||||
}
|
||||
else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public SqmPathSource<?> findSubPathSource(String name, JpaMetamodel metamodel) {
|
||||
SqmPathSource<?> source = super.findSubPathSource(name, metamodel);
|
||||
switch (name) {
|
||||
case EntityIdentifierMapping.ID_ROLE_NAME:
|
||||
return getIdentifierDescriptor();
|
||||
case "{version}":
|
||||
return findVersionAttribute();
|
||||
}
|
||||
final SqmPathSource<?> source = super.findSubPathSource(name, metamodel);
|
||||
if ( source != null ) {
|
||||
return source;
|
||||
}
|
||||
|
|
|
@ -10,6 +10,7 @@ import jakarta.persistence.AccessType;
|
|||
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||
import org.hibernate.PropertyNotFoundException;
|
||||
import org.hibernate.engine.spi.Mapping;
|
||||
import org.hibernate.metamodel.mapping.EntityIdentifierMapping;
|
||||
import org.hibernate.type.BasicType;
|
||||
import org.hibernate.type.CollectionType;
|
||||
import org.hibernate.type.CompositeType;
|
||||
|
@ -148,6 +149,7 @@ public abstract class ProcessorSessionFactory extends MockSessionFactory {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
Type propertyType(String typeName, String propertyPath) {
|
||||
TypeElement type = findClassByQualifiedName(typeName);
|
||||
|
@ -366,6 +368,21 @@ public abstract class ProcessorSessionFactory extends MockSessionFactory {
|
|||
initSubclassPersisters();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getRootEntityName() {
|
||||
TypeElement result = type;
|
||||
TypeMirror superclass = type.getSuperclass();
|
||||
while ( superclass!=null && superclass.getKind() == TypeKind.DECLARED ) {
|
||||
final DeclaredType declaredType = (DeclaredType) superclass;
|
||||
final TypeElement typeElement = (TypeElement) declaredType.asElement();
|
||||
if ( hasAnnotation(typeElement, "Entity") ) {
|
||||
result = typeElement;
|
||||
}
|
||||
superclass = typeElement.getSuperclass();
|
||||
}
|
||||
return ProcessorSessionFactory.getEntityName(result);
|
||||
}
|
||||
|
||||
@Override
|
||||
boolean isSamePersister(MockEntityPersister entityPersister) {
|
||||
EntityPersister persister = (EntityPersister) entityPersister;
|
||||
|
@ -385,6 +402,35 @@ public abstract class ProcessorSessionFactory extends MockSessionFactory {
|
|||
propertyType(symbol, getEntityName(), propertyPath, defaultAccessType);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String identifierPropertyName() {
|
||||
for (Element element : type.getEnclosedElements()) {
|
||||
if ( hasAnnotation(element, "Id") || hasAnnotation(element, "EmbeddedId") ) {
|
||||
return element.getSimpleName().toString();
|
||||
}
|
||||
}
|
||||
return "id";
|
||||
}
|
||||
|
||||
@Override
|
||||
public Type identifierType() {
|
||||
for (Element element : type.getEnclosedElements()) {
|
||||
if ( hasAnnotation(element, "Id")|| hasAnnotation(element, "EmbeddedId") ) {
|
||||
return propertyType(element, getEntityName(), EntityIdentifierMapping.ID_ROLE_NAME, defaultAccessType);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BasicType<?> versionType() {
|
||||
for (Element element : type.getEnclosedElements()) {
|
||||
if ( hasAnnotation(element, "Version") ) {
|
||||
return (BasicType<?>) propertyType(element, getEntityName(), "{version}", defaultAccessType);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public abstract static class ToManyAssociationPersister extends MockCollectionPersister {
|
||||
|
|
Loading…
Reference in New Issue