parent
5359a7b5fd
commit
4dd7c280ca
|
@ -10,6 +10,8 @@ import java.io.Serializable;
|
|||
import java.sql.Connection;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Function;
|
||||
import javax.naming.Referenceable;
|
||||
import javax.persistence.EntityManagerFactory;
|
||||
|
||||
|
@ -103,6 +105,108 @@ public interface SessionFactory extends EntityManagerFactory, HibernateEntityMan
|
|||
*/
|
||||
StatelessSession openStatelessSession(Connection connection);
|
||||
|
||||
/**
|
||||
* Open a Session and perform a action using it
|
||||
*/
|
||||
default void inSession(Consumer<Session> action) {
|
||||
try (Session session = openSession()) {
|
||||
action.accept( session );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Open a Session and perform a action using it within the bounds of a transaction
|
||||
*/
|
||||
default void inTransaction(Consumer<Session> action) {
|
||||
inSession(
|
||||
session -> {
|
||||
final Transaction txn = session.beginTransaction();
|
||||
|
||||
try {
|
||||
action.accept( session );
|
||||
|
||||
if ( !txn.isActive() ) {
|
||||
throw new TransactionManagementException( "Execution of action caused managed transaction to be completed" );
|
||||
}
|
||||
}
|
||||
catch (RuntimeException e) {
|
||||
// an error happened in the action
|
||||
if ( txn.isActive() ) {
|
||||
try {
|
||||
txn.rollback();
|
||||
}
|
||||
catch (Exception ignore) {
|
||||
}
|
||||
}
|
||||
|
||||
throw e;
|
||||
}
|
||||
|
||||
// action completed with no errors - attempt to commit the transaction allowing
|
||||
// any RollbackException to propagate. Note that when we get here we know the
|
||||
// txn is active
|
||||
|
||||
txn.commit();
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
class TransactionManagementException extends RuntimeException {
|
||||
TransactionManagementException(String message) {
|
||||
super( message );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Open a Session and perform a action using it
|
||||
*/
|
||||
default <R> R fromSession(Function<Session,R> action) {
|
||||
try (Session session = openSession()) {
|
||||
return action.apply( session );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Open a Session and perform a action using it within the bounds of a transaction
|
||||
*/
|
||||
default <R> R fromTransaction(Function<Session,R> action) {
|
||||
return fromSession(
|
||||
session -> {
|
||||
R result = null;
|
||||
|
||||
final Transaction txn = session.beginTransaction();
|
||||
|
||||
try {
|
||||
result = action.apply( session );
|
||||
|
||||
if ( !txn.isActive() ) {
|
||||
throw new TransactionManagementException( "Execution of action caused managed transaction to be completed" );
|
||||
}
|
||||
}
|
||||
catch (RuntimeException e) {
|
||||
// an error happened in the action
|
||||
if ( txn.isActive() ) {
|
||||
try {
|
||||
txn.rollback();
|
||||
}
|
||||
catch (Exception ignore) {
|
||||
}
|
||||
}
|
||||
|
||||
throw e;
|
||||
}
|
||||
|
||||
// action completed with no errors - attempt to commit the transaction allowing
|
||||
// any RollbackException to propagate. Note that when we get here we know the
|
||||
// txn is active
|
||||
|
||||
txn.commit();
|
||||
|
||||
return result;
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve the statistics fopr this factory.
|
||||
*
|
||||
|
|
|
@ -7,24 +7,19 @@
|
|||
package org.hibernate.metamodel.model.domain;
|
||||
|
||||
import org.hibernate.Incubating;
|
||||
import org.hibernate.metamodel.model.mapping.spi.Writeable;
|
||||
import org.hibernate.metamodel.model.mapping.spi.ModelPart;
|
||||
import org.hibernate.metamodel.model.mapping.spi.ValueMapping;
|
||||
import org.hibernate.query.Query;
|
||||
import org.hibernate.query.sqm.SqmExpressable;
|
||||
import org.hibernate.type.descriptor.java.JavaTypeDescriptor;
|
||||
|
||||
/**
|
||||
* Specialization of DomainType for types that can be used as {@link Query} parameter bind values
|
||||
* Specialization of DomainType for types that can be used as {@link Query} parameter bind values.
|
||||
*
|
||||
* todo (6.0) : extend Writeable? or expose Writeable as "component"?
|
||||
* i.e.
|
||||
* ````
|
||||
* Writeable getWriteable();
|
||||
* ````
|
||||
* todo (6.0) : Need a resolution between AllowableParameterType and {@link ValueMapping} / {@link ModelPart}
|
||||
*
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
@Incubating
|
||||
public interface AllowableParameterType<J> extends Writeable, SqmExpressable<J> {
|
||||
|
||||
public interface AllowableParameterType<J> extends SimpleDomainType<J> {
|
||||
JavaTypeDescriptor<J> getExpressableJavaTypeDescriptor();
|
||||
}
|
||||
|
|
|
@ -6,17 +6,17 @@
|
|||
*/
|
||||
package org.hibernate.metamodel.model.domain.internal;
|
||||
|
||||
import org.hibernate.metamodel.model.domain.AllowableParameterType;
|
||||
import org.hibernate.metamodel.model.domain.EmbeddableDomainType;
|
||||
import org.hibernate.query.sqm.SqmPathSource;
|
||||
import org.hibernate.query.sqm.produce.spi.SqmCreationState;
|
||||
import org.hibernate.query.sqm.tree.domain.SqmAnyValuedSimplePath;
|
||||
import org.hibernate.query.sqm.tree.domain.SqmEmbeddedValuedSimplePath;
|
||||
import org.hibernate.query.sqm.tree.domain.SqmPath;
|
||||
|
||||
/**
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public class EmbeddedSqmPathSource<J> extends AbstractSqmPathSource<J> {
|
||||
public class EmbeddedSqmPathSource<J> extends AbstractSqmPathSource<J> implements AllowableParameterType<J> {
|
||||
public EmbeddedSqmPathSource(
|
||||
String localPathName,
|
||||
EmbeddableDomainType<J> domainType,
|
||||
|
@ -30,6 +30,16 @@ public class EmbeddedSqmPathSource<J> extends AbstractSqmPathSource<J> {
|
|||
return (EmbeddableDomainType<J>) super.getSqmPathType();
|
||||
}
|
||||
|
||||
@Override
|
||||
public PersistenceType getPersistenceType() {
|
||||
return PersistenceType.EMBEDDABLE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<J> getJavaType() {
|
||||
return getBindableJavaType();
|
||||
}
|
||||
|
||||
@Override
|
||||
public SqmPathSource<?> findSubPathSource(String name) {
|
||||
return (SqmPathSource<?>) getSqmPathType().findAttribute( name );
|
||||
|
|
|
@ -73,14 +73,15 @@ public class StandardCallableStatementSupport implements CallableStatementSuppor
|
|||
sep = ",";
|
||||
}
|
||||
else {
|
||||
parameter.getHibernateType().visitJdbcTypes(
|
||||
sqlExpressableType -> {
|
||||
buffer.append( sep ).append( "?" );
|
||||
sep = ",";
|
||||
},
|
||||
Clause.IRRELEVANT,
|
||||
session.getFactory().getTypeConfiguration()
|
||||
);
|
||||
throw new NotYetImplementedFor6Exception( getClass() );
|
||||
// parameter.getHibernateType().visitJdbcTypes(
|
||||
// sqlExpressableType -> {
|
||||
// buffer.append( sep ).append( "?" );
|
||||
// sep = ",";
|
||||
// },
|
||||
// Clause.IRRELEVANT,
|
||||
// session.getFactory().getTypeConfiguration()
|
||||
// );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -104,6 +104,7 @@ import org.hibernate.query.sqm.tree.from.SqmQualifiedJoin;
|
|||
import org.hibernate.query.sqm.tree.from.SqmRoot;
|
||||
import org.hibernate.query.sqm.tree.insert.SqmInsertSelectStatement;
|
||||
import org.hibernate.query.sqm.tree.predicate.SqmAndPredicate;
|
||||
import org.hibernate.query.sqm.tree.predicate.SqmBetweenPredicate;
|
||||
import org.hibernate.query.sqm.tree.predicate.SqmComparisonPredicate;
|
||||
import org.hibernate.query.sqm.tree.predicate.SqmEmptinessPredicate;
|
||||
import org.hibernate.query.sqm.tree.predicate.SqmGroupedPredicate;
|
||||
|
@ -165,9 +166,6 @@ public class SemanticQueryBuilder extends HqlParserBaseVisitor implements SqmCre
|
|||
private final SqmCreationOptions creationOptions;
|
||||
private final SqmCreationContext creationContext;
|
||||
|
||||
private final ImplicitAliasGenerator implicitAliasGenerator;
|
||||
private final UniqueIdGenerator uidGenerator;
|
||||
|
||||
private final Stack<DotIdentifierConsumer> dotIdentifierConsumerStack;
|
||||
|
||||
private final Stack<TreatHandler> treatHandlerStack = new StandardStack<>( new TreatHandlerNormal() );
|
||||
|
@ -186,11 +184,7 @@ public class SemanticQueryBuilder extends HqlParserBaseVisitor implements SqmCre
|
|||
this.creationOptions = creationOptions;
|
||||
this.creationContext = creationContext;
|
||||
|
||||
this.implicitAliasGenerator = new ImplicitAliasGenerator();
|
||||
this.uidGenerator = new UniqueIdGenerator();
|
||||
|
||||
this.dotIdentifierConsumerStack = new StandardStack<>( new BasicDotIdentifierConsumer( this ) );
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -1092,6 +1086,18 @@ public class SemanticQueryBuilder extends HqlParserBaseVisitor implements SqmCre
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public SqmBetweenPredicate visitBetweenPredicate(HqlParser.BetweenPredicateContext ctx) {
|
||||
return new SqmBetweenPredicate(
|
||||
(SqmExpression) ctx.expression( 0 ).accept( this ),
|
||||
(SqmExpression) ctx.expression( 1 ).accept( this ),
|
||||
(SqmExpression) ctx.expression( 2 ).accept( this ),
|
||||
ctx.NOT() != null,
|
||||
creationContext.getNodeBuilder()
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public SqmNullnessPredicate visitIsNullPredicate(HqlParser.IsNullPredicateContext ctx) {
|
||||
return new SqmNullnessPredicate(
|
||||
|
@ -1187,7 +1193,6 @@ public class SemanticQueryBuilder extends HqlParserBaseVisitor implements SqmCre
|
|||
else {
|
||||
throw new SemanticException( "Path argument to MEMBER OF must be a plural attribute" );
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -861,4 +861,14 @@ public class ComponentType extends AbstractType implements CompositeType, Proced
|
|||
public JavaTypeDescriptor getExpressableJavaTypeDescriptor() {
|
||||
throw new NotYetImplementedFor6Exception( getClass() );
|
||||
}
|
||||
|
||||
@Override
|
||||
public PersistenceType getPersistenceType() {
|
||||
return PersistenceType.EMBEDDABLE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class getJavaType() {
|
||||
return getReturnedClass();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -33,7 +33,7 @@ public class JdbcDateTypeDescriptor extends AbstractTypeDescriptor<Date> {
|
|||
* @see #DATE_FORMAT
|
||||
*/
|
||||
@SuppressWarnings("unused")
|
||||
public static final DateTimeFormatter LITERAL_FORMATTER = DateTimeFormatter.ofPattern( DATE_FORMAT );
|
||||
public static final DateTimeFormatter LITERAL_FORMATTER = DateTimeFormatter.ISO_LOCAL_DATE;
|
||||
|
||||
/**
|
||||
* Alias for {@link java.time.format.DateTimeFormatter#ISO_LOCAL_DATE}.
|
||||
|
|
|
@ -28,7 +28,7 @@ public class JdbcTimeTypeDescriptor extends AbstractTypeDescriptor<Date> {
|
|||
@SuppressWarnings("WeakerAccess")
|
||||
public static final String TIME_FORMAT = "HH:mm:ss.SSS";
|
||||
|
||||
public static final DateTimeFormatter LITERAL_FORMATTER = DateTimeFormatter.ofPattern( TIME_FORMAT );
|
||||
public static final DateTimeFormatter LITERAL_FORMATTER = DateTimeFormatter.ISO_LOCAL_TIME;
|
||||
|
||||
/**
|
||||
* Alias for {@link java.time.format.DateTimeFormatter#ISO_LOCAL_TIME}.
|
||||
|
|
|
@ -34,7 +34,7 @@ public class JdbcTimestampTypeDescriptor extends AbstractTypeDescriptor<Date> {
|
|||
* @see #TIMESTAMP_FORMAT
|
||||
*/
|
||||
@SuppressWarnings("unused")
|
||||
public static final DateTimeFormatter LITERAL_FORMATTER = DateTimeFormatter.ofPattern( TIMESTAMP_FORMAT );
|
||||
public static final DateTimeFormatter LITERAL_FORMATTER = DateTimeFormatter.ISO_LOCAL_DATE_TIME;
|
||||
|
||||
/**
|
||||
* Alias for {@link java.time.format.DateTimeFormatter#ISO_LOCAL_DATE_TIME}.
|
||||
|
|
|
@ -17,6 +17,7 @@ import org.hibernate.query.sqm.tree.predicate.SqmComparisonPredicate;
|
|||
import org.hibernate.query.sqm.tree.select.SqmSelectStatement;
|
||||
import org.hibernate.query.sqm.tree.select.SqmSelectableNode;
|
||||
|
||||
import org.hibernate.testing.orm.junit.FailureExpected;
|
||||
import org.hibernate.testing.orm.junit.TestingUtil;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
|
@ -86,6 +87,7 @@ public class CaseExpressionsTest extends BaseSqmUnitTest {
|
|||
}
|
||||
|
||||
@Test
|
||||
@FailureExpected( "Support for functions not yet defined" )
|
||||
public void testBasicCoalesceExpression() {
|
||||
SqmSelectStatement select = interpretSelect(
|
||||
"select coalesce(p.nickName, p.mate.nickName) from Person p"
|
||||
|
@ -103,6 +105,7 @@ public class CaseExpressionsTest extends BaseSqmUnitTest {
|
|||
}
|
||||
|
||||
@Test
|
||||
@FailureExpected( "Support for functions not yet defined" )
|
||||
public void testBasicNullifExpression() {
|
||||
SqmSelectStatement select = interpretSelect(
|
||||
"select nullif(p.nickName, p.mate.nickName) from Person p"
|
||||
|
|
|
@ -0,0 +1,40 @@
|
|||
/*
|
||||
* 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.orm.test.query.hql;
|
||||
|
||||
import org.hibernate.boot.MetadataSources;
|
||||
import org.hibernate.orm.test.query.sqm.BaseSqmUnitTest;
|
||||
import org.hibernate.query.sqm.tree.select.SqmSelectStatement;
|
||||
|
||||
import org.hibernate.testing.orm.domain.StandardDomainModel;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
/**
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public class LiteralTests extends BaseSqmUnitTest {
|
||||
|
||||
@Override
|
||||
protected void applyMetadataSources(MetadataSources metadataSources) {
|
||||
StandardDomainModel.GAMBIT.getDescriptor().applyDomainModel( metadataSources );
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTimestampLiteral() {
|
||||
final SqmSelectStatement sqm = interpretSelect( "from EntityOfBasics e1 where e1.theTimestamp = {ts '2018-01-01T12:30:00'}" );
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDateLiteral() {
|
||||
final SqmSelectStatement sqm = interpretSelect( "from EntityOfBasics e1 where e1.theDate = {d '2018-01-01'}" );
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTimeLiteral() {
|
||||
final SqmSelectStatement sqm = interpretSelect( "from EntityOfBasics e1 where e1.theTime = {t '12:30:00'}" );
|
||||
}
|
||||
}
|
|
@ -0,0 +1,54 @@
|
|||
/*
|
||||
* 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.orm.test.query.hql;
|
||||
|
||||
import org.hibernate.cfg.AvailableSettings;
|
||||
|
||||
import org.hibernate.testing.orm.domain.StandardDomainModel;
|
||||
import org.hibernate.testing.orm.junit.DomainModel;
|
||||
import org.hibernate.testing.orm.junit.ServiceRegistry;
|
||||
import org.hibernate.testing.orm.junit.SessionFactory;
|
||||
import org.hibernate.testing.orm.junit.SessionFactoryScope;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static org.hibernate.orm.test.query.sqm.BaseSqmUnitTest.interpretSelect;
|
||||
|
||||
/**
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
@SuppressWarnings("WeakerAccess")
|
||||
@DomainModel(
|
||||
standardModels = StandardDomainModel.GAMBIT
|
||||
)
|
||||
@ServiceRegistry(
|
||||
settings = @ServiceRegistry.Setting(
|
||||
name = AvailableSettings.HBM2DDL_AUTO,
|
||||
value = "create-drop"
|
||||
)
|
||||
)
|
||||
@SessionFactory
|
||||
public class PagingTests {
|
||||
|
||||
@Test
|
||||
public void testPagingByParameter(SessionFactoryScope scope) {
|
||||
interpretSelect( "select o from SimpleEntity o offset :param", scope.getSessionFactory() );
|
||||
interpretSelect( "select o from SimpleEntity o limit :param", scope.getSessionFactory() );
|
||||
interpretSelect( "select o from SimpleEntity o limit :param offset :param", scope.getSessionFactory() );
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPagingByConstant(SessionFactoryScope scope) {
|
||||
interpretSelect( "select o from SimpleEntity o offset 1", scope.getSessionFactory() );
|
||||
interpretSelect( "select o from SimpleEntity o limit 1", scope.getSessionFactory() );
|
||||
interpretSelect( "select o from SimpleEntity o limit 1 offset 1", scope.getSessionFactory() );
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPagingOnSubQuery(SessionFactoryScope scope) {
|
||||
interpretSelect( "select o from SimpleEntity o where o.someString = ( select oSub.someString from SimpleEntity oSub order by oSub.someString limit 1 )", scope.getSessionFactory() );
|
||||
}
|
||||
}
|
|
@ -7,6 +7,8 @@
|
|||
package org.hibernate.orm.test.query.hql;
|
||||
|
||||
import java.time.Instant;
|
||||
import java.time.temporal.ChronoUnit;
|
||||
import java.util.Date;
|
||||
import javax.persistence.Embeddable;
|
||||
import javax.persistence.Embedded;
|
||||
import javax.persistence.Entity;
|
||||
|
@ -15,19 +17,24 @@ import javax.persistence.ManyToOne;
|
|||
import javax.persistence.Temporal;
|
||||
import javax.persistence.TemporalType;
|
||||
|
||||
import org.hibernate.metamodel.model.domain.BasicDomainType;
|
||||
import org.hibernate.metamodel.model.domain.SingularPersistentAttribute;
|
||||
import org.hibernate.Session;
|
||||
import org.hibernate.metamodel.model.domain.internal.BasicSqmPathSource;
|
||||
import org.hibernate.metamodel.model.domain.internal.EmbeddedSqmPathSource;
|
||||
import org.hibernate.orm.test.query.sqm.BaseSqmUnitTest;
|
||||
import org.hibernate.query.Query;
|
||||
import org.hibernate.query.SemanticException;
|
||||
import org.hibernate.query.spi.QueryParameterBinding;
|
||||
import org.hibernate.query.spi.QueryParameterBindings;
|
||||
import org.hibernate.query.sqm.tree.expression.SqmParameter;
|
||||
import org.hibernate.query.sqm.tree.select.SqmSelectStatement;
|
||||
import org.hibernate.sql.exec.spi.DomainParameterBindingContext;
|
||||
|
||||
import org.hibernate.testing.orm.junit.ExpectedException;
|
||||
import org.hibernate.testing.orm.junit.ExpectedExceptionExtension;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
|
||||
import static org.hamcrest.CoreMatchers.equalTo;
|
||||
import static org.hamcrest.CoreMatchers.instanceOf;
|
||||
import static org.hamcrest.CoreMatchers.is;
|
||||
import static org.hamcrest.MatcherAssert.assertThat;
|
||||
|
@ -35,6 +42,8 @@ import static org.hibernate.testing.hamcrest.CollectionMatchers.hasSize;
|
|||
|
||||
/**
|
||||
* @author Steve Ebersole
|
||||
* @author Andrea Boriero
|
||||
* @author Chris Cranford
|
||||
*/
|
||||
@SuppressWarnings("WeakerAccess")
|
||||
@ExtendWith( ExpectedExceptionExtension.class )
|
||||
|
@ -81,6 +90,60 @@ public class ParameterTests extends BaseSqmUnitTest {
|
|||
assertThat( parameter.allowMultiValuedBinding(), is(true) );
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testWideningTemporalPrecision() {
|
||||
try (Session session = sessionFactory().openSession()) {
|
||||
final Query query = session.createQuery( "select p.id from Person p where p.anniversary between :start and :end" );
|
||||
|
||||
query.setParameter( "start", Instant.now().minus( 7, ChronoUnit.DAYS ), TemporalType.TIMESTAMP );
|
||||
query.setParameter( "end", Instant.now().plus( 7, ChronoUnit.DAYS ), TemporalType.TIMESTAMP );
|
||||
|
||||
final QueryParameterBindings bindings = ( (DomainParameterBindingContext) query ).getQueryParameterBindings();
|
||||
|
||||
final QueryParameterBinding<?> startBinding = bindings.getBinding( "start" );
|
||||
assertThat( startBinding.getExplicitTemporalPrecision(), equalTo( TemporalType.TIMESTAMP ) );
|
||||
|
||||
final QueryParameterBinding<?> endBinding = bindings.getBinding( "end" );
|
||||
assertThat( endBinding.getExplicitTemporalPrecision(), equalTo( TemporalType.TIMESTAMP ) );
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNarrowingTemporalPrecision() {
|
||||
try (Session session = sessionFactory().openSession()) {
|
||||
final Query query = session.createQuery( "select p.id from Person p where p.dob between :start and :end" );
|
||||
|
||||
query.setParameter( "start", Instant.now().minus( 7, ChronoUnit.DAYS ), TemporalType.DATE );
|
||||
query.setParameter( "end", Instant.now().plus( 7, ChronoUnit.DAYS ), TemporalType.DATE );
|
||||
|
||||
final QueryParameterBindings bindings = ( (DomainParameterBindingContext) query ).getQueryParameterBindings();
|
||||
|
||||
final QueryParameterBinding<?> startBinding = bindings.getBinding( "start" );
|
||||
assertThat( startBinding.getExplicitTemporalPrecision(), equalTo( TemporalType.DATE ) );
|
||||
|
||||
final QueryParameterBinding<?> endBinding = bindings.getBinding( "end" );
|
||||
assertThat( endBinding.getExplicitTemporalPrecision(), equalTo( TemporalType.DATE ) );
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testEmbeddableUseInPredicates() {
|
||||
{
|
||||
final SqmSelectStatement<?> sqm = interpretSelect( "select p.id from Person p where p.name.first = :fname" );
|
||||
assertThat( sqm.getSqmParameters().size(), equalTo( 1 ) );
|
||||
final SqmParameter<?> parameter = sqm.getSqmParameters().iterator().next();
|
||||
assertThat( parameter.getAnticipatedType(), instanceOf( BasicSqmPathSource.class ) );
|
||||
}
|
||||
|
||||
{
|
||||
final SqmSelectStatement<?> sqm = interpretSelect( "select p.id from Person p where p.name = :name" );
|
||||
assertThat( sqm.getSqmParameters().size(), equalTo( 1 ) );
|
||||
final SqmParameter<?> parameter = sqm.getSqmParameters().iterator().next();
|
||||
assertThat( parameter.getAnticipatedType(), instanceOf( EmbeddedSqmPathSource.class ) );
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Class[] getAnnotatedClasses() {
|
||||
return new Class[] {
|
||||
|
@ -104,12 +167,15 @@ public class ParameterTests extends BaseSqmUnitTest {
|
|||
|
||||
public String nickName;
|
||||
|
||||
@ManyToOne
|
||||
Person mate;
|
||||
|
||||
@Temporal( TemporalType.TIMESTAMP )
|
||||
public Instant dob;
|
||||
|
||||
@ManyToOne
|
||||
public Person mate;
|
||||
|
||||
@Temporal( TemporalType.DATE )
|
||||
public Date anniversary;
|
||||
|
||||
public int numberOfToes;
|
||||
}
|
||||
|
||||
|
|
|
@ -8,6 +8,7 @@ package org.hibernate.orm.test.query.sqm;
|
|||
|
||||
import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
|
||||
import org.hibernate.cfg.AvailableSettings;
|
||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
import org.hibernate.loader.spi.AfterLoadAction;
|
||||
import org.hibernate.metamodel.spi.MetamodelImplementor;
|
||||
import org.hibernate.query.sqm.tree.select.SqmSelectStatement;
|
||||
|
@ -51,7 +52,11 @@ public abstract class BaseSqmUnitTest
|
|||
}
|
||||
|
||||
protected SqmSelectStatement interpretSelect(String hql) {
|
||||
return (SqmSelectStatement) sessionFactory().getQueryEngine().getSemanticQueryProducer().interpret( hql );
|
||||
return interpretSelect( hql, sessionFactory() );
|
||||
}
|
||||
|
||||
public static SqmSelectStatement interpretSelect(String hql, SessionFactoryImplementor sessionFactory) {
|
||||
return (SqmSelectStatement) sessionFactory.getQueryEngine().getSemanticQueryProducer().interpret( hql );
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
Loading…
Reference in New Issue