Embedded collection member of and Embeddable parameter binding
This commit is contained in:
parent
7e87deb349
commit
38753afab6
|
@ -135,6 +135,15 @@ public class InferredBasicValueResolver {
|
|||
}
|
||||
}
|
||||
|
||||
if ( jdbcMapping == null ) {
|
||||
throw new MappingException(
|
||||
"Could not determine JavaTypeDescriptor nor SqlTypeDescriptor to use" + "" +
|
||||
" for " + ( (BasicValue) stdIndicators ).getResolvedJavaClass() +
|
||||
"; table = " + table.getName() +
|
||||
"; column = " + selectable.getText()
|
||||
);
|
||||
}
|
||||
|
||||
return new InferredBasicValueResolution(
|
||||
jdbcMapping,
|
||||
jdbcMapping.getJavaTypeDescriptor(),
|
||||
|
|
|
@ -167,6 +167,10 @@ public class BasicValue extends SimpleValue implements SqlTypeDescriptorIndicato
|
|||
return column;
|
||||
}
|
||||
|
||||
public Class getResolvedJavaClass() {
|
||||
return resolvedJavaClass;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getColumnLength() {
|
||||
if ( column != null && column instanceof Column ) {
|
||||
|
|
|
@ -42,6 +42,7 @@ import org.hibernate.metamodel.model.domain.internal.MapMember;
|
|||
import org.hibernate.metamodel.model.domain.internal.MappedSuperclassTypeImpl;
|
||||
import org.hibernate.metamodel.model.domain.internal.PluralAttributeBuilder;
|
||||
import org.hibernate.metamodel.model.domain.internal.SingularAttributeImpl;
|
||||
import org.hibernate.metamodel.spi.EmbeddableRepresentationStrategy;
|
||||
import org.hibernate.metamodel.spi.ManagedTypeRepresentationStrategy;
|
||||
import org.hibernate.persister.entity.EntityPersister;
|
||||
import org.hibernate.property.access.internal.PropertyAccessMapImpl;
|
||||
|
@ -244,7 +245,7 @@ public class AttributeFactory {
|
|||
.getJavaTypeDescriptorRegistry();
|
||||
final JavaTypeDescriptor javaTypeDescriptor = registry.resolveDescriptor( embeddableClass );
|
||||
|
||||
final ManagedTypeRepresentationStrategy representationStrategy = context.getTypeConfiguration()
|
||||
final EmbeddableRepresentationStrategy representationStrategy = context.getTypeConfiguration()
|
||||
.getMetadataBuildingContext()
|
||||
.getBuildingOptions()
|
||||
.getManagedTypeRepresentationResolver()
|
||||
|
|
|
@ -347,6 +347,9 @@ public class EmbeddableMappingType implements ManagedMappingType {
|
|||
TypeConfiguration typeConfiguration) {
|
||||
attributeMappings.forEach(
|
||||
(s, attributeMapping) -> {
|
||||
if ( attributeMapping instanceof PluralAttributeMapping ) {
|
||||
return;
|
||||
}
|
||||
if ( attributeMapping instanceof ToOneAttributeMapping ) {
|
||||
( (ToOneAttributeMapping) attributeMapping ).getKeyTargetMatchPart().visitJdbcTypes(
|
||||
action,
|
||||
|
|
|
@ -275,6 +275,14 @@ public class BasicEntityIdentifierMappingImpl implements BasicEntityIdentifierMa
|
|||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object disassemble(Object value, SharedSessionContractImplementor session) {
|
||||
if ( value == null ) {
|
||||
return null;
|
||||
}
|
||||
return propertyAccess.getGetter().get( value );
|
||||
}
|
||||
|
||||
@Override
|
||||
public Fetch generateFetch(
|
||||
FetchParent fetchParent,
|
||||
|
|
|
@ -40,12 +40,14 @@ import org.hibernate.sql.ast.tree.expression.SqlTuple;
|
|||
import org.hibernate.sql.ast.tree.from.CompositeTableGroup;
|
||||
import org.hibernate.sql.ast.tree.from.TableGroup;
|
||||
import org.hibernate.sql.ast.tree.from.TableGroupJoin;
|
||||
import org.hibernate.sql.results.graph.DomainResult;
|
||||
import org.hibernate.sql.results.graph.DomainResultCreationState;
|
||||
import org.hibernate.sql.results.graph.Fetch;
|
||||
import org.hibernate.sql.results.graph.FetchOptions;
|
||||
import org.hibernate.sql.results.graph.FetchParent;
|
||||
import org.hibernate.sql.results.graph.embeddable.EmbeddableValuedFetchable;
|
||||
import org.hibernate.sql.results.graph.embeddable.internal.EmbeddableFetchImpl;
|
||||
import org.hibernate.sql.results.graph.embeddable.internal.EmbeddableResultImpl;
|
||||
import org.hibernate.type.descriptor.java.JavaTypeDescriptor;
|
||||
import org.hibernate.type.spi.TypeConfiguration;
|
||||
|
||||
|
@ -92,6 +94,20 @@ public class EmbeddedCollectionPart implements CollectionPart, EmbeddableValuedF
|
|||
this.sqlAliasStem = sqlAliasStem;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> DomainResult<T> createDomainResult(
|
||||
NavigablePath navigablePath,
|
||||
TableGroup tableGroup,
|
||||
String resultVariable,
|
||||
DomainResultCreationState creationState) {
|
||||
return new EmbeddableResultImpl<>(
|
||||
navigablePath,
|
||||
this,
|
||||
resultVariable,
|
||||
creationState
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Nature getNature() {
|
||||
return nature;
|
||||
|
|
|
@ -11,6 +11,8 @@ import java.util.ArrayList;
|
|||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
@ -44,8 +46,8 @@ public abstract class AbstractManagedType<J>
|
|||
private final ManagedDomainType<? super J> superType;
|
||||
private final RepresentationMode representationMode;
|
||||
|
||||
private final Map<String, SingularPersistentAttribute<J, ?>> declaredSingularAttributes = new HashMap<>();
|
||||
private final Map<String, PluralPersistentAttribute<J, ?, ?>> declaredPluralAttributes = new HashMap<>();
|
||||
private final Map<String, SingularPersistentAttribute<J, ?>> declaredSingularAttributes = new LinkedHashMap<>();
|
||||
private final Map<String, PluralPersistentAttribute<J, ?, ?>> declaredPluralAttributes = new LinkedHashMap<>();
|
||||
|
||||
private final List<ManagedDomainType> subTypes = new ArrayList<>();
|
||||
|
||||
|
@ -104,7 +106,7 @@ public abstract class AbstractManagedType<J>
|
|||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public Set<Attribute<? super J, ?>> getAttributes() {
|
||||
final HashSet attributes = new HashSet<>( getDeclaredAttributes() );
|
||||
final HashSet attributes = new LinkedHashSet( getDeclaredAttributes() );
|
||||
|
||||
if ( getSuperType() != null ) {
|
||||
attributes.addAll( getSuperType().getAttributes() );
|
||||
|
@ -120,7 +122,7 @@ public abstract class AbstractManagedType<J>
|
|||
return Collections.emptySet();
|
||||
}
|
||||
|
||||
final HashSet attributes = new HashSet<>( declaredSingularAttributes.values() );
|
||||
final HashSet attributes = new LinkedHashSet( declaredSingularAttributes.values() );
|
||||
attributes.addAll( declaredPluralAttributes.values() );
|
||||
return attributes;
|
||||
}
|
||||
|
|
|
@ -18,6 +18,6 @@ import org.hibernate.metamodel.spi.ManagedTypeRepresentationStrategy;
|
|||
*
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public interface EmbeddableDomainType<J> extends ManagedDomainType<J>, EmbeddableType<J> {
|
||||
public interface EmbeddableDomainType<J> extends ManagedDomainType<J>, EmbeddableType<J>, AllowableParameterType<J> {
|
||||
ManagedTypeRepresentationStrategy getRepresentationStrategy();
|
||||
}
|
||||
|
|
|
@ -7,16 +7,31 @@
|
|||
package org.hibernate.metamodel.model.domain.internal;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.function.Consumer;
|
||||
import javax.persistence.metamodel.Attribute;
|
||||
|
||||
import org.hibernate.NotYetImplementedFor6Exception;
|
||||
import org.hibernate.engine.spi.SharedSessionContractImplementor;
|
||||
import org.hibernate.graph.internal.SubGraphImpl;
|
||||
import org.hibernate.graph.spi.SubGraphImplementor;
|
||||
import org.hibernate.metamodel.mapping.JdbcMapping;
|
||||
import org.hibernate.metamodel.mapping.MappingModelExpressable;
|
||||
import org.hibernate.metamodel.model.domain.AbstractManagedType;
|
||||
import org.hibernate.metamodel.model.domain.EmbeddableDomainType;
|
||||
import org.hibernate.metamodel.model.domain.JpaMetamodel;
|
||||
import org.hibernate.metamodel.spi.EmbeddableRepresentationStrategy;
|
||||
import org.hibernate.metamodel.spi.ManagedTypeRepresentationStrategy;
|
||||
import org.hibernate.persister.entity.EntityPersister;
|
||||
import org.hibernate.property.access.internal.PropertyAccessStrategyMixedImpl;
|
||||
import org.hibernate.property.access.spi.PropertyAccess;
|
||||
import org.hibernate.sql.ast.Clause;
|
||||
import org.hibernate.type.BasicType;
|
||||
import org.hibernate.type.descriptor.java.JavaTypeDescriptor;
|
||||
import org.hibernate.type.spi.TypeConfiguration;
|
||||
|
||||
/**
|
||||
* Standard Hibernate implementation of JPA's {@link javax.persistence.metamodel.EmbeddableType}
|
||||
|
@ -27,13 +42,13 @@ import org.hibernate.type.descriptor.java.JavaTypeDescriptor;
|
|||
*/
|
||||
public class EmbeddableTypeImpl<J>
|
||||
extends AbstractManagedType<J>
|
||||
implements EmbeddableDomainType<J>, Serializable {
|
||||
implements EmbeddableDomainType<J>, Serializable, MappingModelExpressable<J> {
|
||||
|
||||
private final ManagedTypeRepresentationStrategy representationStrategy;
|
||||
private final EmbeddableRepresentationStrategy representationStrategy;
|
||||
|
||||
public EmbeddableTypeImpl(
|
||||
JavaTypeDescriptor<J> javaTypeDescriptor,
|
||||
ManagedTypeRepresentationStrategy representationStrategy,
|
||||
EmbeddableRepresentationStrategy representationStrategy,
|
||||
JpaMetamodel domainMetamodel) {
|
||||
super( javaTypeDescriptor.getJavaType().getName(), javaTypeDescriptor, null, domainMetamodel );
|
||||
this.representationStrategy = representationStrategy;
|
||||
|
@ -71,4 +86,75 @@ public class EmbeddableTypeImpl<J>
|
|||
public <S extends J> SubGraphImplementor<S> makeSubGraph(Class<S> subType) {
|
||||
return new SubGraphImpl( this, true, jpaMetamodel() );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitJdbcValues(
|
||||
Object value, Clause clause, JdbcValuesConsumer valuesConsumer, SharedSessionContractImplementor session) {
|
||||
Object[] disassemble = (Object[]) disassemble( value, session );
|
||||
|
||||
List<JdbcMapping> jdbcMappings = getJdbcMappings( session.getFactory().getTypeConfiguration() );
|
||||
for ( int i = 0; i < disassemble.length; i++ ) {
|
||||
valuesConsumer.consume( disassemble[i], jdbcMappings.get( i ) );
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitJdbcTypes(
|
||||
Consumer<JdbcMapping> action,
|
||||
Clause clause,
|
||||
TypeConfiguration typeConfiguration) {
|
||||
Set<Attribute<? super J, ?>> attributes = getAttributes();
|
||||
|
||||
for ( Attribute attribute : attributes ) {
|
||||
if ( attribute instanceof SingularAttributeImpl ) {
|
||||
if ( attribute.isAssociation() ) {
|
||||
EntityTypeImpl entityType = (EntityTypeImpl) ( (SingularAttributeImpl) attribute ).getValueGraphType();
|
||||
|
||||
BasicType basicType = jpaMetamodel().getTypeConfiguration()
|
||||
.getBasicTypeForJavaType( entityType.findIdAttribute().getJavaType() );
|
||||
action.accept( basicType.getJdbcMapping() );
|
||||
}
|
||||
else {
|
||||
BasicType basicType = jpaMetamodel().getTypeConfiguration()
|
||||
.getBasicTypeForJavaType( attribute.getJavaType() );
|
||||
action.accept( basicType.getJdbcMapping() );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object disassemble(Object value, SharedSessionContractImplementor session) {
|
||||
final Set<Attribute<? super J, ?>> attributes = getAttributes();
|
||||
final List<Object> result = new ArrayList<>();
|
||||
for ( Attribute attribute : attributes ) {
|
||||
if ( attribute instanceof SingularAttributeImpl ) {
|
||||
final PropertyAccess propertyAccess = PropertyAccessStrategyMixedImpl.INSTANCE
|
||||
.buildPropertyAccess( getJavaType(), attribute.getName() );
|
||||
|
||||
final Object attributeValue = propertyAccess.getGetter().get( value );
|
||||
if ( attribute.isAssociation() ) {
|
||||
final EntityPersister entityDescriptor = session.getFactory().getMetamodel()
|
||||
.findEntityDescriptor( attribute.getJavaType().getName() );
|
||||
final Object disassembled = entityDescriptor.getIdentifierMapping().disassemble(
|
||||
attributeValue,
|
||||
session
|
||||
);
|
||||
if ( disassembled instanceof Object[] ) {
|
||||
for ( Object o : (Object[]) disassembled ) {
|
||||
result.add( o );
|
||||
}
|
||||
}
|
||||
else {
|
||||
result.add( disassembled );
|
||||
}
|
||||
}
|
||||
else {
|
||||
result.add( attributeValue );
|
||||
}
|
||||
}
|
||||
}
|
||||
return result.toArray();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -712,6 +712,10 @@ public class MappingMetamodelImpl implements MappingMetamodel, MetamodelImplemen
|
|||
throw new NotYetImplementedFor6Exception( "Resolution of embedded-valued SqmExpressable nodes not yet implemented" );
|
||||
}
|
||||
|
||||
if ( sqmExpressable instanceof EmbeddableTypeImpl ) {
|
||||
return (MappingModelExpressable) sqmExpressable;
|
||||
}
|
||||
|
||||
throw new UnsupportedOperationException( "Cannot determine proper mapping model expressable for " + sqmExpressable );
|
||||
}
|
||||
|
||||
|
|
|
@ -29,7 +29,6 @@ import org.hibernate.metamodel.mapping.CollectionPart;
|
|||
import org.hibernate.metamodel.mapping.MappingModelExpressable;
|
||||
import org.hibernate.metamodel.mapping.ModelPart;
|
||||
import org.hibernate.metamodel.mapping.PluralAttributeMapping;
|
||||
import org.hibernate.metamodel.mapping.internal.BasicValuedCollectionPart;
|
||||
import org.hibernate.metamodel.mapping.internal.EntityCollectionPart;
|
||||
import org.hibernate.metamodel.model.domain.AllowableFunctionReturnType;
|
||||
import org.hibernate.metamodel.model.domain.AllowableParameterType;
|
||||
|
@ -2178,25 +2177,17 @@ public abstract class BaseSqmToSqlAstConverter
|
|||
@Override
|
||||
public MemberOfPredicate visitMemberOfPredicate(SqmMemberOfPredicate predicate) {
|
||||
final SqmPath<?> pluralPath = predicate.getPluralPath();
|
||||
final PluralAttributeMapping mappingModelExpressable = (PluralAttributeMapping) SqmMappingModelHelper.resolveMappingModelExpressable(
|
||||
pluralPath,
|
||||
getCreationContext().getDomainModel(),
|
||||
getFromClauseAccess()::findTableGroup
|
||||
);
|
||||
final PluralAttributeMapping mappingModelExpressable = (PluralAttributeMapping) determineValueMapping(pluralPath);
|
||||
|
||||
final CollectionPart elementDescriptor = mappingModelExpressable.getElementDescriptor();
|
||||
|
||||
if ( elementDescriptor instanceof EntityCollectionPart ) {
|
||||
if ( mappingModelExpressable.getElementDescriptor() instanceof EntityCollectionPart ) {
|
||||
inferableTypeAccessStack.push(
|
||||
() -> ( (EntityCollectionPart) elementDescriptor ).getEntityMappingType().getIdentifierMapping() );
|
||||
}
|
||||
else if ( elementDescriptor instanceof BasicValuedCollectionPart ) {
|
||||
inferableTypeAccessStack.push( () -> elementDescriptor );
|
||||
() -> ( (EntityCollectionPart) mappingModelExpressable.getElementDescriptor() ).getEntityMappingType()
|
||||
.getIdentifierMapping() );
|
||||
}
|
||||
else {
|
||||
throw new NotYetImplementedFor6Exception(
|
||||
"Member of with Collection of Embeddable has not yet been implemented" );
|
||||
inferableTypeAccessStack.push( () -> mappingModelExpressable );
|
||||
}
|
||||
|
||||
final Expression lhs;
|
||||
try {
|
||||
lhs = (Expression) predicate.getLeftHandExpression().accept( this );
|
||||
|
@ -2234,6 +2225,8 @@ public abstract class BaseSqmToSqlAstConverter
|
|||
creationContext
|
||||
);
|
||||
|
||||
fromClauseIndex.registerTableGroup( pluralPath.getNavigablePath(), rootTableGroup );
|
||||
|
||||
querySpec.getFromClause().addRoot( rootTableGroup );
|
||||
|
||||
final CollectionPart elementDescriptor = mappingModelExpressable.getElementDescriptor();
|
||||
|
|
|
@ -0,0 +1,145 @@
|
|||
package org.hibernate.orm.test.annotations.collectionelement;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import javax.persistence.ElementCollection;
|
||||
import javax.persistence.Embeddable;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.JoinColumn;
|
||||
import javax.persistence.JoinTable;
|
||||
import javax.persistence.ManyToOne;
|
||||
|
||||
import org.hibernate.query.spi.QueryImplementor;
|
||||
|
||||
import org.hibernate.testing.orm.junit.DomainModel;
|
||||
import org.hibernate.testing.orm.junit.SessionFactory;
|
||||
import org.hibernate.testing.orm.junit.SessionFactoryScope;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
/**
|
||||
* @author Andrea Boriero
|
||||
*/
|
||||
@DomainModel(annotatedClasses = {
|
||||
EmbeddableElementCollectionMemberOfTest.Person.class,
|
||||
EmbeddableElementCollectionMemberOfTest.City.class
|
||||
})
|
||||
@SessionFactory
|
||||
public class EmbeddableElementCollectionMemberOfTest {
|
||||
|
||||
@Test
|
||||
public void testMemberOfQuery(SessionFactoryScope scope) {
|
||||
scope.inTransaction(
|
||||
session -> {
|
||||
Address a = new Address();
|
||||
a.setStreet( "Lollard Street" );
|
||||
QueryImplementor query = session.createQuery( "from Person p where :address member of p.addresses" );
|
||||
query.setParameter( "address", a );
|
||||
query.list();
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
@Entity(name = "Person")
|
||||
public static class Person {
|
||||
private Long id;
|
||||
private String name;
|
||||
private Set<Address> addresses = new HashSet<>();
|
||||
private Address address;
|
||||
|
||||
@Id
|
||||
public Long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(Long id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
@ElementCollection
|
||||
@JoinTable(
|
||||
name = "addresses",
|
||||
joinColumns = @JoinColumn(name = "PERSON_ID"))
|
||||
public Set<Address> getAddresses() {
|
||||
return addresses;
|
||||
}
|
||||
|
||||
public void setAddresses(Set<Address> addresses) {
|
||||
this.addresses = addresses;
|
||||
}
|
||||
|
||||
public Address getAddress() {
|
||||
return address;
|
||||
}
|
||||
|
||||
public void setAddress(Address address) {
|
||||
this.address = address;
|
||||
}
|
||||
}
|
||||
|
||||
@Embeddable
|
||||
public static class Address {
|
||||
public String street;
|
||||
public int number;
|
||||
|
||||
public City city;
|
||||
|
||||
public String getStreet() {
|
||||
return street;
|
||||
}
|
||||
|
||||
public void setStreet(String street) {
|
||||
this.street = street;
|
||||
}
|
||||
|
||||
public int getNumber() {
|
||||
return number;
|
||||
}
|
||||
|
||||
public void setNumber(int number) {
|
||||
this.number = number;
|
||||
}
|
||||
|
||||
@ManyToOne
|
||||
public City getCity() {
|
||||
return city;
|
||||
}
|
||||
|
||||
public void setCity(City city) {
|
||||
this.city = city;
|
||||
}
|
||||
}
|
||||
|
||||
@Entity(name = "City")
|
||||
public static class City {
|
||||
|
||||
private Long id;
|
||||
|
||||
private String name;
|
||||
|
||||
@Id
|
||||
public Long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(Long id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -128,7 +128,6 @@ public class EagerManyToOneEmbeddedIdFKTest {
|
|||
}
|
||||
|
||||
@Test
|
||||
@FailureExpected(reason = "Embedded parameters has not yet been implemented ")
|
||||
public void testEmbeddedIdParameter(SessionFactoryScope scope) {
|
||||
scope.inTransaction(
|
||||
session -> {
|
||||
|
|
|
@ -19,7 +19,6 @@ import org.hibernate.Hibernate;
|
|||
|
||||
import org.hibernate.testing.jdbc.SQLStatementInspector;
|
||||
import org.hibernate.testing.orm.junit.DomainModel;
|
||||
import org.hibernate.testing.orm.junit.FailureExpected;
|
||||
import org.hibernate.testing.orm.junit.SessionFactory;
|
||||
import org.hibernate.testing.orm.junit.SessionFactoryScope;
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
|
@ -150,7 +149,6 @@ public class ManyToOneEmbeddedIdWithToOneFKTest {
|
|||
}
|
||||
|
||||
@Test
|
||||
@FailureExpected(reason = "Embedded parameters has not yet been implemented ")
|
||||
public void testEmbeddedIdParameter(SessionFactoryScope scope) {
|
||||
scope.inTransaction(
|
||||
session -> {
|
||||
|
@ -159,7 +157,7 @@ public class ManyToOneEmbeddedIdWithToOneFKTest {
|
|||
PK superUserKey = new PK( dataCenter, "Fab" );
|
||||
|
||||
System system = session.createQuery(
|
||||
"from System e join fetch e.user u where u.id = :id",
|
||||
"from System e join fetch e.dataCenterUser u where u.id = :id",
|
||||
System.class
|
||||
).setParameter( "id", superUserKey ).uniqueResult();
|
||||
|
||||
|
|
|
@ -123,7 +123,6 @@ public class OneToManyEmbeddedIdFKTest {
|
|||
}
|
||||
|
||||
@Test
|
||||
@FailureExpected(reason = "Embedded parameters has not yet been implemented ")
|
||||
public void testEmbeddedIdParameter(SessionFactoryScope scope) {
|
||||
scope.inTransaction(
|
||||
session -> {
|
||||
|
@ -135,7 +134,7 @@ public class OneToManyEmbeddedIdFKTest {
|
|||
).setParameter( "id", superUserKey ).uniqueResult();
|
||||
|
||||
assertThat( system, is( notNullValue() ) );
|
||||
assertThat( system.getUsers().size(), is( 2 ) );
|
||||
assertThat( system.getUsers().size(), is( 1 ) );
|
||||
}
|
||||
);
|
||||
}
|
||||
|
|
|
@ -10,9 +10,11 @@ import java.util.List;
|
|||
import javax.persistence.Embeddable;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.OneToMany;
|
||||
|
||||
import org.hibernate.testing.junit5.SessionFactoryBasedFunctionalTest;
|
||||
import org.hibernate.testing.orm.junit.FailureExpected;
|
||||
import org.hibernate.testing.orm.junit.DomainModel;
|
||||
import org.hibernate.testing.orm.junit.SessionFactory;
|
||||
import org.hibernate.testing.orm.junit.SessionFactoryScope;
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
@ -23,19 +25,18 @@ import static org.hamcrest.MatcherAssert.assertThat;
|
|||
/**
|
||||
* @author Andrea Boriero
|
||||
*/
|
||||
@FailureExpected( reason = "Support for embedded-valued parameters not yet implemented" )
|
||||
public class EmbeddableAsParameterTest extends SessionFactoryBasedFunctionalTest {
|
||||
|
||||
@Override
|
||||
protected Class[] getAnnotatedClasses() {
|
||||
return new Class[] {
|
||||
Person.class,
|
||||
};
|
||||
}
|
||||
@DomainModel(
|
||||
annotatedClasses = {
|
||||
EmbeddableAsParameterTest.Person.class,
|
||||
EmbeddableAsParameterTest.EntityTest.class
|
||||
}
|
||||
)
|
||||
@SessionFactory
|
||||
public class EmbeddableAsParameterTest {
|
||||
|
||||
@Test
|
||||
public void testAsParameterInWhereClause() {
|
||||
inTransaction(
|
||||
public void testAsParameterInWhereClause(SessionFactoryScope scope) {
|
||||
scope.inTransaction(
|
||||
session -> {
|
||||
List results = session.createQuery( "select p from Person p where p.name = :name" ).
|
||||
setParameter( "name", new Name( "Fab", "Fab" ) ).list();
|
||||
|
@ -45,19 +46,32 @@ public class EmbeddableAsParameterTest extends SessionFactoryBasedFunctionalTest
|
|||
}
|
||||
|
||||
@Test
|
||||
public void testAsParameterReuseInWhereClause() {
|
||||
inTransaction(
|
||||
public void testAsParameterReuseInWhereClause(SessionFactoryScope scope) {
|
||||
scope.inTransaction(
|
||||
session -> {
|
||||
List results = session.createQuery( "select p from Person p where p.name = :name or p.name = :name " ).
|
||||
setParameter( "name", new Name( "Fab", "Fab" ) ).list();
|
||||
List results = session.createQuery( "select p from Person p where p.name = :name or p.name = :name " )
|
||||
.
|
||||
setParameter( "name", new Name( "Fab", "Fab" ) )
|
||||
.list();
|
||||
assertThat( results.size(), is( 1 ) );
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAsParameterReuseInWhereClause2(SessionFactoryScope scope) {
|
||||
scope.inTransaction(
|
||||
session -> {
|
||||
List results = session.createQuery( "select p from Person p where p.embeddableTest = :embeddable" ).
|
||||
setParameter( "embeddable", new EmbeddableTest() ).list();
|
||||
assertThat( results.size(), is( 0 ) );
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
@BeforeEach
|
||||
public void setUp() {
|
||||
inTransaction(
|
||||
public void setUp(SessionFactoryScope scope) {
|
||||
scope.inTransaction(
|
||||
session -> {
|
||||
Person person = new Person(
|
||||
1,
|
||||
|
@ -70,8 +84,8 @@ public class EmbeddableAsParameterTest extends SessionFactoryBasedFunctionalTest
|
|||
}
|
||||
|
||||
@AfterEach
|
||||
public void tearDown() {
|
||||
inTransaction(
|
||||
public void tearDown(SessionFactoryScope scope) {
|
||||
scope.inTransaction(
|
||||
session -> {
|
||||
session.createQuery( "delete Person" ).executeUpdate();
|
||||
}
|
||||
|
@ -85,6 +99,8 @@ public class EmbeddableAsParameterTest extends SessionFactoryBasedFunctionalTest
|
|||
|
||||
private Name name;
|
||||
|
||||
private EmbeddableTest embeddableTest;
|
||||
|
||||
private Integer age;
|
||||
|
||||
public Person() {
|
||||
|
@ -124,6 +140,46 @@ public class EmbeddableAsParameterTest extends SessionFactoryBasedFunctionalTest
|
|||
public void setAge(Integer age) {
|
||||
this.age = age;
|
||||
}
|
||||
|
||||
public EmbeddableTest getEmbeddableTest() {
|
||||
return embeddableTest;
|
||||
}
|
||||
|
||||
public void setEmbeddableTest(EmbeddableTest embeddableTest) {
|
||||
this.embeddableTest = embeddableTest;
|
||||
}
|
||||
}
|
||||
|
||||
@Embeddable
|
||||
public static class EmbeddableTest {
|
||||
private String street;
|
||||
|
||||
@OneToMany
|
||||
private List<EntityTest> entityTests;
|
||||
|
||||
}
|
||||
|
||||
@Entity(name = "EmbeddableTest")
|
||||
public static class EntityTest {
|
||||
@Id
|
||||
private Long id;
|
||||
private String name;
|
||||
|
||||
public Long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(Long id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -0,0 +1,114 @@
|
|||
package org.hibernate.orm.test.query.hql;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import javax.persistence.CascadeType;
|
||||
import javax.persistence.Embeddable;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.OneToMany;
|
||||
|
||||
import org.hibernate.testing.orm.junit.DomainModel;
|
||||
import org.hibernate.testing.orm.junit.SessionFactory;
|
||||
import org.hibernate.testing.orm.junit.SessionFactoryScope;
|
||||
import org.junit.jupiter.api.BeforeAll;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static org.hamcrest.CoreMatchers.is;
|
||||
import static org.hamcrest.MatcherAssert.assertThat;
|
||||
|
||||
|
||||
/**
|
||||
* @author Andrea Boriero
|
||||
*/
|
||||
@DomainModel(
|
||||
annotatedClasses = {
|
||||
EmbeddableWithPluralAttributeTest.A.class,
|
||||
EmbeddableWithPluralAttributeTest.C.class
|
||||
}
|
||||
)
|
||||
@SessionFactory
|
||||
public class EmbeddableWithPluralAttributeTest {
|
||||
|
||||
|
||||
@BeforeAll
|
||||
public void setUp(SessionFactoryScope scope){
|
||||
scope.inTransaction(
|
||||
session -> {
|
||||
A a = new A();
|
||||
a.id = 1;
|
||||
|
||||
B b = B.buildB();
|
||||
a.b = b;
|
||||
|
||||
session.save( a );
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAsParameterReuseInWhereClauseZeroResults(SessionFactoryScope scope) {
|
||||
|
||||
scope.inTransaction(
|
||||
session -> {
|
||||
List results = session.createQuery( "select a from A a where a.b = :b" ).
|
||||
setParameter( "b", new B() ).list();
|
||||
assertThat( results.size(), is( 0 ) );
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAsParameterReuseInWhereClause(SessionFactoryScope scope) {
|
||||
|
||||
scope.inTransaction(
|
||||
session -> {
|
||||
List results = session.createQuery( "select a from A a where a.b = :b" ).
|
||||
setParameter( "b", B.buildB() ).list();
|
||||
assertThat( results.size(), is( 1 ) );
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
@Entity(name = "A")
|
||||
public static class A {
|
||||
@Id
|
||||
private Integer id;
|
||||
|
||||
private B b;
|
||||
|
||||
}
|
||||
|
||||
@Embeddable
|
||||
public static class B {
|
||||
private String value;
|
||||
|
||||
@OneToMany(cascade = CascadeType.ALL)
|
||||
private List<C> cs;
|
||||
|
||||
public static B buildB() {
|
||||
B b = new B();
|
||||
b.value = "v";
|
||||
C c = new C();
|
||||
|
||||
c.id = 2L;
|
||||
c.name = "c";
|
||||
|
||||
List cs = new ArrayList();
|
||||
cs.add( c );
|
||||
b.cs = cs;
|
||||
|
||||
return b;
|
||||
}
|
||||
}
|
||||
|
||||
@Entity(name = "C")
|
||||
public static class C {
|
||||
@Id
|
||||
private Long id;
|
||||
|
||||
private String name;
|
||||
}
|
||||
|
||||
|
||||
}
|
Loading…
Reference in New Issue