rough implementation of naturalid() function in HQL
and add tests for id(), version(), naturalid()
This commit is contained in:
parent
80b5c1e085
commit
5a0537aa04
|
@ -288,7 +288,12 @@ public class MetadataContext {
|
|||
);
|
||||
if ( attribute != null ) {
|
||||
( (AttributeContainer<Object>) jpaMapping ).getInFlightAccess().addAttribute( attribute );
|
||||
if ( property.isNaturalIdentifier() ) {
|
||||
( ( AttributeContainer<Object>) jpaMapping ).getInFlightAccess()
|
||||
.applyNaturalIdAttribute( attribute );
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
( (AttributeContainer<?>) jpaMapping ).getInFlightAccess().finishUp();
|
||||
|
@ -313,6 +318,7 @@ public class MetadataContext {
|
|||
|
||||
applyIdMetadata( safeMapping, jpaType );
|
||||
applyVersionAttribute( safeMapping, jpaType );
|
||||
// applyNaturalIdAttribute( safeMapping, jpaType );
|
||||
|
||||
Iterator<Property> properties = safeMapping.getDeclaredPropertyIterator();
|
||||
while ( properties.hasNext() ) {
|
||||
|
@ -324,6 +330,10 @@ public class MetadataContext {
|
|||
final PersistentAttribute<Object, ?> attribute = attributeFactory.buildAttribute( jpaType, property );
|
||||
if ( attribute != null ) {
|
||||
( (AttributeContainer<Object>) jpaType ).getInFlightAccess().addAttribute( attribute );
|
||||
if ( property.isNaturalIdentifier() ) {
|
||||
( ( AttributeContainer<Object>) jpaType ).getInFlightAccess()
|
||||
.applyNaturalIdAttribute( attribute );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -7,8 +7,10 @@
|
|||
package org.hibernate.metamodel.model.domain;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.function.Consumer;
|
||||
import jakarta.persistence.metamodel.Bindable;
|
||||
|
@ -53,6 +55,7 @@ public abstract class AbstractIdentifiableType<J>
|
|||
|
||||
private final boolean isVersioned;
|
||||
private SingularPersistentAttribute<J, ?> versionAttribute;
|
||||
private List<PersistentAttribute<J,?>> naturalIdAttributes;
|
||||
|
||||
public AbstractIdentifiableType(
|
||||
String typeName,
|
||||
|
@ -250,7 +253,7 @@ public abstract class AbstractIdentifiableType<J>
|
|||
return null;
|
||||
}
|
||||
|
||||
SingularPersistentAttribute<J, ?> version = findVersionAttribute();
|
||||
SingularPersistentAttribute<? super J, ?> version = findVersionAttribute();
|
||||
if ( version != null ) {
|
||||
checkType( version, javaType );
|
||||
}
|
||||
|
@ -258,14 +261,26 @@ public abstract class AbstractIdentifiableType<J>
|
|||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public SingularPersistentAttribute<J, ?> findVersionAttribute() {
|
||||
public SingularPersistentAttribute<? super J, ?> findVersionAttribute() {
|
||||
if ( versionAttribute != null ) {
|
||||
return versionAttribute;
|
||||
}
|
||||
|
||||
if ( getSuperType() != null ) {
|
||||
return (SingularPersistentAttribute<J, ?>) getSuperType().findVersionAttribute();
|
||||
return getSuperType().findVersionAttribute();
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<? extends PersistentAttribute<? super J, ?>> findNaturalIdAttributes() {
|
||||
if ( naturalIdAttributes != null ) {
|
||||
return naturalIdAttributes;
|
||||
}
|
||||
|
||||
if ( getSuperType() != null ) {
|
||||
return getSuperType().findNaturalIdAttributes();
|
||||
}
|
||||
|
||||
return null;
|
||||
|
@ -362,6 +377,14 @@ public abstract class AbstractIdentifiableType<J>
|
|||
managedTypeAccess.addAttribute( versionAttribute );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void applyNaturalIdAttribute(PersistentAttribute<J, ?> naturalIdAttribute) {
|
||||
if ( AbstractIdentifiableType.this.naturalIdAttributes == null ) {
|
||||
AbstractIdentifiableType.this.naturalIdAttributes = new ArrayList<>();
|
||||
}
|
||||
AbstractIdentifiableType.this.naturalIdAttributes.add( naturalIdAttribute );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addAttribute(PersistentAttribute<J, ?> attribute) {
|
||||
managedTypeAccess.addAttribute( attribute );
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
*/
|
||||
package org.hibernate.metamodel.model.domain;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.function.Consumer;
|
||||
import jakarta.persistence.metamodel.IdentifiableType;
|
||||
|
@ -49,4 +50,6 @@ public interface IdentifiableDomainType<J> extends ManagedDomainType<J>, Identif
|
|||
void visitIdClassAttributes(Consumer<SingularPersistentAttribute<? super J,?>> action);
|
||||
|
||||
SingularPersistentAttribute<? super J, ?> findVersionAttribute();
|
||||
|
||||
List<? extends PersistentAttribute<? super J, ?>> findNaturalIdAttributes();
|
||||
}
|
||||
|
|
|
@ -60,6 +60,11 @@ public interface AttributeContainer<J> {
|
|||
);
|
||||
}
|
||||
|
||||
default void applyNaturalIdAttribute(PersistentAttribute<J, ?> versionAttribute) {
|
||||
throw new UnsupportedMappingException(
|
||||
"AttributeContainer [" + getClass().getName() + "] does not support natural ids"
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when configuration of the type is complete
|
||||
|
|
|
@ -33,6 +33,7 @@ import java.util.Map;
|
|||
import java.util.Set;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import jakarta.persistence.metamodel.SingularAttribute;
|
||||
import org.hibernate.NotYetImplementedFor6Exception;
|
||||
import org.hibernate.QueryException;
|
||||
import org.hibernate.boot.registry.classloading.spi.ClassLoaderService;
|
||||
|
@ -52,6 +53,7 @@ import org.hibernate.metamodel.model.domain.DomainType;
|
|||
import org.hibernate.metamodel.model.domain.EntityDomainType;
|
||||
import org.hibernate.metamodel.model.domain.IdentifiableDomainType;
|
||||
import org.hibernate.metamodel.model.domain.ManagedDomainType;
|
||||
import org.hibernate.metamodel.model.domain.PersistentAttribute;
|
||||
import org.hibernate.metamodel.model.domain.PluralPersistentAttribute;
|
||||
import org.hibernate.metamodel.model.domain.SingularPersistentAttribute;
|
||||
import org.hibernate.query.BinaryArithmeticOperator;
|
||||
|
@ -2175,7 +2177,33 @@ public class SemanticQueryBuilder<R> extends HqlParserBaseVisitor<Object> implem
|
|||
|
||||
@Override
|
||||
public SqmPath<?> visitEntityNaturalIdReference(HqlParser.EntityNaturalIdReferenceContext ctx) {
|
||||
throw new NotYetImplementedFor6Exception( "Support for HQL natural-id references not yet implemented" );
|
||||
final SqmPath<Object> sqmPath = consumeDomainPath( (HqlParser.PathContext) ctx.getChild( 2 ) );
|
||||
final DomainType<?> sqmPathType = sqmPath.getReferencedPathSource().getSqmPathType();
|
||||
|
||||
if ( sqmPathType instanceof IdentifiableDomainType<?> ) {
|
||||
@SuppressWarnings("unchecked")
|
||||
final IdentifiableDomainType<Object> identifiableType = (IdentifiableDomainType<? super Object>) sqmPathType;
|
||||
final List<? extends PersistentAttribute<Object, ?>> attributes = identifiableType.findNaturalIdAttributes();
|
||||
if ( attributes == null ) {
|
||||
throw new SemanticException(
|
||||
"`" + sqmPath.getNavigablePath().getFullPath() + "` resolved to an identifiable-type (`" +
|
||||
identifiableType.getTypeName() + "`) which does not define a natural id"
|
||||
);
|
||||
}
|
||||
else if ( attributes.size() >1 ) {
|
||||
throw new SemanticException(
|
||||
"`" + sqmPath.getNavigablePath().getFullPath() + "` resolved to an identifiable-type (`" +
|
||||
identifiableType.getTypeName() + "`) which defines multiple natural ids"
|
||||
);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
SingularAttribute<Object, ?> naturalIdAttribute
|
||||
= (SingularAttribute<Object, ?>) attributes.get(0);
|
||||
return sqmPath.get( naturalIdAttribute );
|
||||
}
|
||||
|
||||
throw new SemanticException( "Path does not reference an identifiable-type : " + sqmPath.getNavigablePath().getFullPath() );
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -467,6 +467,11 @@ public class SqmPolymorphicRootDescriptor<T> implements EntityDomainType<T> {
|
|||
throw new UnsupportedOperationException( );
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<? extends SingularPersistentAttribute<? super T, ?>> findNaturalIdAttributes() {
|
||||
throw new UnsupportedOperationException( );
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasSingleIdAttribute() {
|
||||
throw new UnsupportedOperationException( );
|
||||
|
|
|
@ -60,6 +60,20 @@ public class FunctionTests {
|
|||
);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIdVersionFunctions(SessionFactoryScope scope) {
|
||||
scope.inTransaction(
|
||||
session -> {
|
||||
session.createQuery("select id(w) from VersionedEntity w")
|
||||
.list();
|
||||
session.createQuery("select version(w) from VersionedEntity w")
|
||||
.list();
|
||||
session.createQuery("select naturalid(w) from VersionedEntity w")
|
||||
.list();
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
@Test
|
||||
@RequiresDialectFeature(feature = DialectFeatureChecks.SupportsCharCodeConversion.class)
|
||||
public void testAsciiChrFunctions(SessionFactoryScope scope) {
|
||||
|
|
|
@ -17,6 +17,7 @@ public class GambitDomainModel extends AbstractDomainModelDescriptor {
|
|||
public GambitDomainModel() {
|
||||
super(
|
||||
BasicEntity.class,
|
||||
VersionedEntity.class,
|
||||
Component.class,
|
||||
EmbeddedIdEntity.class,
|
||||
EntityOfArrays.class,
|
||||
|
|
|
@ -0,0 +1,71 @@
|
|||
/*
|
||||
* 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.testing.orm.domain.gambit;
|
||||
|
||||
import jakarta.persistence.Entity;
|
||||
import jakarta.persistence.Id;
|
||||
import jakarta.persistence.Version;
|
||||
import org.hibernate.annotations.NaturalId;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* @author Chris Cranford
|
||||
*/
|
||||
@Entity
|
||||
public class VersionedEntity {
|
||||
@Id
|
||||
private Integer id;
|
||||
@Version
|
||||
private Integer version;
|
||||
@NaturalId
|
||||
private String code;
|
||||
private String data;
|
||||
|
||||
public VersionedEntity() {
|
||||
|
||||
}
|
||||
|
||||
public VersionedEntity(Integer id, String data) {
|
||||
this.id = id;
|
||||
this.data = data;
|
||||
}
|
||||
|
||||
public Integer getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(Integer id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getData() {
|
||||
return data;
|
||||
}
|
||||
|
||||
public void setData(String data) {
|
||||
this.data = data;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if ( this == o ) {
|
||||
return true;
|
||||
}
|
||||
if ( o == null || getClass() != o.getClass() ) {
|
||||
return false;
|
||||
}
|
||||
VersionedEntity that = (VersionedEntity) o;
|
||||
return Objects.equals( id, that.id ) &&
|
||||
Objects.equals( data, that.data );
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash( id, data );
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue