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
d0295473b2
commit
e9223cb984
|
@ -420,11 +420,10 @@ public abstract class AbstractIdentifiableType<J>
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
assert type instanceof EmbeddableDomainType;
|
assert type instanceof EmbeddableDomainType;
|
||||||
final EmbeddableDomainType<?> compositeType = (EmbeddableDomainType<?>) type;
|
|
||||||
return new EmbeddedSqmPathSource<>(
|
return new EmbeddedSqmPathSource<>(
|
||||||
EntityIdentifierMapping.ID_ROLE_NAME,
|
EntityIdentifierMapping.ID_ROLE_NAME,
|
||||||
(SqmPathSource) id,
|
(SqmPathSource) id,
|
||||||
compositeType,
|
(EmbeddableDomainType<?>) type,
|
||||||
Bindable.BindableType.SINGULAR_ATTRIBUTE,
|
Bindable.BindableType.SINGULAR_ATTRIBUTE,
|
||||||
id.isGeneric()
|
id.isGeneric()
|
||||||
);
|
);
|
||||||
|
|
|
@ -2971,9 +2971,15 @@ public class SemanticQueryBuilder<R> extends HqlParserBaseVisitor<Object> implem
|
||||||
|
|
||||||
final SqmPath<?> sqmPath = consumeDomainPath( ctx.path() );
|
final SqmPath<?> sqmPath = consumeDomainPath( ctx.path() );
|
||||||
final DomainType<?> sqmPathType = sqmPath.getReferencedPathSource().getSqmPathType();
|
final DomainType<?> sqmPathType = sqmPath.getReferencedPathSource().getSqmPathType();
|
||||||
|
|
||||||
if ( sqmPathType instanceof IdentifiableDomainType<?> ) {
|
if ( sqmPathType instanceof IdentifiableDomainType<?> ) {
|
||||||
final SqmPathSource<?> identifierDescriptor = ( (IdentifiableDomainType<?>) sqmPathType ).getIdentifierDescriptor();
|
final IdentifiableDomainType<?> identifiableType = (IdentifiableDomainType<?>) sqmPathType;
|
||||||
|
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() );
|
return sqmPath.get( identifierDescriptor.getPathName() );
|
||||||
}
|
}
|
||||||
else if ( sqmPath instanceof SqmAnyValuedSimplePath<?> ) {
|
else if ( sqmPath instanceof SqmAnyValuedSimplePath<?> ) {
|
||||||
|
@ -2981,7 +2987,7 @@ public class SemanticQueryBuilder<R> extends HqlParserBaseVisitor<Object> implem
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
throw new FunctionArgumentException( "Argument '" + sqmPath.getNavigablePath()
|
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" );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2994,26 +3000,22 @@ public class SemanticQueryBuilder<R> extends HqlParserBaseVisitor<Object> implem
|
||||||
public SqmPath<?> visitEntityVersionReference(HqlParser.EntityVersionReferenceContext ctx) {
|
public SqmPath<?> visitEntityVersionReference(HqlParser.EntityVersionReferenceContext ctx) {
|
||||||
final SqmPath<?> sqmPath = consumeDomainPath( ctx.path() );
|
final SqmPath<?> sqmPath = consumeDomainPath( ctx.path() );
|
||||||
final DomainType<?> sqmPathType = sqmPath.getReferencedPathSource().getSqmPathType();
|
final DomainType<?> sqmPathType = sqmPath.getReferencedPathSource().getSqmPathType();
|
||||||
|
|
||||||
if ( sqmPathType instanceof IdentifiableDomainType<?> ) {
|
if ( sqmPathType instanceof IdentifiableDomainType<?> ) {
|
||||||
@SuppressWarnings("unchecked")
|
final IdentifiableDomainType<?> identifiableType = (IdentifiableDomainType<?>) sqmPathType;
|
||||||
final IdentifiableDomainType<Object> identifiableType = (IdentifiableDomainType<Object>) sqmPathType;
|
if ( !identifiableType.hasVersionAttribute() ) {
|
||||||
final SingularPersistentAttribute<Object, ?> versionAttribute = identifiableType.findVersionAttribute();
|
throw new FunctionArgumentException( "Argument '" + sqmPath.getNavigablePath()
|
||||||
if ( versionAttribute == null ) {
|
+ "' of 'version()' is a '" + identifiableType.getTypeName()
|
||||||
throw new FunctionArgumentException(
|
+ "' and does not have a '@Version' attribute" );
|
||||||
String.format(
|
|
||||||
"Argument '%s' of 'version()' function resolved to entity type '%s' which does not have a '@Version' attribute",
|
|
||||||
sqmPath.getNavigablePath(),
|
|
||||||
identifiableType.getTypeName()
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
final SingularPersistentAttribute<Object, ?> versionAttribute =
|
||||||
|
(SingularPersistentAttribute<Object, ?>) identifiableType.findVersionAttribute();
|
||||||
return sqmPath.get( versionAttribute );
|
return sqmPath.get( versionAttribute );
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
throw new FunctionArgumentException( "Argument '" + sqmPath.getNavigablePath()
|
throw new FunctionArgumentException( "Argument '" + sqmPath.getNavigablePath()
|
||||||
+ "' of 'version()' function does not resolve to an entity type" );
|
+ "' of 'version()' does not resolve to an entity type" );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -3032,35 +3034,29 @@ public class SemanticQueryBuilder<R> extends HqlParserBaseVisitor<Object> implem
|
||||||
|
|
||||||
if ( sqmPathType instanceof IdentifiableDomainType<?> ) {
|
if ( sqmPathType instanceof IdentifiableDomainType<?> ) {
|
||||||
@SuppressWarnings("unchecked")
|
@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();
|
final List<? extends PersistentAttribute<Object, ?>> attributes = identifiableType.findNaturalIdAttributes();
|
||||||
if ( attributes == null ) {
|
if ( attributes == null ) {
|
||||||
throw new FunctionArgumentException(
|
throw new FunctionArgumentException( "Argument '" + sqmPath.getNavigablePath()
|
||||||
String.format(
|
+ "' of 'naturalid()' is a '" + identifiableType.getTypeName()
|
||||||
"Argument '%s' of 'naturalid()' function resolved to entity type '%s' which does not have a natural id",
|
+ "' and does not have a natural id"
|
||||||
sqmPath.getNavigablePath(),
|
|
||||||
identifiableType.getTypeName()
|
|
||||||
)
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
else if ( attributes.size() >1 ) {
|
else if ( attributes.size() >1 ) {
|
||||||
throw new FunctionArgumentException(
|
throw new FunctionArgumentException( "Argument '" + sqmPath.getNavigablePath()
|
||||||
String.format(
|
+ "' of 'naturalid()' is a '" + identifiableType.getTypeName()
|
||||||
"Argument '%s' of 'naturalid()' function resolved to entity type '%s' which has a composite natural id",
|
+ "' and has a composite natural id"
|
||||||
sqmPath.getNavigablePath(),
|
|
||||||
identifiableType.getTypeName()
|
|
||||||
)
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
SingularAttribute<Object, ?> naturalIdAttribute
|
final SingularAttribute<Object, ?> naturalIdAttribute
|
||||||
= (SingularAttribute<Object, ?>) attributes.get(0);
|
= (SingularAttribute<Object, ?>) attributes.get(0);
|
||||||
return sqmPath.get( naturalIdAttribute );
|
return sqmPath.get( naturalIdAttribute );
|
||||||
}
|
}
|
||||||
|
|
||||||
throw new FunctionArgumentException( "Argument '" + sqmPath.getNavigablePath()
|
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
|
// @Override
|
||||||
|
|
|
@ -3,5 +3,5 @@ package org.hibernate.processor.test.data.basic;
|
||||||
import jakarta.data.repository.Repository;
|
import jakarta.data.repository.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 {
|
public class DataTest extends CompilationTest {
|
||||||
@Test
|
@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() {
|
public void test() {
|
||||||
System.out.println( getMetaModelSourceAsString( Author.class ) );
|
System.out.println( getMetaModelSourceAsString( Author.class ) );
|
||||||
System.out.println( getMetaModelSourceAsString( Book.class ) );
|
System.out.println( getMetaModelSourceAsString( Book.class ) );
|
||||||
|
|
|
@ -23,11 +23,6 @@ import jakarta.data.Order;
|
||||||
import jakarta.data.Sort;
|
import jakarta.data.Sort;
|
||||||
import jakarta.data.repository.Query;
|
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> {
|
public interface IdOperations<T> {
|
||||||
@Query("where id(this) between ?1 and ?2")
|
@Query("where id(this) between ?1 and ?2")
|
||||||
Stream<T> findByIdBetween(long minimum, long maximum, Sort<T> sort);
|
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 );
|
||||||
|
}
|
||||||
|
}
|
|
@ -13,6 +13,7 @@ import org.hibernate.persister.entity.DiscriminatorMetadata;
|
||||||
import org.hibernate.persister.entity.EntityPersister;
|
import org.hibernate.persister.entity.EntityPersister;
|
||||||
import org.hibernate.persister.entity.Queryable;
|
import org.hibernate.persister.entity.Queryable;
|
||||||
import org.hibernate.tuple.entity.EntityMetamodel;
|
import org.hibernate.tuple.entity.EntityMetamodel;
|
||||||
|
import org.hibernate.type.BasicType;
|
||||||
import org.hibernate.type.Type;
|
import org.hibernate.type.Type;
|
||||||
|
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
|
@ -115,18 +116,36 @@ public abstract class MockEntityPersister implements EntityPersister, Queryable,
|
||||||
|
|
||||||
abstract Type createPropertyType(String propertyPath);
|
abstract Type createPropertyType(String propertyPath);
|
||||||
|
|
||||||
@Override
|
/**
|
||||||
public Type getIdentifierType() {
|
* Override on subclasses!
|
||||||
//TODO: propertyType(getIdentifierPropertyName())
|
*/
|
||||||
return factory.getTypeConfiguration().getBasicTypeForJavaType(Long.class);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getIdentifierPropertyName() {
|
public String getIdentifierPropertyName() {
|
||||||
//TODO: return the correct @Id property name
|
return getRootEntityPersister().identifierPropertyName();
|
||||||
return "id";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected abstract String identifierPropertyName();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Override on subclasses!
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
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
|
@Override
|
||||||
public Type toType(String propertyName) throws QueryException {
|
public Type toType(String propertyName) throws QueryException {
|
||||||
Type type = getPropertyType(propertyName);
|
Type type = getPropertyType(propertyName);
|
||||||
|
@ -139,13 +158,10 @@ public abstract class MockEntityPersister implements EntityPersister, Queryable,
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getRootEntityName() {
|
public abstract String getRootEntityName();
|
||||||
for (MockEntityPersister persister : factory.getMockEntityPersisters()) {
|
|
||||||
if (this != persister && persister.isSubclassPersister(this)) {
|
public MockEntityPersister getRootEntityPersister() {
|
||||||
return persister.getRootEntityName();
|
return factory.createMockEntityPersister(getRootEntityName());
|
||||||
}
|
|
||||||
}
|
|
||||||
return entityName;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -217,7 +233,12 @@ public abstract class MockEntityPersister implements EntityPersister, Queryable,
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getVersionProperty() {
|
public int getVersionProperty() {
|
||||||
return -66;
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isVersioned() {
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
*/
|
*/
|
||||||
package org.hibernate.processor.validation;
|
package org.hibernate.processor.validation;
|
||||||
|
|
||||||
|
import jakarta.persistence.metamodel.Bindable;
|
||||||
import org.checkerframework.checker.nullness.qual.Nullable;
|
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||||
import org.hibernate.CustomEntityDirtinessStrategy;
|
import org.hibernate.CustomEntityDirtinessStrategy;
|
||||||
import org.hibernate.EntityNameResolver;
|
import org.hibernate.EntityNameResolver;
|
||||||
|
@ -57,16 +58,22 @@ import org.hibernate.metamodel.internal.JpaMetaModelPopulationSetting;
|
||||||
import org.hibernate.metamodel.internal.JpaStaticMetaModelPopulationSetting;
|
import org.hibernate.metamodel.internal.JpaStaticMetaModelPopulationSetting;
|
||||||
import org.hibernate.metamodel.internal.MetadataContext;
|
import org.hibernate.metamodel.internal.MetadataContext;
|
||||||
import org.hibernate.metamodel.internal.RuntimeMetamodelsImpl;
|
import org.hibernate.metamodel.internal.RuntimeMetamodelsImpl;
|
||||||
|
import org.hibernate.metamodel.mapping.EntityIdentifierMapping;
|
||||||
import org.hibernate.metamodel.mapping.JdbcMapping;
|
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.DomainType;
|
||||||
|
import org.hibernate.metamodel.model.domain.EmbeddableDomainType;
|
||||||
import org.hibernate.metamodel.model.domain.EntityDomainType;
|
import org.hibernate.metamodel.model.domain.EntityDomainType;
|
||||||
import org.hibernate.metamodel.model.domain.ManagedDomainType;
|
import org.hibernate.metamodel.model.domain.ManagedDomainType;
|
||||||
import org.hibernate.metamodel.model.domain.PersistentAttribute;
|
import org.hibernate.metamodel.model.domain.PersistentAttribute;
|
||||||
|
import org.hibernate.metamodel.model.domain.SingularPersistentAttribute;
|
||||||
import org.hibernate.metamodel.model.domain.internal.AbstractAttribute;
|
import org.hibernate.metamodel.model.domain.internal.AbstractAttribute;
|
||||||
import org.hibernate.metamodel.model.domain.internal.AbstractPluralAttribute;
|
import org.hibernate.metamodel.model.domain.internal.AbstractPluralAttribute;
|
||||||
import org.hibernate.metamodel.model.domain.internal.BagAttributeImpl;
|
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.BasicTypeImpl;
|
||||||
import org.hibernate.metamodel.model.domain.internal.EmbeddableTypeImpl;
|
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.EntityTypeImpl;
|
||||||
import org.hibernate.metamodel.model.domain.internal.JpaMetamodelImpl;
|
import org.hibernate.metamodel.model.domain.internal.JpaMetamodelImpl;
|
||||||
import org.hibernate.metamodel.model.domain.internal.ListAttributeImpl;
|
import org.hibernate.metamodel.model.domain.internal.ListAttributeImpl;
|
||||||
|
@ -102,6 +109,7 @@ import org.hibernate.query.sqm.sql.StandardSqmTranslatorFactory;
|
||||||
import org.hibernate.stat.internal.StatisticsImpl;
|
import org.hibernate.stat.internal.StatisticsImpl;
|
||||||
import org.hibernate.stat.spi.StatisticsImplementor;
|
import org.hibernate.stat.spi.StatisticsImplementor;
|
||||||
import org.hibernate.type.BagType;
|
import org.hibernate.type.BagType;
|
||||||
|
import org.hibernate.type.BasicType;
|
||||||
import org.hibernate.type.CollectionType;
|
import org.hibernate.type.CollectionType;
|
||||||
import org.hibernate.type.CompositeType;
|
import org.hibernate.type.CompositeType;
|
||||||
import org.hibernate.type.ListType;
|
import org.hibernate.type.ListType;
|
||||||
|
@ -336,6 +344,12 @@ public abstract class MockSessionFactory
|
||||||
.getIdentifierType();
|
.getIdentifierType();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public BasicType<?> getVersionType(String className)
|
||||||
|
throws MappingException {
|
||||||
|
return createEntityPersister(className)
|
||||||
|
.getVersionType();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getIdentifierPropertyName(String className)
|
public String getIdentifierPropertyName(String className)
|
||||||
throws MappingException {
|
throws MappingException {
|
||||||
|
@ -915,9 +929,73 @@ public abstract class MockSessionFactory
|
||||||
metamodel.getJpaMetamodel());
|
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
|
@Override
|
||||||
public SqmPathSource<?> findSubPathSource(String name, JpaMetamodelImplementor metamodel) {
|
public SqmPathSource<?> findSubPathSource(String name, JpaMetamodelImplementor 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 ) {
|
if ( source != null ) {
|
||||||
return source;
|
return source;
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,6 +10,7 @@ import jakarta.persistence.AccessType;
|
||||||
import org.checkerframework.checker.nullness.qual.Nullable;
|
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||||
import org.hibernate.PropertyNotFoundException;
|
import org.hibernate.PropertyNotFoundException;
|
||||||
import org.hibernate.engine.spi.Mapping;
|
import org.hibernate.engine.spi.Mapping;
|
||||||
|
import org.hibernate.metamodel.mapping.EntityIdentifierMapping;
|
||||||
import org.hibernate.type.BasicType;
|
import org.hibernate.type.BasicType;
|
||||||
import org.hibernate.type.CollectionType;
|
import org.hibernate.type.CollectionType;
|
||||||
import org.hibernate.type.CompositeType;
|
import org.hibernate.type.CompositeType;
|
||||||
|
@ -148,6 +149,7 @@ public abstract class ProcessorSessionFactory extends MockSessionFactory {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
Type propertyType(String typeName, String propertyPath) {
|
Type propertyType(String typeName, String propertyPath) {
|
||||||
TypeElement type = findClassByQualifiedName(typeName);
|
TypeElement type = findClassByQualifiedName(typeName);
|
||||||
|
@ -370,6 +372,21 @@ public abstract class ProcessorSessionFactory extends MockSessionFactory {
|
||||||
initSubclassPersisters();
|
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
|
@Override
|
||||||
boolean isSubclassPersister(MockEntityPersister entityPersister) {
|
boolean isSubclassPersister(MockEntityPersister entityPersister) {
|
||||||
EntityPersister persister = (EntityPersister) entityPersister;
|
EntityPersister persister = (EntityPersister) entityPersister;
|
||||||
|
@ -383,6 +400,35 @@ public abstract class ProcessorSessionFactory extends MockSessionFactory {
|
||||||
factory.propertyType(symbol, getEntityName(), propertyPath, defaultAccessType);
|
factory.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 factory.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<?>) factory.propertyType(element, getEntityName(), "{version}", defaultAccessType);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public abstract static class ToManyAssociationPersister extends MockCollectionPersister {
|
public abstract static class ToManyAssociationPersister extends MockCollectionPersister {
|
||||||
|
|
Loading…
Reference in New Issue