Merge remote-tracking branch 'upstream/master' into wip/6.0

This commit is contained in:
Andrea Boriero 2020-03-03 16:59:30 +00:00
commit abe1e656f7
53 changed files with 3784 additions and 227 deletions

View File

@ -26,7 +26,7 @@ Generally, this required their users to configure the Hibernate dialect or defin
Starting with version 3.2, Hibernate introduced the notion of automatically detecting the dialect to use based on the `java.sql.DatabaseMetaData` obtained from a `java.sql.Connection` to that database.
This was much better, except that this resolution was limited to databases Hibernate know about ahead of time and was in no way configurable or overrideable.
Starting with version 3.3, Hibernate has a fare more powerful way to automatically determine which dialect to be used by relying on a series of delegates which implement the `org.hibernate.dialect.resolver.DialectResolver` which defines only a single method:
Starting with version 3.3, Hibernate has a far more powerful way to automatically determine which dialect to be used by relying on a series of delegates which implement the `org.hibernate.dialect.resolver.DialectResolver` which defines only a single method:
[source,java]
----

View File

@ -165,9 +165,10 @@ include::{sourcedir}/HQLTest.java[tags=jpql-api-positional-parameter-example]
It's good practice not to mix parameter binding forms in a given query.
====
In terms of execution, JPA `Query` offers 2 different methods for retrieving a result set.
In terms of execution, JPA `Query` offers 3 different methods for retrieving a result set.
* `Query#getResultList()` - executes the select query and returns back the list of results.
* `Query#getResultStream()` - executes the select query and returns back a `Stream` over the results.
* `Query#getSingleResult()` - executes the select query and returns a single result. If there were more than one result an exception is thrown.
[[jpql-api-list-example]]
@ -179,6 +180,15 @@ include::{sourcedir}/HQLTest.java[tags=jpql-api-list-example]
----
====
[[jpql-api-stream-example]]
.JPA `getResultStream()` result
====
[source, JAVA, indent=0]
----
include::{sourcedir}/HQLTest.java[tags=jpql-api-stream-example]
----
====
[[jpql-api-unique-result-example]]
.JPA `getSingleResult()`
====
@ -414,6 +424,29 @@ include::{sourcedir}/HQLTest.java[tags=hql-api-stream-example]
Just like with `ScrollableResults`, you should always close a Hibernate `Stream` either explicitly or using a https://docs.oracle.com/javase/tutorial/essential/exceptions/tryResourceClose.html[try-with-resources] block.
====
[[jpql-api-stream]]
==== Query streaming
Since version 2.2, the JPA `Query` interface offers support for returning a `Stream` via the `getResultStream` method.
Just like the `scroll` method, you can use a try-with-resources block to close the `Stream`
prior to closing the currently running Persistence Context.
Since Hibernate 5.4, the `Stream` is also closed when calling a terminal operation,
as illustrated by the following example.
[[jpql-api-stream-terminal-operation]]
====
[source, JAVA, indent=0]
----
include::{sourcedir}/HQLTest.java[tags=jpql-api-stream-terminal-operation]
----
====
The `Stream` is closed automatically after calling the `collect` method,
since there is no reason to keep the underlying JDBC `ResultSet` open
if the `Stream` cannot be reused.
[[hql-case-sensitivity]]
=== Case Sensitivity

View File

@ -10,7 +10,6 @@ import java.math.BigDecimal;
import java.sql.Timestamp;
import java.time.LocalDateTime;
import java.time.ZoneOffset;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
@ -43,7 +42,6 @@ import org.hibernate.userguide.model.PhoneType;
import org.hibernate.userguide.model.WireTransferPayment;
import org.hibernate.testing.DialectChecks;
import org.hibernate.testing.FailureExpected;
import org.hibernate.testing.RequiresDialect;
import org.hibernate.testing.RequiresDialectFeature;
import org.hibernate.testing.SkipForDialect;
@ -673,6 +671,38 @@ public class HQLTest extends BaseEntityManagerFunctionalTestCase {
});
}
@Test
public void test_jpql_api_stream_example() {
doInJPA( this::entityManagerFactory, entityManager -> {
//tag::jpql-api-stream-example[]
try(Stream<Person> personStream = entityManager.createQuery(
"select p " +
"from Person p " +
"where p.name like :name", Person.class )
.setParameter( "name", "J%" )
.getResultStream()) {
List<Person> persons = personStream
.skip( 5 )
.limit( 5 )
.collect( Collectors.toList() );
}
//end::jpql-api-stream-example[]
// tag::jpql-api-stream-terminal-operation[]
List<Person> persons = entityManager.createQuery(
"select p " +
"from Person p " +
"where p.name like :name", Person.class )
.setParameter( "name", "J%" )
.getResultStream()
.skip( 5 )
.limit( 5 )
.collect( Collectors.toList() );
//end::jpql-api-stream-terminal-operation[]
});
}
@Test
public void test_jpql_api_single_result_example() {
doInJPA( this::entityManagerFactory, entityManager -> {

View File

@ -691,7 +691,7 @@ public class OracleDialect extends Dialect {
@Override
public String getQuerySequencesString() {
return "select * from all_sequences";
return "select * from user_sequences";
}
public SequenceInformationExtractor getSequenceInformationExtractor() {

View File

@ -46,9 +46,9 @@ public class ResultSetReturnImpl implements ResultSetReturn {
@Override
public ResultSet extract(PreparedStatement statement) {
// IMPL NOTE : SQL logged by caller
long executeStart = 0;
long executeStartNanos = 0;
if ( this.sqlStatementLogger.getLogSlowQuery() > 0 ) {
executeStart = System.currentTimeMillis();
executeStartNanos = System.nanoTime();
}
try {
final ResultSet rs;
@ -58,7 +58,7 @@ public class ResultSetReturnImpl implements ResultSetReturn {
}
finally {
jdbcExecuteStatementEnd();
sqlStatementLogger.logSlowQuery( statement, executeStart );
sqlStatementLogger.logSlowQuery( statement, executeStartNanos );
}
postExtract( rs, statement );
return rs;
@ -79,9 +79,9 @@ public class ResultSetReturnImpl implements ResultSetReturn {
@Override
public ResultSet extract(CallableStatement callableStatement) {
// IMPL NOTE : SQL logged by caller
long executeStart = 0;
long executeStartNanos = 0;
if ( this.sqlStatementLogger.getLogSlowQuery() > 0 ) {
executeStart = System.currentTimeMillis();
executeStartNanos = System.nanoTime();
}
try {
final ResultSet rs;
@ -91,7 +91,7 @@ public class ResultSetReturnImpl implements ResultSetReturn {
}
finally {
jdbcExecuteStatementEnd();
sqlStatementLogger.logSlowQuery( callableStatement, executeStart );
sqlStatementLogger.logSlowQuery( callableStatement, executeStartNanos );
}
postExtract( rs, callableStatement );
return rs;
@ -104,9 +104,9 @@ public class ResultSetReturnImpl implements ResultSetReturn {
@Override
public ResultSet extract(Statement statement, String sql) {
sqlStatementLogger.logStatement( sql );
long executeStart = 0;
long executeStartNanos = 0;
if ( this.sqlStatementLogger.getLogSlowQuery() > 0 ) {
executeStart = System.currentTimeMillis();
executeStartNanos = System.nanoTime();
}
try {
final ResultSet rs;
@ -116,7 +116,7 @@ public class ResultSetReturnImpl implements ResultSetReturn {
}
finally {
jdbcExecuteStatementEnd();
sqlStatementLogger.logSlowQuery( sql, executeStart );
sqlStatementLogger.logSlowQuery( sql, executeStartNanos );
}
postExtract( rs, statement );
return rs;
@ -129,9 +129,9 @@ public class ResultSetReturnImpl implements ResultSetReturn {
@Override
public ResultSet execute(PreparedStatement statement) {
// sql logged by StatementPreparerImpl
long executeStart = 0;
long executeStartNanos = 0;
if ( this.sqlStatementLogger.getLogSlowQuery() > 0 ) {
executeStart = System.currentTimeMillis();
executeStartNanos = System.nanoTime();
}
try {
final ResultSet rs;
@ -146,7 +146,7 @@ public class ResultSetReturnImpl implements ResultSetReturn {
}
finally {
jdbcExecuteStatementEnd();
sqlStatementLogger.logSlowQuery( statement, executeStart );
sqlStatementLogger.logSlowQuery( statement, executeStartNanos );
}
postExtract( rs, statement );
return rs;
@ -159,9 +159,9 @@ public class ResultSetReturnImpl implements ResultSetReturn {
@Override
public ResultSet execute(Statement statement, String sql) {
sqlStatementLogger.logStatement( sql );
long executeStart = 0;
long executeStartNanos = 0;
if ( this.sqlStatementLogger.getLogSlowQuery() > 0 ) {
executeStart = System.currentTimeMillis();
executeStartNanos = System.nanoTime();
}
try {
final ResultSet rs;
@ -176,7 +176,7 @@ public class ResultSetReturnImpl implements ResultSetReturn {
}
finally {
jdbcExecuteStatementEnd();
sqlStatementLogger.logSlowQuery( statement, executeStart );
sqlStatementLogger.logSlowQuery( statement, executeStartNanos );
}
postExtract( rs, statement );
return rs;
@ -188,9 +188,9 @@ public class ResultSetReturnImpl implements ResultSetReturn {
@Override
public int executeUpdate(PreparedStatement statement) {
long executeStart = 0;
long executeStartNanos = 0;
if ( this.sqlStatementLogger.getLogSlowQuery() > 0 ) {
executeStart = System.currentTimeMillis();
executeStartNanos = System.nanoTime();
}
try {
jdbcExecuteStatementStart();
@ -201,16 +201,16 @@ public class ResultSetReturnImpl implements ResultSetReturn {
}
finally {
jdbcExecuteStatementEnd();
sqlStatementLogger.logSlowQuery( statement, executeStart );
sqlStatementLogger.logSlowQuery( statement, executeStartNanos );
}
}
@Override
public int executeUpdate(Statement statement, String sql) {
sqlStatementLogger.logStatement( sql );
long executeStart = 0;
long executeStartNanos = 0;
if ( this.sqlStatementLogger.getLogSlowQuery() > 0 ) {
executeStart = System.currentTimeMillis();
executeStartNanos = System.nanoTime();
}
try {
jdbcExecuteStatementStart();
@ -221,7 +221,7 @@ public class ResultSetReturnImpl implements ResultSetReturn {
}
finally {
jdbcExecuteStatementEnd();
sqlStatementLogger.logSlowQuery( statement, executeStart );
sqlStatementLogger.logSlowQuery( statement, executeStartNanos );
}
}

View File

@ -7,6 +7,7 @@
package org.hibernate.engine.jdbc.spi;
import java.sql.Statement;
import java.util.concurrent.TimeUnit;
import org.hibernate.engine.jdbc.internal.FormatStyle;
import org.hibernate.engine.jdbc.internal.Formatter;
@ -134,34 +135,34 @@ public class SqlStatementLogger {
* Log a slow SQL query
*
* @param statement SQL statement.
* @param startTime Start time in milliseconds.
* @param startTimeNanos Start time in nanoseconds.
*/
public void logSlowQuery(Statement statement, long startTime) {
public void logSlowQuery(Statement statement, long startTimeNanos) {
if ( logSlowQuery < 1 ) {
return;
}
logSlowQuery( statement.toString(), startTime );
logSlowQuery( statement.toString(), startTimeNanos );
}
/**
* Log a slow SQL query
*
* @param sql The SQL query.
* @param startTime Start time in milliseconds.
* @param startTimeNanos Start time in nanoseconds.
*/
@AllowSysOut
public void logSlowQuery(String sql, long startTime) {
public void logSlowQuery(String sql, long startTimeNanos) {
if ( logSlowQuery < 1 ) {
return;
}
assert startTime > 0 : "startTime is invalid!";
if ( startTimeNanos <= 0 ) {
throw new IllegalArgumentException( "startTimeNanos [" + startTimeNanos + "] should be greater than 0!" );
}
long spent = System.currentTimeMillis() - startTime;
long queryExecutionMillis = TimeUnit.NANOSECONDS.toMillis( System.nanoTime() - startTimeNanos );
assert spent >= 0 : "startTime is invalid!";
if ( spent > logSlowQuery ) {
String logData = "SlowQuery: " + spent + " milliseconds. SQL: '" + sql + "'";
if ( queryExecutionMillis > logSlowQuery ) {
String logData = "SlowQuery: " + queryExecutionMillis + " milliseconds. SQL: '" + sql + "'";
LOG_SLOW.info( logData );
if ( logToStdout ) {
System.out.println( logData );

View File

@ -979,7 +979,7 @@ public class SessionImpl
}
@Override
public final Object internalLoad(
public Object internalLoad(
String entityName,
Object id,
boolean eager,

View File

@ -347,6 +347,25 @@ public final class ReflectHelper {
}
public static <T> Constructor<T> getConstructor(
Class<T> clazz,
Class... constructorArgs) {
Constructor<T> constructor = null;
try {
constructor = clazz.getDeclaredConstructor( constructorArgs );
try {
ReflectHelper.ensureAccessibility( constructor );
}
catch ( SecurityException e ) {
constructor = null;
}
}
catch ( NoSuchMethodException ignore ) {
}
return constructor;
}
public static Method getMethod(Class clazz, Method method) {
try {
return clazz.getMethod( method.getName(), method.getParameterTypes() );
@ -356,6 +375,15 @@ public final class ReflectHelper {
}
}
public static Method getMethod(Class clazz, String methodName, Class... paramTypes) {
try {
return clazz.getMethod( methodName, paramTypes );
}
catch (Exception e) {
return null;
}
}
public static Field findField(Class containerClass, String propertyName) {
if ( containerClass == null ) {
throw new IllegalArgumentException( "Class on which to find field [" + propertyName + "] cannot be null" );

View File

@ -1,70 +0,0 @@
/*
* 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.internal.util.collections;
import java.util.function.Consumer;
import java.util.function.Function;
/**
* @author Steve Ebersole
*/
public class SingletonStack<T> implements Stack<T> {
private final T instance;
public SingletonStack(T instance) {
this.instance = instance;
}
@Override
public void push(T newCurrent) {
throw new UnsupportedOperationException( "Cannot push to a singleton Stack" );
}
@Override
public T pop() {
throw new UnsupportedOperationException( "Cannot pop from a singleton Stack" );
}
@Override
public T getCurrent() {
return instance;
}
@Override
public T getPrevious() {
return null;
}
@Override
public int depth() {
return 1;
}
@Override
public boolean isEmpty() {
return false;
}
@Override
public void clear() {
}
@Override
public void visitRootFirst(Consumer<T> action) {
action.accept( instance );
}
@Override
public void visitCurrentFirst(Consumer<T> action) {
action.accept( instance );
}
@Override
public <X> X findCurrentFirst(Function<T, X> action) {
return action.apply( instance );
}
}

View File

@ -32,11 +32,6 @@ public interface Stack<T> {
*/
T getCurrent();
/**
* The element previously at the top of the stack before the current one
*/
T getPrevious();
/**
* How many elements are currently on the stack?
*/
@ -57,11 +52,6 @@ public interface Stack<T> {
*/
void visitRootFirst(Consumer<T> action);
/**
* Visit all elements in the stack, starting with the current and working back
*/
void visitCurrentFirst(Consumer<T> action);
/**
* Find an element on the stack and return a value. The first non-null element
* returned from `action` stops the iteration and is returned from here

View File

@ -17,13 +17,13 @@ import java.util.function.Function;
*
* @author Steve Ebersole
*/
public class StandardStack<T> implements Stack<T> {
public final class StandardStack<T> implements Stack<T> {
@SuppressWarnings("unchecked")
private final T nullMarker = (T) new Object();
private T current;
private LinkedList<T> internalStack;
private final LinkedList<T> internalStack = new LinkedList<>();
public StandardStack() {
}
@ -39,9 +39,6 @@ public class StandardStack<T> implements Stack<T> {
}
if ( current != null ) {
if ( internalStack == null ) {
internalStack = new LinkedList<>();
}
internalStack.addFirst( current );
}
@ -51,7 +48,7 @@ public class StandardStack<T> implements Stack<T> {
@Override
public T pop() {
final T popped = this.current;
if ( internalStack == null || internalStack.isEmpty() ) {
if ( internalStack.isEmpty() ) {
this.current = null;
}
else {
@ -66,23 +63,12 @@ public class StandardStack<T> implements Stack<T> {
return current == nullMarker ? null : current;
}
@Override
public T getPrevious() {
if ( current != null && internalStack != null ) {
final T previous = internalStack.getFirst();
return previous == nullMarker ? null : previous;
}
// otherwise...
return null;
}
@Override
public int depth() {
if ( current == null ) {
return 0;
}
else if ( internalStack == null || internalStack.isEmpty() ) {
else if ( internalStack.isEmpty() ) {
return 1;
}
else {
@ -98,34 +84,20 @@ public class StandardStack<T> implements Stack<T> {
@Override
public void clear() {
current = null;
if ( internalStack != null ) {
internalStack.clear();
}
internalStack.clear();
}
@Override
public void visitRootFirst(Consumer<T> action) {
if ( internalStack != null ) {
final int stackSize = internalStack.size();
for ( int i = stackSize - 1; i >= 0; i-- ) {
action.accept( internalStack.get( i ) );
}
final int stackSize = internalStack.size();
for ( int i = stackSize - 1; i >= 0; i-- ) {
action.accept( internalStack.get( i ) );
}
if ( current != null ) {
action.accept( current );
}
}
@Override
public void visitCurrentFirst(Consumer<T> action) {
if ( current != null ) {
action.accept( current );
if ( internalStack != null ) {
internalStack.forEach( action );
}
}
}
@Override
public <X> X findCurrentFirst(Function<T, X> function) {
if ( current != null ) {
@ -137,12 +109,10 @@ public class StandardStack<T> implements Stack<T> {
}
}
if ( internalStack != null ) {
for ( T t : internalStack ) {
final X result = function.apply( t );
if ( result != null ) {
return result;
}
for ( T t : internalStack ) {
final X result = function.apply( t );
if ( result != null ) {
return result;
}
}
}

View File

@ -182,7 +182,7 @@ public class EntityManagerFactoryBuilderImpl implements EntityManagerFactoryBuil
ClassLoaderService providedClassLoaderService ) {
this( persistenceUnit, integrationSettings, null, providedClassLoaderService);
}
private EntityManagerFactoryBuilderImpl(
PersistenceUnitDescriptor persistenceUnit,
Map integrationSettings,
@ -194,11 +194,23 @@ public class EntityManagerFactoryBuilderImpl implements EntityManagerFactoryBuil
this.persistenceUnit = persistenceUnit;
if ( integrationSettings == null ) {
integrationSettings = Collections.emptyMap();
integrationSettings = new HashMap();
}
Map mergedIntegrationSettings = null;
Properties properties = persistenceUnit.getProperties();
if ( properties != null ) {
// original integratin setting entries take precedence
mergedIntegrationSettings = new HashMap( properties );
mergedIntegrationSettings.putAll( integrationSettings );
}
// Build the boot-strap service registry, which mainly handles class loader interactions
final BootstrapServiceRegistry bsr = buildBootstrapServiceRegistry( integrationSettings, providedClassLoader, providedClassLoaderService);
final BootstrapServiceRegistry bsr = buildBootstrapServiceRegistry(
mergedIntegrationSettings != null ? mergedIntegrationSettings : integrationSettings,
providedClassLoader,
providedClassLoaderService
);
// merge configuration sources and build the "standard" service registry
final StandardServiceRegistryBuilder ssrBuilder = StandardServiceRegistryBuilder.forJpa( bsr );

View File

@ -151,7 +151,7 @@ public abstract class Constraint implements RelationalModel, Exportable, Seriali
public Column getColumn(int i) {
return columns.get( i );
}
public Iterator<Column> getColumnIterator() {
return columns.iterator();
}

View File

@ -11,6 +11,7 @@ import java.time.Instant;
import java.time.LocalDateTime;
import java.time.OffsetDateTime;
import java.time.ZonedDateTime;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Calendar;
import java.util.Collection;
@ -70,6 +71,7 @@ import org.hibernate.query.spi.QueryParameterBinding;
import org.hibernate.query.spi.QueryParameterBindings;
import org.hibernate.query.spi.QueryParameterImplementor;
import org.hibernate.query.spi.ScrollableResultsImplementor;
import org.hibernate.query.spi.StreamDecorator;
import org.hibernate.transform.ResultTransformer;
import org.jboss.logging.Logger;
@ -1427,8 +1429,10 @@ public abstract class AbstractProducedQuery<R> implements QueryImplementor<R> {
final ScrollableResultsIterator<R> iterator = new ScrollableResultsIterator<>( scrollableResults );
final Spliterator<R> spliterator = Spliterators.spliteratorUnknownSize( iterator, Spliterator.NONNULL );
final Stream<R> stream = StreamSupport.stream( spliterator, false );
stream.onClose( scrollableResults::close );
final Stream<R> stream = new StreamDecorator(
StreamSupport.stream( spliterator, false ),
scrollableResults::close
);
return stream;
}

View File

@ -0,0 +1,318 @@
/*
* 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.query.spi;
import java.util.DoubleSummaryStatistics;
import java.util.OptionalDouble;
import java.util.PrimitiveIterator;
import java.util.Spliterator;
import java.util.function.BiConsumer;
import java.util.function.DoubleBinaryOperator;
import java.util.function.DoubleConsumer;
import java.util.function.DoubleFunction;
import java.util.function.DoublePredicate;
import java.util.function.DoubleToIntFunction;
import java.util.function.DoubleToLongFunction;
import java.util.function.DoubleUnaryOperator;
import java.util.function.ObjDoubleConsumer;
import java.util.function.Supplier;
import java.util.stream.DoubleStream;
import java.util.stream.IntStream;
import java.util.stream.LongStream;
import java.util.stream.Stream;
import org.hibernate.Incubating;
/**
* The {@link DoubleStreamDecorator} wraps a Java {@link DoubleStream} and registers a {@code closeHandler}
* which is passed further to any resulting {@link Stream}.
* <p>
* The goal of the {@link DoubleStreamDecorator} is to close the underlying {@link DoubleStream} upon
* calling a terminal operation.
*
* @author Vlad Mihalcea
* @since 5.4
*/
@Incubating
public class DoubleStreamDecorator implements DoubleStream {
private final DoubleStream delegate;
private Runnable closeHandler;
public DoubleStreamDecorator(
DoubleStream delegate,
Runnable closeHandler) {
this.delegate = delegate;
this.closeHandler = closeHandler;
this.delegate.onClose( closeHandler );
}
@Override
public DoubleStream filter(DoublePredicate predicate) {
return new DoubleStreamDecorator(
delegate.filter( predicate ),
closeHandler
);
}
@Override
public DoubleStream map(DoubleUnaryOperator mapper) {
return new DoubleStreamDecorator(
delegate.map( mapper ),
closeHandler
);
}
@Override
public <U> Stream<U> mapToObj(DoubleFunction<? extends U> mapper) {
return new StreamDecorator<>(
delegate.mapToObj( mapper ),
closeHandler
);
}
@Override
public IntStream mapToInt(DoubleToIntFunction mapper) {
return new IntStreamDecorator(
delegate.mapToInt( mapper ),
closeHandler
);
}
@Override
public LongStream mapToLong(DoubleToLongFunction mapper) {
return new LongStreamDecorator(
delegate.mapToLong( mapper ),
closeHandler
);
}
@Override
public DoubleStream flatMap(DoubleFunction<? extends DoubleStream> mapper) {
return new DoubleStreamDecorator(
delegate.flatMap( mapper ),
closeHandler
);
}
@Override
public DoubleStream distinct() {
return new DoubleStreamDecorator(
delegate.distinct(),
closeHandler
);
}
@Override
public DoubleStream sorted() {
return new DoubleStreamDecorator(
delegate.sorted(),
closeHandler
);
}
@Override
public DoubleStream peek(DoubleConsumer action) {
return new DoubleStreamDecorator(
delegate.peek( action ),
closeHandler
);
}
@Override
public DoubleStream limit(long maxSize) {
return new DoubleStreamDecorator(
delegate.limit( maxSize ),
closeHandler
);
}
@Override
public DoubleStream skip(long n) {
return new DoubleStreamDecorator(
delegate.skip( n ),
closeHandler
);
}
@Override
public void forEach(DoubleConsumer action) {
delegate.forEach( action );
close();
}
@Override
public void forEachOrdered(DoubleConsumer action) {
delegate.forEachOrdered( action );
close();
}
@Override
public double[] toArray() {
double[] result = delegate.toArray();
close();
return result;
}
@Override
public double reduce(double identity, DoubleBinaryOperator op) {
double result = delegate.reduce( identity, op );
close();
return result;
}
@Override
public OptionalDouble reduce(DoubleBinaryOperator op) {
OptionalDouble result = delegate.reduce( op );
close();
return result;
}
@Override
public <R> R collect(
Supplier<R> supplier, ObjDoubleConsumer<R> accumulator, BiConsumer<R, R> combiner) {
R result = delegate.collect( supplier, accumulator, combiner );
close();
return result;
}
@Override
public double sum() {
double result = delegate.sum();
close();
return result;
}
@Override
public OptionalDouble min() {
OptionalDouble result = delegate.min();
close();
return result;
}
@Override
public OptionalDouble max() {
OptionalDouble result = delegate.max();
close();
return result;
}
@Override
public long count() {
long result = delegate.count();
close();
return result;
}
@Override
public OptionalDouble average() {
OptionalDouble result = delegate.average();
close();
return result;
}
@Override
public DoubleSummaryStatistics summaryStatistics() {
DoubleSummaryStatistics result = delegate.summaryStatistics();
close();
return result;
}
@Override
public boolean anyMatch(DoublePredicate predicate) {
boolean result = delegate.anyMatch( predicate );
close();
return result;
}
@Override
public boolean allMatch(DoublePredicate predicate) {
boolean result = delegate.allMatch( predicate );
close();
return result;
}
@Override
public boolean noneMatch(DoublePredicate predicate) {
boolean result = delegate.noneMatch( predicate );
close();
return result;
}
@Override
public OptionalDouble findFirst() {
OptionalDouble result = delegate.findFirst();
close();
return result;
}
@Override
public OptionalDouble findAny() {
OptionalDouble result = delegate.findAny();
close();
return result;
}
@Override
public Stream<Double> boxed() {
return new StreamDecorator<>(
delegate.boxed(),
closeHandler
);
}
@Override
public DoubleStream sequential() {
return new DoubleStreamDecorator(
delegate.sequential(),
closeHandler
);
}
@Override
public DoubleStream parallel() {
return new DoubleStreamDecorator(
delegate.parallel(),
closeHandler
);
}
@Override
public DoubleStream unordered() {
return new DoubleStreamDecorator(
delegate.unordered(),
closeHandler
);
}
@Override
public DoubleStream onClose(Runnable closeHandler) {
this.closeHandler = closeHandler;
return this;
}
@Override
public void close() {
delegate.close();
}
@Override
public PrimitiveIterator.OfDouble iterator() {
return delegate.iterator();
}
@Override
public Spliterator.OfDouble spliterator() {
return delegate.spliterator();
}
@Override
public boolean isParallel() {
return delegate.isParallel();
}
}

View File

@ -0,0 +1,333 @@
/*
* 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.query.spi;
import java.util.IntSummaryStatistics;
import java.util.OptionalDouble;
import java.util.OptionalInt;
import java.util.PrimitiveIterator;
import java.util.Spliterator;
import java.util.function.BiConsumer;
import java.util.function.IntBinaryOperator;
import java.util.function.IntConsumer;
import java.util.function.IntFunction;
import java.util.function.IntPredicate;
import java.util.function.IntToDoubleFunction;
import java.util.function.IntToLongFunction;
import java.util.function.IntUnaryOperator;
import java.util.function.ObjIntConsumer;
import java.util.function.Supplier;
import java.util.stream.DoubleStream;
import java.util.stream.IntStream;
import java.util.stream.LongStream;
import java.util.stream.Stream;
import org.hibernate.Incubating;
/**
* The {@link IntStreamDecorator} wraps a Java {@link IntStream} and registers a {@code closeHandler}
* which is passed further to any resulting {@link Stream}.
* <p>
* The goal of the {@link IntStreamDecorator} is to close the underlying {@link IntStream} upon
* calling a terminal operation.
*
* @author Vlad Mihalcea
* @since 5.4
*/
@Incubating
public class IntStreamDecorator implements IntStream {
private final IntStream delegate;
private Runnable closeHandler;
public IntStreamDecorator(
IntStream delegate,
Runnable closeHandler) {
this.delegate = delegate;
this.closeHandler = closeHandler;
this.delegate.onClose( closeHandler );
}
@Override
public IntStream filter(IntPredicate predicate) {
return new IntStreamDecorator(
delegate.filter( predicate ),
closeHandler
);
}
@Override
public IntStream map(IntUnaryOperator mapper) {
return new IntStreamDecorator(
delegate.map( mapper ),
closeHandler
);
}
@Override
public <U> Stream<U> mapToObj(IntFunction<? extends U> mapper) {
return new StreamDecorator<>(
delegate.mapToObj( mapper ),
closeHandler
);
}
@Override
public LongStream mapToLong(IntToLongFunction mapper) {
return new LongStreamDecorator(
delegate.mapToLong( mapper ),
closeHandler
);
}
@Override
public DoubleStream mapToDouble(IntToDoubleFunction mapper) {
return new DoubleStreamDecorator(
delegate.mapToDouble( mapper ),
closeHandler
);
}
@Override
public IntStream flatMap(IntFunction<? extends IntStream> mapper) {
return new IntStreamDecorator(
delegate.flatMap( mapper ),
closeHandler
);
}
@Override
public IntStream distinct() {
return new IntStreamDecorator(
delegate.distinct(),
closeHandler
);
}
@Override
public IntStream sorted() {
return new IntStreamDecorator(
delegate.sorted(),
closeHandler
);
}
@Override
public IntStream peek(IntConsumer action) {
return new IntStreamDecorator(
delegate.peek( action ),
closeHandler
);
}
@Override
public IntStream limit(long maxSize) {
return new IntStreamDecorator(
delegate.limit( maxSize ),
closeHandler
);
}
@Override
public IntStream skip(long n) {
return new IntStreamDecorator(
delegate.skip( n ),
closeHandler
);
}
@Override
public void forEach(IntConsumer action) {
delegate.forEach( action );
close();
}
@Override
public void forEachOrdered(IntConsumer action) {
delegate.forEachOrdered( action );
close();
}
@Override
public int[] toArray() {
int[] result = delegate.toArray();
close();
return result;
}
@Override
public int reduce(int identity, IntBinaryOperator op) {
int result = delegate.reduce( identity, op );
close();
return result;
}
@Override
public OptionalInt reduce(IntBinaryOperator op) {
OptionalInt result = delegate.reduce( op );
close();
return result;
}
@Override
public <R> R collect(
Supplier<R> supplier, ObjIntConsumer<R> accumulator, BiConsumer<R, R> combiner) {
R result = delegate.collect( supplier, accumulator, combiner );
close();
return result;
}
@Override
public int sum() {
int result = delegate.sum();
close();
return result;
}
@Override
public OptionalInt min() {
OptionalInt result = delegate.min();
close();
return result;
}
@Override
public OptionalInt max() {
OptionalInt result = delegate.max();
close();
return result;
}
@Override
public long count() {
long result = delegate.count();
close();
return result;
}
@Override
public OptionalDouble average() {
OptionalDouble result = delegate.average();
close();
return result;
}
@Override
public IntSummaryStatistics summaryStatistics() {
IntSummaryStatistics result = delegate.summaryStatistics();
close();
return result;
}
@Override
public boolean anyMatch(IntPredicate predicate) {
boolean result = delegate.anyMatch( predicate );
close();
return result;
}
@Override
public boolean allMatch(IntPredicate predicate) {
boolean result = delegate.allMatch( predicate );
close();
return result;
}
@Override
public boolean noneMatch(IntPredicate predicate) {
boolean result = delegate.noneMatch( predicate );
close();
return result;
}
@Override
public OptionalInt findFirst() {
OptionalInt result = delegate.findFirst();
close();
return result;
}
@Override
public OptionalInt findAny() {
OptionalInt result = delegate.findAny();
close();
return result;
}
@Override
public LongStream asLongStream() {
LongStream result = delegate.asLongStream();
close();
return result;
}
@Override
public DoubleStream asDoubleStream() {
DoubleStream result = delegate.asDoubleStream();
close();
return result;
}
@Override
public Stream<Integer> boxed() {
return new StreamDecorator<>(
delegate.boxed(),
closeHandler
);
}
@Override
public IntStream sequential() {
return new IntStreamDecorator(
delegate.sequential(),
closeHandler
);
}
@Override
public IntStream parallel() {
return new IntStreamDecorator(
delegate.parallel(),
closeHandler
);
}
@Override
public IntStream unordered() {
return new IntStreamDecorator(
delegate.unordered(),
closeHandler
);
}
@Override
public IntStream onClose(Runnable closeHandler) {
this.closeHandler = closeHandler;
return this;
}
@Override
public void close() {
delegate.close();
}
@Override
public PrimitiveIterator.OfInt iterator() {
return delegate.iterator();
}
@Override
public Spliterator.OfInt spliterator() {
return delegate.spliterator();
}
@Override
public boolean isParallel() {
return delegate.isParallel();
}
}

View File

@ -0,0 +1,326 @@
/*
* 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.query.spi;
import java.util.LongSummaryStatistics;
import java.util.OptionalDouble;
import java.util.OptionalLong;
import java.util.PrimitiveIterator;
import java.util.Spliterator;
import java.util.function.BiConsumer;
import java.util.function.LongBinaryOperator;
import java.util.function.LongConsumer;
import java.util.function.LongFunction;
import java.util.function.LongPredicate;
import java.util.function.LongToDoubleFunction;
import java.util.function.LongToIntFunction;
import java.util.function.LongUnaryOperator;
import java.util.function.ObjLongConsumer;
import java.util.function.Supplier;
import java.util.stream.DoubleStream;
import java.util.stream.IntStream;
import java.util.stream.LongStream;
import java.util.stream.Stream;
import org.hibernate.Incubating;
/**
* The {@link LongStreamDecorator} wraps a Java {@link LongStream} and registers a {@code closeHandler}
* which is passed further to any resulting {@link Stream}.
*
* The goal of the {@link LongStreamDecorator} is to close the underlying {@link LongStream} upon
* calling a terminal operation.
*
* @author Vlad Mihalcea
* @since 5.4
*/
@Incubating
public class LongStreamDecorator implements LongStream {
private final LongStream delegate;
private Runnable closeHandler;
public LongStreamDecorator(
LongStream delegate,
Runnable closeHandler) {
this.delegate = delegate;
this.closeHandler = closeHandler;
this.delegate.onClose( closeHandler );
}
@Override
public LongStream filter(LongPredicate predicate) {
return new LongStreamDecorator(
delegate.filter( predicate ),
closeHandler
);
}
@Override
public LongStream map(LongUnaryOperator mapper) {
return new LongStreamDecorator(
delegate.map( mapper ),
closeHandler
);
}
@Override
public <U> Stream<U> mapToObj(LongFunction<? extends U> mapper) {
return new StreamDecorator<>(
delegate.mapToObj( mapper ),
closeHandler
);
}
@Override
public IntStream mapToInt(LongToIntFunction mapper) {
return new IntStreamDecorator(
delegate.mapToInt( mapper ),
closeHandler
);
}
@Override
public DoubleStream mapToDouble(LongToDoubleFunction mapper) {
return new DoubleStreamDecorator(
delegate.mapToDouble( mapper ),
closeHandler
);
}
@Override
public LongStream flatMap(LongFunction<? extends LongStream> mapper) {
return new LongStreamDecorator(
delegate.flatMap( mapper ),
closeHandler
);
}
@Override
public LongStream distinct() {
return new LongStreamDecorator(
delegate.distinct(),
closeHandler
);
}
@Override
public LongStream sorted() {
return new LongStreamDecorator(
delegate.sorted(),
closeHandler
);
}
@Override
public LongStream peek(LongConsumer action) {
return new LongStreamDecorator(
delegate.peek( action ),
closeHandler
);
}
@Override
public LongStream limit(long maxSize) {
return new LongStreamDecorator(
delegate.limit( maxSize ),
closeHandler
);
}
@Override
public LongStream skip(long n) {
return new LongStreamDecorator(
delegate.skip( n ),
closeHandler
);
}
@Override
public void forEach(LongConsumer action) {
delegate.forEach( action );
close();
}
@Override
public void forEachOrdered(LongConsumer action) {
delegate.forEachOrdered( action );
close();
}
@Override
public long[] toArray() {
long[] result = delegate.toArray();
close();
return result;
}
@Override
public long reduce(long identity, LongBinaryOperator op) {
long result = delegate.reduce( identity, op );
close();
return result;
}
@Override
public OptionalLong reduce(LongBinaryOperator op) {
OptionalLong result = delegate.reduce( op );
close();
return result;
}
@Override
public <R> R collect(
Supplier<R> supplier, ObjLongConsumer<R> accumulator, BiConsumer<R, R> combiner) {
R result = delegate.collect( supplier, accumulator, combiner );
close();
return result;
}
@Override
public long sum() {
long result = delegate.sum();
close();
return result;
}
@Override
public OptionalLong min() {
OptionalLong result = delegate.min();
close();
return result;
}
@Override
public OptionalLong max() {
OptionalLong result = delegate.max();
close();
return result;
}
@Override
public long count() {
long result = delegate.count();
close();
return result;
}
@Override
public OptionalDouble average() {
OptionalDouble result = delegate.average();
close();
return result;
}
@Override
public LongSummaryStatistics summaryStatistics() {
LongSummaryStatistics result = delegate.summaryStatistics();
close();
return result;
}
@Override
public boolean anyMatch(LongPredicate predicate) {
boolean result = delegate.anyMatch(predicate);
close();
return result;
}
@Override
public boolean allMatch(LongPredicate predicate) {
boolean result = delegate.allMatch(predicate);
close();
return result;
}
@Override
public boolean noneMatch(LongPredicate predicate) {
boolean result = delegate.noneMatch(predicate);
close();
return result;
}
@Override
public OptionalLong findFirst() {
OptionalLong result = delegate.findFirst();
close();
return result;
}
@Override
public OptionalLong findAny() {
OptionalLong result = delegate.findAny();
close();
return result;
}
@Override
public DoubleStream asDoubleStream() {
DoubleStream result = delegate.asDoubleStream();
close();
return result;
}
@Override
public Stream<Long> boxed() {
return new StreamDecorator<>(
delegate.boxed(),
closeHandler
);
}
@Override
public LongStream sequential() {
return new LongStreamDecorator(
delegate.sequential(),
closeHandler
);
}
@Override
public LongStream parallel() {
return new LongStreamDecorator(
delegate.parallel(),
closeHandler
);
}
@Override
public LongStream unordered() {
return new LongStreamDecorator(
delegate.unordered(),
closeHandler
);
}
@Override
public LongStream onClose(Runnable closeHandler) {
this.closeHandler = closeHandler;
return this;
}
@Override
public void close() {
delegate.close();
}
@Override
public PrimitiveIterator.OfLong iterator() {
return delegate.iterator();
}
@Override
public Spliterator.OfLong spliterator() {
return delegate.spliterator();
}
@Override
public boolean isParallel() {
return delegate.isParallel();
}
}

View File

@ -0,0 +1,340 @@
/*
* 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.query.spi;
import java.lang.reflect.InvocationTargetException;
import java.util.Comparator;
import java.util.Iterator;
import java.util.Optional;
import java.util.Spliterator;
import java.util.function.BiConsumer;
import java.util.function.BiFunction;
import java.util.function.BinaryOperator;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.IntFunction;
import java.util.function.Predicate;
import java.util.function.Supplier;
import java.util.function.ToDoubleFunction;
import java.util.function.ToIntFunction;
import java.util.function.ToLongFunction;
import java.util.stream.Collector;
import java.util.stream.DoubleStream;
import java.util.stream.IntStream;
import java.util.stream.LongStream;
import java.util.stream.Stream;
import org.hibernate.HibernateException;
import org.hibernate.Incubating;
import org.hibernate.internal.util.ReflectHelper;
/**
* The {@link StreamDecorator} wraps a Java {@link Stream} and registers a {@code closeHandler}
* which is passed further to any resulting {@link Stream}.
*
* The goal of the {@link StreamDecorator} is to close the underlying {@link Stream} upon
* calling a terminal operation.
*
* @author Vlad Mihalcea
* @since 5.4
*/
@Incubating
public class StreamDecorator<R> implements Stream<R> {
private final Stream<R> delegate;
private Runnable closeHandler;
public StreamDecorator(
Stream<R> delegate,
Runnable closeHandler) {
this.delegate = delegate;
this.closeHandler = closeHandler;
this.delegate.onClose( closeHandler );
}
@Override
public Stream<R> filter(Predicate<? super R> predicate) {
return new StreamDecorator<R>( delegate.filter( predicate ), closeHandler );
}
@Override
public <R1> Stream<R1> map(Function<? super R, ? extends R1> mapper) {
return new StreamDecorator<>( delegate.map( mapper ), closeHandler );
}
@Override
public IntStream mapToInt(ToIntFunction<? super R> mapper) {
return new IntStreamDecorator(
delegate.mapToInt( mapper ),
closeHandler
);
}
@Override
public LongStream mapToLong(ToLongFunction<? super R> mapper) {
return new LongStreamDecorator(
delegate.mapToLong( mapper ),
closeHandler
);
}
@Override
public DoubleStream mapToDouble(ToDoubleFunction<? super R> mapper) {
return new DoubleStreamDecorator(
delegate.mapToDouble( mapper ),
closeHandler
);
}
@Override
public <R1> Stream<R1> flatMap(Function<? super R, ? extends Stream<? extends R1>> mapper) {
return new StreamDecorator<>( delegate.flatMap( mapper ), closeHandler );
}
@Override
public IntStream flatMapToInt(Function<? super R, ? extends IntStream> mapper) {
return new IntStreamDecorator(
delegate.flatMapToInt( mapper ),
closeHandler
);
}
@Override
public LongStream flatMapToLong(Function<? super R, ? extends LongStream> mapper) {
return new LongStreamDecorator(
delegate.flatMapToLong( mapper ),
closeHandler
);
}
@Override
public DoubleStream flatMapToDouble(Function<? super R, ? extends DoubleStream> mapper) {
return new DoubleStreamDecorator(
delegate.flatMapToDouble( mapper ),
closeHandler
);
}
@Override
public Stream<R> distinct() {
return new StreamDecorator<>( delegate.distinct(), closeHandler );
}
@Override
public Stream<R> sorted() {
return new StreamDecorator<>( delegate.sorted(), closeHandler );
}
@Override
public Stream<R> sorted(Comparator<? super R> comparator) {
return new StreamDecorator<>( delegate.sorted( comparator ), closeHandler );
}
@Override
public Stream<R> peek(Consumer<? super R> action) {
return new StreamDecorator<>( delegate.peek( action ), closeHandler );
}
@Override
public Stream<R> limit(long maxSize) {
return new StreamDecorator<>( delegate.limit( maxSize ), closeHandler );
}
@Override
public Stream<R> skip(long n) {
return new StreamDecorator<>( delegate.skip( n ), closeHandler );
}
@Override
public void forEach(Consumer<? super R> action) {
delegate.forEach( action );
close();
}
@Override
public void forEachOrdered(Consumer<? super R> action) {
delegate.forEachOrdered( action );
close();
}
@Override
public Object[] toArray() {
Object[] result = delegate.toArray();
close();
return result;
}
@Override
public <A> A[] toArray(IntFunction<A[]> generator) {
A[] result = delegate.toArray( generator );
close();
return result;
}
@Override
public R reduce(R identity, BinaryOperator<R> accumulator) {
R result = delegate.reduce( identity, accumulator );
close();
return result;
}
@Override
public Optional<R> reduce(BinaryOperator<R> accumulator) {
Optional<R> result = delegate.reduce( accumulator );
close();
return result;
}
@Override
public <U> U reduce(
U identity, BiFunction<U, ? super R, U> accumulator, BinaryOperator<U> combiner) {
U result = delegate.reduce( identity, accumulator, combiner );
close();
return result;
}
@Override
public <R1> R1 collect(
Supplier<R1> supplier, BiConsumer<R1, ? super R> accumulator, BiConsumer<R1, R1> combiner) {
R1 result = delegate.collect( supplier, accumulator, combiner );
close();
return result;
}
@Override
public <R1, A> R1 collect(Collector<? super R, A, R1> collector) {
R1 result = delegate.collect( collector );
close();
return result;
}
@Override
public Optional<R> min(Comparator<? super R> comparator) {
Optional<R> result = delegate.min( comparator );
close();
return result;
}
@Override
public Optional<R> max(Comparator<? super R> comparator) {
Optional<R> result = delegate.max( comparator );
close();
return result;
}
@Override
public long count() {
long result = delegate.count();
close();
return result;
}
@Override
public boolean anyMatch(Predicate<? super R> predicate) {
boolean result = delegate.anyMatch( predicate );
close();
return result;
}
@Override
public boolean allMatch(Predicate<? super R> predicate) {
boolean result = delegate.allMatch( predicate );
close();
return result;
}
@Override
public boolean noneMatch(Predicate<? super R> predicate) {
boolean result = delegate.noneMatch( predicate );
close();
return result;
}
@Override
public Optional<R> findFirst() {
Optional<R> result = delegate.findFirst();
close();
return result;
}
@Override
public Optional<R> findAny() {
Optional<R> result = delegate.findAny();
close();
return result;
}
@Override
public Iterator<R> iterator() {
return delegate.iterator();
}
@Override
public Spliterator<R> spliterator() {
return delegate.spliterator();
}
@Override
public boolean isParallel() {
return delegate.isParallel();
}
@Override
public Stream<R> sequential() {
return new StreamDecorator<>( delegate.sequential(), closeHandler );
}
@Override
public Stream<R> parallel() {
return new StreamDecorator<>( delegate.parallel(), closeHandler );
}
@Override
public Stream<R> unordered() {
return new StreamDecorator<>( delegate.unordered(), closeHandler );
}
@Override
public Stream<R> onClose(Runnable closeHandler) {
this.closeHandler = closeHandler;
return this;
}
@Override
public void close() {
delegate.close();
}
//Methods added to JDK 9
public Stream<R> takeWhile(Predicate<? super R> predicate) {
try {
@SuppressWarnings("unchecked")
Stream<R> result = (Stream<R>)
ReflectHelper.getMethod( Stream.class, "takeWhile", Predicate.class )
.invoke( delegate, predicate );
return new StreamDecorator<>( result, closeHandler );
}
catch (IllegalAccessException | InvocationTargetException e) {
throw new HibernateException( e );
}
}
public Stream<R> dropWhile(Predicate<? super R> predicate) {
try {
@SuppressWarnings("unchecked")
Stream<R> result = (Stream<R>)
ReflectHelper.getMethod( Stream.class, "dropWhile", Predicate.class )
.invoke( delegate, predicate );
return new StreamDecorator<>( result, closeHandler );
}
catch (IllegalAccessException | InvocationTargetException e) {
throw new HibernateException( e );
}
}
}

View File

@ -0,0 +1,24 @@
/*
* 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.type.spi;
import java.util.Map;
/**
* Provide a way to customize the {@link org.hibernate.type.Type} instantiation process.
* <p/>
* If a custom {@link org.hibernate.type.Type} defines a constructor which takes the
* {@link TypeBootstrapContext} argument, Hibernate will use this instead of the
* default constructor.
*
* @author Vlad Mihalcea
*
* @since 5.4
*/
public interface TypeBootstrapContext {
Map<String, Object> getConfigurationSettings();
}

View File

@ -80,7 +80,7 @@ public abstract class BaseEntityManagerFunctionalTestCase extends BaseUnitTestCa
afterEntityManagerFactoryBuilt();
}
private PersistenceUnitDescriptor buildPersistenceUnitDescriptor() {
protected PersistenceUnitDescriptor buildPersistenceUnitDescriptor() {
return new TestingPersistenceUnitDescriptorImpl( getClass().getSimpleName() );
}

View File

@ -0,0 +1,57 @@
/*
* 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.jpa.test.integrationprovider;
import java.util.List;
import java.util.Properties;
import org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl;
import org.hibernate.jpa.boot.spi.PersistenceUnitDescriptor;
import org.hibernate.jpa.test.BaseEntityManagerFunctionalTestCase;
import org.hibernate.testing.TestForIssue;
import org.junit.Test;
import static org.hibernate.testing.transaction.TransactionUtil.doInJPA;
/**
* @author Vlad Mihalcea
*/
@TestForIssue(jiraKey = "HHHH-13853")
public class IntegrationProviderSettingByClassUsingPropertiesTest extends BaseEntityManagerFunctionalTestCase {
@Override
protected Class<?>[] getAnnotatedClasses() {
return new Class<?>[] {
Person.class
};
}
@Test
public void test() {
doInJPA( this::entityManagerFactory, entityManager -> {
List<PersonDto> dtos = entityManager.createQuery(
"select new PersonDto(id, name) " +
"from Person", PersonDto.class )
.getResultList();
} );
}
protected PersistenceUnitDescriptor buildPersistenceUnitDescriptor() {
return new TestingPersistenceUnitDescriptorImpl( getClass().getSimpleName() ) {
@Override
public Properties getProperties() {
Properties properties = new Properties();
properties.put(
EntityManagerFactoryBuilderImpl.INTEGRATOR_PROVIDER,
DtoIntegratorProvider.class.getName()
);
return properties;
}
};
}
}

View File

@ -154,10 +154,6 @@ public class JpaSchemaGeneratorTest extends BaseEntityManagerFunctionalTestCase
}
}
private PersistenceUnitDescriptor buildPersistenceUnitDescriptor() {
return new TestingPersistenceUnitDescriptorImpl( getClass().getSimpleName() );
}
/* Disable hibernate schema export */
@Override
protected boolean createSchema() {

View File

@ -0,0 +1,297 @@
/*
* 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.test.annotations.onetoone;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.MapsId;
import javax.persistence.OneToOne;
import javax.persistence.Table;
import org.hibernate.annotations.NotFound;
import org.hibernate.annotations.NotFoundAction;
import org.hibernate.testing.TestForIssue;
import org.hibernate.testing.junit4.BaseNonConfigCoreFunctionalTestCase;
import org.junit.After;
import org.junit.Test;
import static org.hibernate.testing.transaction.TransactionUtil.doInHibernate;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
@TestForIssue( jiraKey = "HHH-13875")
public class OptionalOneToOneMapsIdQueryTest extends BaseNonConfigCoreFunctionalTestCase {
@Test
public void testOneToOneWithIdNamedId() {
// Test with associated entity having ID named "id"
doInHibernate( this::sessionFactory, session -> {
BarWithIdNamedId bar = new BarWithIdNamedId();
bar.id = 1L;
bar.longValue = 2L;
FooHasBarWithIdNamedId foo = new FooHasBarWithIdNamedId();
foo.id = 1L;
foo.bar = bar;
session.persist( bar );
session.persist( foo );
});
doInHibernate( this::sessionFactory, session -> {
final FooHasBarWithIdNamedId foo = session.createQuery(
"from FooHasBarWithIdNamedId where bar.id = ?1",
FooHasBarWithIdNamedId.class
).setParameter( 1, 1L )
.uniqueResult();
assertNotNull( foo );
assertNotNull( foo.bar );
});
doInHibernate( this::sessionFactory, session -> {
final FooHasBarWithIdNamedId foo = session.get( FooHasBarWithIdNamedId.class, 1L );
session.delete( foo.bar );
foo.bar = null;
});
doInHibernate( this::sessionFactory, session -> {
final FooHasBarWithIdNamedId foo = session.createQuery(
"from FooHasBarWithIdNamedId where bar.id = ?1",
FooHasBarWithIdNamedId.class
).setParameter( 1, 1L )
.uniqueResult();
assertNull( foo );
});
}
@Test
public void testOneToOneWithNoIdOrPropNamedId() {
// Test with associated entity having ID not named "id", and with no property named "id"
doInHibernate( this::sessionFactory, session -> {
BarWithNoIdOrPropNamedId bar = new BarWithNoIdOrPropNamedId();
bar.barId = 1L;
bar.longValue = 2L;
FooHasBarWithNoIdOrPropNamedId foo = new FooHasBarWithNoIdOrPropNamedId();
foo.id = 1L;
foo.bar = bar;
session.persist( bar );
session.persist( foo );
});
doInHibernate( this::sessionFactory, session -> {
final FooHasBarWithNoIdOrPropNamedId foo = session.createQuery(
"from FooHasBarWithNoIdOrPropNamedId where bar.barId = ?1",
FooHasBarWithNoIdOrPropNamedId.class
).setParameter( 1, 1L )
.uniqueResult();
assertNotNull( foo );
assertNotNull( foo.bar );
});
// Querying by the generic "id" should work the same as "barId".
doInHibernate( this::sessionFactory, session -> {
final FooHasBarWithNoIdOrPropNamedId foo = session.createQuery(
"from FooHasBarWithNoIdOrPropNamedId where bar.id = ?1",
FooHasBarWithNoIdOrPropNamedId.class
).setParameter( 1, 1L )
.uniqueResult();
assertNotNull( foo );
assertNotNull( foo.bar );
});
doInHibernate( this::sessionFactory, session -> {
final FooHasBarWithNoIdOrPropNamedId foo = session.get( FooHasBarWithNoIdOrPropNamedId.class, 1L );
session.delete( foo.bar );
foo.bar = null;
});
doInHibernate( this::sessionFactory, session -> {
final FooHasBarWithNoIdOrPropNamedId foo = session.createQuery(
"from FooHasBarWithNoIdOrPropNamedId where bar.barId = ?1",
FooHasBarWithNoIdOrPropNamedId.class
).setParameter( 1, 1L )
.uniqueResult();
assertNull( foo );
});
// Querying by the generic "id" should work the same as "barId".
doInHibernate( this::sessionFactory, session -> {
final FooHasBarWithNoIdOrPropNamedId foo = session.createQuery(
"from FooHasBarWithNoIdOrPropNamedId where bar.id = ?1",
FooHasBarWithNoIdOrPropNamedId.class
).setParameter( 1, 1L )
.uniqueResult();
assertNull( foo );
});
}
@Test
public void testOneToOneWithNonIdPropNamedId() {
// Test with associated entity having a non-ID property named "id"
doInHibernate( this::sessionFactory, session -> {
BarWithNonIdPropNamedId bar = new BarWithNonIdPropNamedId();
bar.barId = 1L;
bar.id = 2L;
FooHasBarWithNonIdPropNamedId foo = new FooHasBarWithNonIdPropNamedId();
foo.id = 1L;
foo.bar = bar;
session.persist( bar );
session.persist( foo );
});
doInHibernate( this::sessionFactory, session -> {
final FooHasBarWithNonIdPropNamedId foo = session.createQuery(
"from FooHasBarWithNonIdPropNamedId where bar.barId = ?1",
FooHasBarWithNonIdPropNamedId.class
).setParameter( 1, 1L )
.uniqueResult();
assertNotNull( foo );
assertNotNull( foo.bar );
});
// bar.id is a non-ID property.
doInHibernate( this::sessionFactory, session -> {
final FooHasBarWithNonIdPropNamedId foo = session.createQuery(
"from FooHasBarWithNonIdPropNamedId where bar.id = ?1",
FooHasBarWithNonIdPropNamedId.class
).setParameter( 1, 2L )
.uniqueResult();
assertNotNull( foo );
assertNotNull( foo.bar );
});
// bar.id is a non-ID property.
doInHibernate( this::sessionFactory, session -> {
final FooHasBarWithNonIdPropNamedId foo = session.createQuery(
"from FooHasBarWithNonIdPropNamedId where bar.id = ?1",
FooHasBarWithNonIdPropNamedId.class
).setParameter( 1, 1L )
.uniqueResult();
assertNull( foo );
});
doInHibernate( this::sessionFactory, session -> {
final FooHasBarWithNonIdPropNamedId foo = session.get( FooHasBarWithNonIdPropNamedId.class, 1L );
session.delete( foo.bar );
foo.bar = null;
});
doInHibernate( this::sessionFactory, session -> {
final FooHasBarWithNonIdPropNamedId foo = session.createQuery(
"from FooHasBarWithNonIdPropNamedId where bar.barId = ?1",
FooHasBarWithNonIdPropNamedId.class
).setParameter( 1, 1L )
.uniqueResult();
assertNull( foo );
});
doInHibernate( this::sessionFactory, session -> {
final FooHasBarWithNonIdPropNamedId foo = session.createQuery(
"from FooHasBarWithNonIdPropNamedId where bar.id = ?1",
FooHasBarWithNonIdPropNamedId.class
).setParameter( 1, 1L )
.uniqueResult();
assertNull( foo );
});
doInHibernate( this::sessionFactory, session -> {
final FooHasBarWithNonIdPropNamedId foo = session.createQuery(
"from FooHasBarWithNonIdPropNamedId where bar.id = ?1",
FooHasBarWithNonIdPropNamedId.class
).setParameter( 1, 2L )
.uniqueResult();
assertNull( foo );
});
}
@After
public void cleanupData() {
doInHibernate( this::sessionFactory, session -> {
session.createQuery( "delete from FooHasBarWithIdNamedId" ).executeUpdate();
session.createQuery( "delete from FooHasBarWithNoIdOrPropNamedId" ).executeUpdate();
session.createQuery( "delete from FooHasBarWithNonIdPropNamedId" ).executeUpdate();
session.createQuery( "delete from BarWithIdNamedId" ).executeUpdate();
session.createQuery( "delete from BarWithNoIdOrPropNamedId" ).executeUpdate();
session.createQuery( "delete from BarWithNoIdOrPropNamedId" ).executeUpdate();
});
}
@Override
protected Class[] getAnnotatedClasses()
{
return new Class[] {
FooHasBarWithIdNamedId.class,
BarWithIdNamedId.class,
FooHasBarWithNoIdOrPropNamedId.class,
BarWithNoIdOrPropNamedId.class,
FooHasBarWithNonIdPropNamedId.class,
BarWithNonIdPropNamedId.class
};
}
@Entity(name = "FooHasBarWithIdNamedId")
public static class FooHasBarWithIdNamedId
{
@Id
private Long id;
@OneToOne(optional = true)
@MapsId
@JoinColumn(name = "id")
@NotFound(action = NotFoundAction.IGNORE)
private BarWithIdNamedId bar;
}
@Entity(name = "BarWithIdNamedId")
public static class BarWithIdNamedId {
@Id
private long id;
private long longValue;
}
@Entity(name = "FooHasBarWithNoIdOrPropNamedId")
@Table(name = "FooHasBarNoIdOrPropNamedId")
public static class FooHasBarWithNoIdOrPropNamedId
{
@Id
private Long id;
@OneToOne(optional = true)
@MapsId
@JoinColumn(name = "id")
@NotFound(action = NotFoundAction.IGNORE)
private BarWithNoIdOrPropNamedId bar;
}
@Entity(name = "BarWithNoIdOrPropNamedId")
public static class BarWithNoIdOrPropNamedId {
@Id
private long barId;
private long longValue;
}
@Entity(name = "FooHasBarWithNonIdPropNamedId")
@Table(name = "FooHasBarNonIdPropNamedId")
public static class FooHasBarWithNonIdPropNamedId
{
@Id
private Long id;
@OneToOne(optional = true)
@MapsId
@JoinColumn(name = "id")
@NotFound(action = NotFoundAction.IGNORE)
private BarWithNonIdPropNamedId bar;
}
@Entity(name = "BarWithNonIdPropNamedId")
public static class BarWithNonIdPropNamedId {
@Id
private long barId;
private long id;
}
}

View File

@ -0,0 +1,289 @@
/*
* 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.test.annotations.onetoone;
import javax.persistence.ConstraintMode;
import javax.persistence.Entity;
import javax.persistence.ForeignKey;
import javax.persistence.Id;
import javax.persistence.OneToOne;
import javax.persistence.PrimaryKeyJoinColumn;
import javax.persistence.Table;
import org.hibernate.testing.TestForIssue;
import org.hibernate.testing.junit4.BaseNonConfigCoreFunctionalTestCase;
import org.junit.After;
import org.junit.Test;
import static org.hibernate.testing.transaction.TransactionUtil.doInHibernate;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
@TestForIssue( jiraKey = "HHH-13875")
public class OptionalOneToOnePKJCQueryTest extends BaseNonConfigCoreFunctionalTestCase {
@Test
public void testOneToOneWithIdNamedId() {
// Test with associated entity having ID named "id"
doInHibernate( this::sessionFactory, session -> {
BarWithIdNamedId bar = new BarWithIdNamedId();
bar.id = 1L;
bar.longValue = 2L;
FooHasBarWithIdNamedId foo = new FooHasBarWithIdNamedId();
foo.id = 1L;
foo.bar = bar;
session.persist( bar );
session.persist( foo );
});
doInHibernate( this::sessionFactory, session -> {
final FooHasBarWithIdNamedId foo = session.createQuery(
"from FooHasBarWithIdNamedId where bar.id = ?1",
FooHasBarWithIdNamedId.class
).setParameter( 1, 1L )
.uniqueResult();
assertNotNull( foo );
assertNotNull( foo.bar );
});
doInHibernate( this::sessionFactory, session -> {
final FooHasBarWithIdNamedId foo = session.get( FooHasBarWithIdNamedId.class, 1L );
session.delete( foo.bar );
foo.bar = null;
});
doInHibernate( this::sessionFactory, session -> {
final FooHasBarWithIdNamedId foo = session.createQuery(
"from FooHasBarWithIdNamedId where bar.id = ?1",
FooHasBarWithIdNamedId.class
).setParameter( 1, 1L )
.uniqueResult();
assertNull( foo );
});
}
@Test
public void testOneToOneWithNoIdOrPropNamedId() {
// Test with associated entity having ID not named "id", and with no property named "id"
doInHibernate( this::sessionFactory, session -> {
BarWithNoIdOrPropNamedId bar = new BarWithNoIdOrPropNamedId();
bar.barId = 1L;
bar.longValue = 2L;
FooHasBarWithNoIdOrPropNamedId foo = new FooHasBarWithNoIdOrPropNamedId();
foo.id = 1L;
foo.bar = bar;
session.persist( bar );
session.persist( foo );
});
doInHibernate( this::sessionFactory, session -> {
final FooHasBarWithNoIdOrPropNamedId foo = session.createQuery(
"from FooHasBarWithNoIdOrPropNamedId where bar.barId = ?1",
FooHasBarWithNoIdOrPropNamedId.class
).setParameter( 1, 1L )
.uniqueResult();
assertNotNull( foo );
assertNotNull( foo.bar );
});
// Querying by the generic "id" should work the same as "barId".
doInHibernate( this::sessionFactory, session -> {
final FooHasBarWithNoIdOrPropNamedId foo = session.createQuery(
"from FooHasBarWithNoIdOrPropNamedId where bar.id = ?1",
FooHasBarWithNoIdOrPropNamedId.class
).setParameter( 1, 1L )
.uniqueResult();
assertNotNull( foo );
assertNotNull( foo.bar );
});
doInHibernate( this::sessionFactory, session -> {
final FooHasBarWithNoIdOrPropNamedId foo = session.get( FooHasBarWithNoIdOrPropNamedId.class, 1L );
session.delete( foo.bar );
foo.bar = null;
});
doInHibernate( this::sessionFactory, session -> {
final FooHasBarWithNoIdOrPropNamedId foo = session.createQuery(
"from FooHasBarWithNoIdOrPropNamedId where bar.barId = ?1",
FooHasBarWithNoIdOrPropNamedId.class
).setParameter( 1, 1L )
.uniqueResult();
assertNull( foo );
});
// Querying by the generic "id" should work the same as "barId".
doInHibernate( this::sessionFactory, session -> {
final FooHasBarWithNoIdOrPropNamedId foo = session.createQuery(
"from FooHasBarWithNoIdOrPropNamedId where bar.id = ?1",
FooHasBarWithNoIdOrPropNamedId.class
).setParameter( 1, 1L )
.uniqueResult();
assertNull( foo );
});
}
@Test
public void testOneToOneWithNonIdPropNamedId() {
// Test with associated entity having a non-ID property named "id"
doInHibernate( this::sessionFactory, session -> {
BarWithNonIdPropNamedId bar = new BarWithNonIdPropNamedId();
bar.barId = 1L;
bar.id = 2L;
FooHasBarWithNonIdPropNamedId foo = new FooHasBarWithNonIdPropNamedId();
foo.id = 1L;
foo.bar = bar;
session.persist( bar );
session.persist( foo );
});
doInHibernate( this::sessionFactory, session -> {
final FooHasBarWithNonIdPropNamedId foo = session.createQuery(
"from FooHasBarWithNonIdPropNamedId where bar.barId = ?1",
FooHasBarWithNonIdPropNamedId.class
).setParameter( 1, 1L )
.uniqueResult();
assertNotNull( foo );
assertNotNull( foo.bar );
});
// bar.id is a non-ID property.
doInHibernate( this::sessionFactory, session -> {
final FooHasBarWithNonIdPropNamedId foo = session.createQuery(
"from FooHasBarWithNonIdPropNamedId where bar.id = ?1",
FooHasBarWithNonIdPropNamedId.class
).setParameter( 1, 2L )
.uniqueResult();
assertNotNull( foo );
assertNotNull( foo.bar );
});
// bar.id is a non-ID property.
doInHibernate( this::sessionFactory, session -> {
final FooHasBarWithNonIdPropNamedId foo = session.createQuery(
"from FooHasBarWithNonIdPropNamedId where bar.id = ?1",
FooHasBarWithNonIdPropNamedId.class
).setParameter( 1, 1L )
.uniqueResult();
assertNull( foo );
});
doInHibernate( this::sessionFactory, session -> {
final FooHasBarWithNonIdPropNamedId foo = session.get( FooHasBarWithNonIdPropNamedId.class, 1L );
session.delete( foo.bar );
foo.bar = null;
});
doInHibernate( this::sessionFactory, session -> {
final FooHasBarWithNonIdPropNamedId foo = session.createQuery(
"from FooHasBarWithNonIdPropNamedId where bar.barId = ?1",
FooHasBarWithNonIdPropNamedId.class
).setParameter( 1, 1L )
.uniqueResult();
assertNull( foo );
});
doInHibernate( this::sessionFactory, session -> {
final FooHasBarWithNonIdPropNamedId foo = session.createQuery(
"from FooHasBarWithNonIdPropNamedId where bar.id = ?1",
FooHasBarWithNonIdPropNamedId.class
).setParameter( 1, 1L )
.uniqueResult();
assertNull( foo );
});
doInHibernate( this::sessionFactory, session -> {
final FooHasBarWithNonIdPropNamedId foo = session.createQuery(
"from FooHasBarWithNonIdPropNamedId where bar.id = ?1",
FooHasBarWithNonIdPropNamedId.class
).setParameter( 1, 2L )
.uniqueResult();
assertNull( foo );
});
}
@After
public void cleanupData() {
doInHibernate( this::sessionFactory, session -> {
session.createQuery( "delete from FooHasBarWithIdNamedId" ).executeUpdate();
session.createQuery( "delete from FooHasBarWithNoIdOrPropNamedId" ).executeUpdate();
session.createQuery( "delete from FooHasBarWithNonIdPropNamedId" ).executeUpdate();
session.createQuery( "delete from BarWithIdNamedId" ).executeUpdate();
session.createQuery( "delete from BarWithNoIdOrPropNamedId" ).executeUpdate();
session.createQuery( "delete from BarWithNoIdOrPropNamedId" ).executeUpdate();
});
}
@Override
protected Class[] getAnnotatedClasses()
{
return new Class[] {
FooHasBarWithIdNamedId.class,
BarWithIdNamedId.class,
FooHasBarWithNoIdOrPropNamedId.class,
BarWithNoIdOrPropNamedId.class,
FooHasBarWithNonIdPropNamedId.class,
BarWithNonIdPropNamedId.class
};
}
@Entity(name = "FooHasBarWithIdNamedId")
public static class FooHasBarWithIdNamedId
{
@Id
private long id;
@OneToOne(optional = true)
@PrimaryKeyJoinColumn(foreignKey = @ForeignKey(ConstraintMode.NO_CONSTRAINT))
private BarWithIdNamedId bar;
}
@Entity(name = "BarWithIdNamedId")
public static class BarWithIdNamedId {
@Id
private long id;
private long longValue;
}
@Entity(name = "FooHasBarWithNoIdOrPropNamedId")
@Table(name = "FooHasBarNoIdOrPropNamedId")
public static class FooHasBarWithNoIdOrPropNamedId
{
@Id
private long id;
@OneToOne(optional = true)
@PrimaryKeyJoinColumn()
private BarWithNoIdOrPropNamedId bar;
}
@Entity(name = "BarWithNoIdOrPropNamedId")
public static class BarWithNoIdOrPropNamedId {
@Id
private long barId;
private long longValue;
}
@Entity(name = "FooHasBarWithNonIdPropNamedId")
@Table(name = "FooHasBarNonIdPropNamedId")
public static class FooHasBarWithNonIdPropNamedId
{
@Id
private long id;
@OneToOne(optional = true)
@PrimaryKeyJoinColumn()
private BarWithNonIdPropNamedId bar;
}
@Entity(name = "BarWithNonIdPropNamedId")
public static class BarWithNonIdPropNamedId {
@Id
private long barId;
private long id;
}
}

View File

@ -0,0 +1,133 @@
package org.hibernate.test.dialect.functional;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Statement;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import org.hibernate.annotations.GenericGenerator;
import org.hibernate.annotations.Parameter;
import org.hibernate.cfg.AvailableSettings;
import org.hibernate.cfg.Configuration;
import org.hibernate.cfg.Environment;
import org.hibernate.dialect.Oracle8iDialect;
import org.hibernate.id.SequenceMismatchStrategy;
import org.hibernate.id.enhanced.SequenceStyleGenerator;
import org.hibernate.testing.BeforeClassOnce;
import org.hibernate.testing.RequiresDialect;
import org.hibernate.testing.TestForIssue;
import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase;
import org.hibernate.test.annotations.lob.OracleSeqIdGenDialect;
import org.junit.AfterClass;
import org.junit.Test;
/**
* @author Nathan Xu
*/
@TestForIssue( jiraKey = "HHH-13322" )
@RequiresDialect( Oracle8iDialect.class )
public class OracleExtractSequenceMetadataTest extends BaseCoreFunctionalTestCase {
private static final String SEQUENCE_NAME = SequenceStyleGenerator.DEF_SEQUENCE_NAME;
private static final String SEQUENCE_INCREMENT_SIZE = "50";
private static final String OTHER_SCHEMA_NAME = "hibernate_orm_test_2";
private static final String SEQUENCE_INCREMENT_SIZE_FROM_OTHER_SCHEMA = "1";
@Override
protected void configure(Configuration configuration) {
configuration.setProperty( Environment.DIALECT, OracleSeqIdGenDialect.class.getName() );
configuration.setProperty(
AvailableSettings.SEQUENCE_INCREMENT_SIZE_MISMATCH_STRATEGY,
SequenceMismatchStrategy.EXCEPTION.toString() );
}
@Override
public Class<?>[] getAnnotatedClasses() {
return new Class<?>[] { TestEntity.class };
}
@BeforeClassOnce
public static void setUpDB() throws Exception {
assert ! SEQUENCE_INCREMENT_SIZE.equals( SEQUENCE_INCREMENT_SIZE_FROM_OTHER_SCHEMA );
try ( Connection conn = getConnection() ) {
try ( Statement stmt = conn.createStatement() ) {
try {
stmt.execute( String.format( "DROP USER %s CASCADE", OTHER_SCHEMA_NAME ) );
}
catch ( Exception ignore ) {
}
stmt.execute( String.format( "CREATE USER %s IDENTIFIED BY whatever", OTHER_SCHEMA_NAME ) );
// create identical sequence in other schema with different 'increment size' than specified in id field of the entity
stmt.execute( String.format( "CREATE SEQUENCE %s.%s START WITH 1 INCREMENT BY %s",
OTHER_SCHEMA_NAME,
SEQUENCE_NAME,
SEQUENCE_INCREMENT_SIZE_FROM_OTHER_SCHEMA
) );
// ensure no sequence exists for current schema, so the identical sequence in the other schema could be the only culprit
try {
stmt.execute( String.format(
"DROP SEQUENCE %s",
SEQUENCE_NAME
) );
}
catch ( Exception ignore ) {
}
}
}
}
@Test
public void testHibernateLaunchSuccessfully() {
// if we were lucky to reach here, woa, the sequence from other schema didn't bother us (with different 'increment size's)
}
@AfterClass
public static void tearDownDB() throws SQLException {
try ( Connection conn = getConnection() ) {
try ( Statement stmt = conn.createStatement() ) {
// dropping user with 'cascade' will drop the sequence as well
stmt.execute( String.format( "DROP USER %s CASCADE", OTHER_SCHEMA_NAME ) );
}
catch ( Exception ignore ) {
}
}
}
private static Connection getConnection() throws SQLException {
String url = Environment.getProperties().getProperty( Environment.URL );
String user = Environment.getProperties().getProperty( Environment.USER );
String password = Environment.getProperties().getProperty( Environment.PASS );
return DriverManager.getConnection( url, user, password );
}
@Entity(name = "TestEntity")
public static class TestEntity {
@Id
@GeneratedValue( strategy = GenerationType.SEQUENCE, generator = "sequence_generator" )
@GenericGenerator(
name = "sequence_generator",
strategy = "org.hibernate.id.enhanced.SequenceStyleGenerator",
parameters = {
@Parameter(name = "sequence_name", value = SEQUENCE_NAME),
@Parameter(name = "initial_value", value = "1" ),
@Parameter(name = "increment_size", value = SEQUENCE_INCREMENT_SIZE),
@Parameter(name = "optimizer", value = "pooled")
}
)
private Long id;
}
}

View File

@ -49,7 +49,7 @@ public class BasicStreamTest extends BaseNonConfigCoreFunctionalTestCase {
final Stream<MyEntity> stream = session.createQuery( "from MyEntity", MyEntity.class ).stream();
assertThat( ( (SessionImplementor) session ).getJdbcCoordinator().getLogicalConnection().getResourceRegistry().hasRegisteredResources(), is( true ) );
stream.forEach( System.out::println );
assertThat( ( (SessionImplementor) session ).getJdbcCoordinator().getLogicalConnection().getResourceRegistry().hasRegisteredResources(), is( true ) );
assertThat( ( (SessionImplementor) session ).getJdbcCoordinator().getLogicalConnection().getResourceRegistry().hasRegisteredResources(), is( false ) );
stream.close();
assertThat( ( (SessionImplementor) session ).getJdbcCoordinator().getLogicalConnection().getResourceRegistry().hasRegisteredResources(), is( false ) );

View File

@ -6,27 +6,34 @@
*/
package org.hibernate.test.stream.basic;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.List;
import java.util.function.Predicate;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Table;
import javax.persistence.Tuple;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Root;
import org.hibernate.Session;
import org.hibernate.boot.MetadataSources;
import org.hibernate.engine.spi.SessionImplementor;
import org.hibernate.dialect.H2Dialect;
import org.hibernate.engine.jdbc.spi.JdbcCoordinator;
import org.hibernate.engine.spi.SharedSessionContractImplementor;
import org.hibernate.internal.util.ReflectHelper;
import org.hibernate.resource.jdbc.ResourceRegistry;
import org.hibernate.testing.RequiresDialect;
import org.hibernate.testing.TestForIssue;
import org.hibernate.testing.junit4.BaseNonConfigCoreFunctionalTestCase;
import org.junit.Test;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.core.Is.is;
import static org.hibernate.testing.junit4.ExtraAssertions.assertTyping;
import static org.hibernate.testing.transaction.TransactionUtil.doInHibernate;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
/**
* @author Steve Ebersole
@ -70,12 +77,180 @@ public class JpaStreamTest extends BaseNonConfigCoreFunctionalTestCase {
} );
}
@Test
@TestForIssue( jiraKey = "HHH-13872")
@RequiresDialect(H2Dialect.class)
public void testStreamCloseOnTerminalOperation() {
doInHibernate( this::sessionFactory, session -> {
session.createQuery( "delete from MyEntity" ).executeUpdate();
for ( int i = 1; i <= 10; i++ ) {
MyEntity e = new MyEntity();
e.id = i;
e.name = "Test";
session.persist( e );
}
} );
doInHibernate( this::sessionFactory, session -> {
Stream<MyEntity> stream = session
.createQuery( "SELECT me FROM MyEntity me" )
.getResultStream();
ResourceRegistry resourceRegistry = resourceRegistry(session);
assertTrue( resourceRegistry.hasRegisteredResources() );
List<MyEntity> entities = stream.collect( Collectors.toList() ) ;
assertEquals(10, entities.size());
assertFalse( resourceRegistry.hasRegisteredResources() );
} );
doInHibernate( this::sessionFactory, session -> {
Stream<MyEntity> stream = session
.createQuery( "SELECT me FROM MyEntity me" )
.getResultStream();
ResourceRegistry resourceRegistry = resourceRegistry(session);
assertTrue( resourceRegistry.hasRegisteredResources() );
int sum = stream.mapToInt( MyEntity::getId ).sum();
assertEquals(55, sum);
assertFalse( resourceRegistry.hasRegisteredResources() );
} );
doInHibernate( this::sessionFactory, session -> {
Stream<MyEntity> stream = session
.createQuery( "SELECT me FROM MyEntity me" )
.getResultStream();
ResourceRegistry resourceRegistry = resourceRegistry(session);
assertTrue( resourceRegistry.hasRegisteredResources() );
long result = stream.mapToLong( entity -> entity.id * 10 ).min().getAsLong();
assertEquals(10, result);
assertFalse( resourceRegistry.hasRegisteredResources() );
} );
doInHibernate( this::sessionFactory, session -> {
Stream<MyEntity> stream = session
.createQuery( "SELECT me FROM MyEntity me" )
.getResultStream();
ResourceRegistry resourceRegistry = resourceRegistry(session);
assertTrue( resourceRegistry.hasRegisteredResources() );
double result = stream.mapToDouble( entity -> entity.id * 0.1D ).max().getAsDouble();
assertEquals(1, result, 0.1);
assertFalse( resourceRegistry.hasRegisteredResources() );
} );
//Test call close explicitly
doInHibernate( this::sessionFactory, session -> {
try (Stream<Long> stream = session
.createQuery( "SELECT me.id FROM MyEntity me" )
.getResultStream()) {
ResourceRegistry resourceRegistry = resourceRegistry( session );
assertTrue( resourceRegistry.hasRegisteredResources() );
Object[] result = stream.sorted().skip( 5 ).limit( 5 ).toArray();
assertEquals( 5, result.length );
assertEquals( 6, result[0] );
assertEquals( 10, result[4] );
assertFalse( resourceRegistry.hasRegisteredResources() );
}
} );
//Test Java 9 Stream methods
doInHibernate( this::sessionFactory, session -> {
Method takeWhileMethod = ReflectHelper.getMethod( Stream.class, "takeWhile", Predicate.class );
if ( takeWhileMethod != null ) {
try (Stream<Long> stream = session
.createQuery( "SELECT me.id FROM MyEntity me" )
.getResultStream()) {
ResourceRegistry resourceRegistry = resourceRegistry( session );
assertTrue( resourceRegistry.hasRegisteredResources() );
Predicate<Integer> predicate = id -> id <= 5;
Stream<Integer> takeWhileStream = (Stream<Integer>) takeWhileMethod.invoke( stream, predicate );
List<Integer> result = takeWhileStream.collect( Collectors.toList() );
assertEquals( 5, result.size() );
assertTrue( result.contains( 1 ) );
assertTrue( result.contains( 3 ) );
assertTrue( result.contains( 5 ) );
assertFalse( resourceRegistry.hasRegisteredResources() );
}
catch (IllegalAccessException | InvocationTargetException e) {
fail( "Could not execute takeWhile because of " + e.getMessage() );
}
}
} );
doInHibernate( this::sessionFactory, session -> {
Method dropWhileMethod = ReflectHelper.getMethod( Stream.class, "dropWhile", Predicate.class );
if ( dropWhileMethod != null ) {
try (Stream<Long> stream = session
.createQuery( "SELECT me.id FROM MyEntity me" )
.getResultStream()) {
ResourceRegistry resourceRegistry = resourceRegistry( session );
assertTrue( resourceRegistry.hasRegisteredResources() );
Predicate<Integer> predicate = id -> id <= 5;
Stream<Integer> dropWhileStream = (Stream<Integer>) dropWhileMethod.invoke( stream, predicate );
List<Integer> result = dropWhileStream.collect( Collectors.toList() );
assertEquals( 5, result.size() );
assertTrue( result.contains( 6 ) );
assertTrue( result.contains( 8 ) );
assertTrue( result.contains( 10 ) );
assertFalse( resourceRegistry.hasRegisteredResources() );
}
catch (IllegalAccessException | InvocationTargetException e) {
fail( "Could not execute takeWhile because of " + e.getMessage() );
}
}
} );
}
private ResourceRegistry resourceRegistry(Session session) {
SharedSessionContractImplementor sharedSessionContractImplementor = (SharedSessionContractImplementor) session;
JdbcCoordinator jdbcCoordinator = sharedSessionContractImplementor.getJdbcCoordinator();
return jdbcCoordinator.getLogicalConnection().getResourceRegistry();
}
@Entity(name = "MyEntity")
@Table(name="MyEntity")
public static class MyEntity {
@Id
public Integer id;
public String name;
public Integer getId() {
return id;
}
public String getName() {
return name;
}
}
}

View File

@ -1,9 +1,12 @@
package org.hibernate.test.type.contributor;
import java.util.Map;
import org.hibernate.dialect.Dialect;
import org.hibernate.type.AbstractSingleColumnStandardBasicType;
import org.hibernate.type.DiscriminatorType;
import org.hibernate.type.descriptor.sql.VarcharTypeDescriptor;
import org.hibernate.type.spi.TypeBootstrapContext;
/**
* @author Vlad Mihalcea
@ -14,10 +17,17 @@ public class ArrayType
public static final ArrayType INSTANCE = new ArrayType();
private Map<String, Object> settings;
public ArrayType() {
super( VarcharTypeDescriptor.INSTANCE, ArrayTypeDescriptor.INSTANCE );
}
public ArrayType(TypeBootstrapContext typeBootstrapContext) {
super( VarcharTypeDescriptor.INSTANCE, ArrayTypeDescriptor.INSTANCE );
this.settings = typeBootstrapContext.getConfigurationSettings();
}
@Override
public Array stringToObject(String xml) throws Exception {
return fromString( xml );
@ -33,4 +43,7 @@ public class ArrayType
return "comma-separated-array";
}
public Map<String, Object> getSettings() {
return settings;
}
}

View File

@ -6,29 +6,33 @@
*/
package org.hibernate.test.type.contributor;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Table;
import org.hibernate.Session;
import org.hibernate.annotations.Type;
import org.hibernate.cfg.Configuration;
import org.hibernate.boot.spi.MetadataBuilderContributor;
import org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl;
import org.hibernate.jpa.test.BaseEntityManagerFunctionalTestCase;
import org.hibernate.query.Query;
import org.hibernate.testing.TestForIssue;
import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase;
import org.hibernate.test.collection.custom.basic.MyList;
import org.junit.Test;
import static org.hibernate.testing.transaction.TransactionUtil.doInHibernate;
import static org.hibernate.testing.transaction.TransactionUtil.doInJPA;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
/**
* @author Vlad Mihalcea
*/
@TestForIssue( jiraKey = "HHH-11409" )
public class ArrayTypeContributorTest extends BaseCoreFunctionalTestCase {
public class ArrayTypeContributorTest extends BaseEntityManagerFunctionalTestCase {
@Override
protected Class<?>[] getAnnotatedClasses() {
@ -36,36 +40,33 @@ public class ArrayTypeContributorTest extends BaseCoreFunctionalTestCase {
}
@Override
protected Configuration constructAndConfigureConfiguration() {
Configuration configuration = super.constructAndConfigureConfiguration();
configuration.registerTypeContributor( (typeContributions, serviceRegistry) -> {
typeContributions.contributeType( ArrayType.INSTANCE );
} );
return configuration;
protected void addConfigOptions(Map options) {
options.put(
EntityManagerFactoryBuilderImpl.METADATA_BUILDER_CONTRIBUTOR,
(MetadataBuilderContributor) metadataBuilder ->
metadataBuilder.applyTypes( (typeContributions, serviceRegistry) -> {
typeContributions.contributeType( ArrayType.INSTANCE );
} ));
}
@Override
protected void prepareTest() throws Exception {
doInHibernate( this::sessionFactory, session -> {
protected void afterEntityManagerFactoryBuilt() {
doInJPA( this::entityManagerFactory, entityManager -> {
CorporateUser user = new CorporateUser();
user.setUserName( "Vlad" );
session.persist( user );
entityManager.persist( user );
user.getEmailAddresses().add( "vlad@hibernate.info" );
user.getEmailAddresses().add( "vlad@hibernate.net" );
} );
}
@Override
protected boolean isCleanupTestDataRequired() {
return true;
}
@Test
public void test() {
doInHibernate( this::sessionFactory, session -> {
List<CorporateUser> users = session.createQuery(
doInJPA( this::entityManagerFactory, entityManager -> {
List<CorporateUser> users = entityManager.createQuery(
"select u from CorporateUser u where u.emailAddresses = :address", CorporateUser.class )
.unwrap( Query.class )
.setParameter( "address", new Array(), ArrayType.INSTANCE )
.getResultList();
@ -75,8 +76,8 @@ public class ArrayTypeContributorTest extends BaseCoreFunctionalTestCase {
@Test
public void testNativeSQL() {
doInHibernate( this::sessionFactory, session -> {
List<Array> emails = session.createNativeQuery(
doInJPA( this::entityManagerFactory, entityManager -> {
List<Array> emails = entityManager.createNativeQuery(
"select u.emailAddresses from CorporateUser u where u.userName = :name" )
.setParameter( "name", "Vlad" )
.getResultList();

View File

@ -0,0 +1,131 @@
/*
* 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.test.type.contributor;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.transaction.Transactional;
import org.hibernate.Session;
import org.hibernate.annotations.Type;
import org.hibernate.annotations.TypeDef;
import org.hibernate.boot.spi.MetadataBuilderContributor;
import org.hibernate.engine.spi.EntityEntry;
import org.hibernate.engine.spi.PersistenceContext;
import org.hibernate.engine.spi.SharedSessionContractImplementor;
import org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl;
import org.hibernate.jpa.test.BaseEntityManagerFunctionalTestCase;
import org.hibernate.persister.entity.EntityPersister;
import org.hibernate.query.Query;
import org.hibernate.testing.TestForIssue;
import org.junit.Test;
import static org.hibernate.testing.transaction.TransactionUtil.doInJPA;
import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
/**
* @author Vlad Mihalcea
*/
@TestForIssue( jiraKey = "HHH-13103" )
public class ArrayTypePropertiesTest extends BaseEntityManagerFunctionalTestCase {
@Override
protected Class<?>[] getAnnotatedClasses() {
return new Class[] { CorporateUser.class };
}
@Override
protected void addConfigOptions(Map options) {
options.put( "hibernate.type.array.config", new Integer[]{1, 2, 3} );
}
@Override
protected void afterEntityManagerFactoryBuilt() {
doInJPA( this::entityManagerFactory, entityManager -> {
CorporateUser user = new CorporateUser();
user.setUserName( "Vlad" );
entityManager.persist( user );
user.getEmailAddresses().add( "vlad@hibernate.info" );
user.getEmailAddresses().add( "vlad@hibernate.net" );
} );
}
@Test
public void test() {
doInJPA( this::entityManagerFactory, entityManager -> {
List<CorporateUser> users = entityManager.createQuery(
"select u from CorporateUser u where u.emailAddresses = :address", CorporateUser.class )
.unwrap( Query.class )
.setParameter( "address", new Array(), ArrayType.INSTANCE )
.getResultList();
assertTrue( users.isEmpty() );
} );
}
@Test
public void testNativeSQL() {
doInJPA( this::entityManagerFactory, entityManager -> {
List<Array> emails = entityManager.createNativeQuery(
"select u.emailAddresses from CorporateUser u where u.userName = :name" )
.setParameter( "name", "Vlad" )
.getResultList();
assertEquals( 1, emails.size() );
} );
}
@Test
public void testConfigurationSettings() {
doInJPA( this::entityManagerFactory, entityManager -> {
SharedSessionContractImplementor session = entityManager.unwrap( SharedSessionContractImplementor.class );
CorporateUser corporateUser = entityManager.find( CorporateUser.class, "Vlad" );
PersistenceContext persistenceContext = session.getPersistenceContext();
EntityPersister entityPersister = persistenceContext.getEntry( corporateUser ).getPersister();
ArrayType arrayType = (ArrayType) entityPersister.getPropertyType( "emailAddresses" );
Map<String, Object> settings = arrayType.getSettings();
Integer[] arrayConfig = (Integer[]) settings.get( "hibernate.type.array.config" );
assertNotNull( arrayConfig );
assertArrayEquals( new Integer[]{1, 2, 3}, arrayConfig );
} );
}
@Entity(name = "CorporateUser")
@TypeDef( typeClass = ArrayType.class, defaultForType = Array.class )
public static class CorporateUser {
@Id
private String userName;
private Array emailAddresses = new Array();
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public Array getEmailAddresses() {
return emailAddresses;
}
}
}

View File

@ -43,17 +43,11 @@ public class HibernatePersistenceProviderAdaptor implements PersistenceProviderA
@SuppressWarnings("WeakerAccess")
public static final String HIBERNATE_EXTENDED_BEANMANAGER = "org.hibernate.resource.beans.container.spi.ExtendedBeanManager";
private volatile JtaManager jtaManager;
private volatile Platform platform;
private static final String NONE = SharedCacheMode.NONE.name();
@Override
public void injectJtaManager(JtaManager jtaManager) {
// todo : why? `this.jtaManager` is never used aside from setting here in this method
if ( this.jtaManager != jtaManager ) {
this.jtaManager = jtaManager;
}
}
public void injectJtaManager(JtaManager jtaManager) { }
@Override
public void injectPlatform(Platform platform) {

View File

@ -10,7 +10,7 @@ hibernate.dialect org.hibernate.spatial.dialect.db2.DB2SpatialDialect
hibernate.connection.driver_class com.ibm.db2.jcc.DB2Driver
hibernate.connection.url jdbc:db2://localhost:50000/hibern8
hibernate.connection.username db2inst1
hibernate.connection.password password
hibernate.connection.password oPucroAsMAgL
hibernate.connection.pool_size 5

View File

@ -9,7 +9,7 @@ hibernate.dialect org.hibernate.spatial.dialect.sqlserver.SqlServer2012SpatialDi
hibernate.connection.driver_class com.microsoft.sqlserver.jdbc.SQLServerDriver
hibernate.connection.url jdbc:sqlserver://localhost:1433;databaseName=TestDb
hibernate.connection.username hibern8
hibernate.connection.password hibern8Pass
hibernate.connection.password langpaswoord123A%1
hibernate.connection.pool_size 5

View File

@ -1,5 +1,8 @@
#! /bin/bash
## The same effect can be achieved by setting the system properties
# in ~/.gradle/gradle.properties
TASK=matrix
if [[ -n $@ ]]; then
TASK="$@"

View File

@ -164,8 +164,16 @@ public enum SpatialFunction {
/**
* the extents function
*/
extent( "common" );
extent( "common" ),
/**
* The filter function
* <p>
* <p>Corresponds to the Oracle Spatial's "SDO_FILTER" function, or the "&&" operator of PostGIS.
*/
filter( "filter" ),
;
private final String description;

View File

@ -0,0 +1,18 @@
/*
* 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.spatial.dialect;
/**
* An Interface for {@code SpatialDialect}s that require a custom
* rendering to JPAQL for the filter predicate
* <p>
* Created by Karel Maesen, Geovise BVBA on 09/02/2020.
*/
public interface WithCustomJPAFilter {
String filterExpression(String geometryParam, String filterParam);
}

View File

@ -7,9 +7,15 @@
package org.hibernate.spatial.dialect.h2geodb;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import org.hibernate.QueryException;
import org.hibernate.boot.model.TypeContributions;
import org.hibernate.dialect.H2Dialect;
import org.hibernate.dialect.function.StandardSQLFunction;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.service.ServiceRegistry;
import org.hibernate.spatial.GeolatteGeometryJavaTypeDescriptor;
import org.hibernate.spatial.GeolatteGeometryType;
@ -19,6 +25,7 @@ import org.hibernate.spatial.SpatialDialect;
import org.hibernate.spatial.SpatialFunction;
import org.hibernate.spatial.SpatialRelation;
import org.hibernate.type.StandardBasicTypes;
import org.hibernate.type.Type;
/**
* Extends the H2Dialect by also including information on spatial functions.
@ -74,6 +81,8 @@ public class GeoDBDialect extends H2Dialect implements SpatialDialect {
registerFunction( "dwithin", new StandardSQLFunction( "ST_DWithin", StandardBasicTypes.BOOLEAN ) );
// Register Spatial Filter function
registerFunction( SpatialFunction.filter.name(), new FilterFunction() );
}
@Override
@ -157,4 +166,26 @@ public class GeoDBDialect extends H2Dialect implements SpatialDialect {
return function != SpatialFunction.difference && ( getFunctions().get( function.toString() ) != null );
}
private static class FilterFunction extends StandardSQLFunction {
public FilterFunction() {
super( "&&" );
}
@Override
public String render(
Type firstArgumentType, List arguments, SessionFactoryImplementor sessionFactory) {
int argumentCount = arguments.size();
if ( argumentCount != 2 ) {
throw new QueryException( String.format( "2 arguments expected, received %d", argumentCount ) );
}
return Stream.of(
String.valueOf( arguments.get( 0 ) ),
getRenderedName( arguments ),
String.valueOf( arguments.get( 1 ) )
).collect( Collectors.joining( " ", "(", ")" ) );
}
}
}

View File

@ -7,11 +7,13 @@
package org.hibernate.spatial.dialect.hana;
import java.sql.Types;
import java.util.List;
import org.hibernate.boot.model.TypeContributions;
import org.hibernate.dialect.HANAColumnStoreDialect;
import org.hibernate.engine.config.spi.ConfigurationService;
import org.hibernate.engine.config.spi.ConfigurationService.Converter;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.service.ServiceRegistry;
import org.hibernate.spatial.GeolatteGeometryJavaTypeDescriptor;
import org.hibernate.spatial.GeolatteGeometryType;
@ -22,6 +24,7 @@ import org.hibernate.spatial.SpatialDialect;
import org.hibernate.spatial.SpatialFunction;
import org.hibernate.spatial.SpatialRelation;
import org.hibernate.type.StandardBasicTypes;
import org.hibernate.type.Type;
public class HANASpatialDialect extends HANAColumnStoreDialect implements SpatialDialect {
@ -102,6 +105,9 @@ public class HANASpatialDialect extends HANAColumnStoreDialect implements Spatia
registerFunction(
SpatialFunction.within.name(),
new HANASpatialFunction( "ST_Within", StandardBasicTypes.NUMERIC_BOOLEAN, true ) );
registerFunction(
SpatialFunction.filter.name(),
new FilterFunction() );
/*
* Additional HANA functions
@ -408,4 +414,17 @@ public class HANASpatialDialect extends HANAColumnStoreDialect implements Spatia
}
return false;
}
private static class FilterFunction extends HANASpatialFunction {
public FilterFunction() {
super( "ST_IntersectsFilter", StandardBasicTypes.NUMERIC_BOOLEAN, true );
}
@Override
public String render(
Type firstArgumentType, List arguments, SessionFactoryImplementor sessionFactory) {
return super.render( firstArgumentType, arguments, sessionFactory ) + " = 1";
}
}
}

View File

@ -7,6 +7,7 @@
package org.hibernate.spatial.dialect.mysql;
import org.hibernate.dialect.function.StandardSQLFunction;
import org.hibernate.spatial.SpatialFunction;
import org.hibernate.spatial.dialect.SpatialFunctionsRegistry;
import org.hibernate.type.StandardBasicTypes;
@ -163,6 +164,13 @@ class MySQL5SpatialFunctions extends SpatialFunctionsRegistry {
// "union"
// )
// );
functionMap.put(
SpatialFunction.filter.name(), new StandardSQLFunction(
"MBRIntersects",
StandardBasicTypes.BOOLEAN
)
);
}
}

View File

@ -7,6 +7,7 @@
package org.hibernate.spatial.dialect.mysql;
import org.hibernate.dialect.function.StandardSQLFunction;
import org.hibernate.spatial.SpatialFunction;
import org.hibernate.spatial.dialect.SpatialFunctionsRegistry;
import org.hibernate.type.StandardBasicTypes;
@ -169,6 +170,13 @@ class MySQL8SpatialFunctions extends SpatialFunctionsRegistry {
"ST_Union"
)
);
functionMap.put(
SpatialFunction.filter.name(), new StandardSQLFunction(
"MBRIntersects",
StandardBasicTypes.BOOLEAN
)
);
}
}

View File

@ -7,6 +7,7 @@
package org.hibernate.spatial.dialect.oracle;
import java.io.Serializable;
import java.util.Locale;
import org.hibernate.boot.model.TypeContributions;
import org.hibernate.boot.registry.selector.spi.StrategySelector;
@ -22,6 +23,7 @@ import org.hibernate.spatial.SpatialDialect;
import org.hibernate.spatial.SpatialFunction;
import org.hibernate.spatial.SpatialRelation;
import org.hibernate.spatial.dialect.SpatialFunctionsRegistry;
import org.hibernate.spatial.dialect.WithCustomJPAFilter;
import org.jboss.logging.Logger;
@ -33,7 +35,7 @@ import org.geolatte.geom.codec.db.oracle.OracleJDBCTypeFactory;
* <p>
* Created by Karel Maesen, Geovise BVBA on 01/11/16.
*/
class OracleSDOSupport implements SpatialDialect, Serializable {
class OracleSDOSupport implements SpatialDialect, Serializable, WithCustomJPAFilter {
private static final HSMessageLogger log = Logger.getMessageLogger(
HSMessageLogger.class,
@ -290,7 +292,7 @@ class OracleSDOSupport implements SpatialDialect, Serializable {
*/
@Override
public String getHavingSridSQL(String columnName) {
return String.format( " (MDSYS.ST_GEOMETRY(%s).ST_SRID() = ?)", columnName );
return String.format( " (MDSYS.ST_GEOMETRY(%s).ST_SRID() = ?)", columnName , Locale.US);
}
/**
@ -304,7 +306,7 @@ class OracleSDOSupport implements SpatialDialect, Serializable {
*/
@Override
public String getIsEmptySQL(String columnName, boolean isEmpty) {
return String.format( "( MDSYS.ST_GEOMETRY(%s).ST_ISEMPTY() = %d )", columnName, isEmpty ? 1 : 0 );
return String.format( "( MDSYS.ST_GEOMETRY(%s).ST_ISEMPTY() = %d )", columnName, isEmpty ? 1 : 0 , Locale.US);
}
/**
@ -331,4 +333,8 @@ class OracleSDOSupport implements SpatialDialect, Serializable {
}
@Override
public String filterExpression(String geometryParam, String filterParam) {
return SpatialFunction.filter.name() + "(" + geometryParam + ", " + filterParam + ") = 'TRUE' ";
}
}

View File

@ -18,6 +18,7 @@ import org.hibernate.service.ServiceRegistry;
import org.hibernate.spatial.HSMessageLogger;
import org.hibernate.spatial.SpatialDialect;
import org.hibernate.spatial.SpatialFunction;
import org.hibernate.spatial.dialect.WithCustomJPAFilter;
import org.jboss.logging.Logger;
@ -26,7 +27,7 @@ import org.jboss.logging.Logger;
*
* @author Karel Maesen
*/
public class OracleSpatial10gDialect extends Oracle10gDialect implements SpatialDialect, Serializable {
public class OracleSpatial10gDialect extends Oracle10gDialect implements SpatialDialect, WithCustomJPAFilter, Serializable {
private static final HSMessageLogger log = Logger.getMessageLogger(
HSMessageLogger.class,
@ -101,5 +102,8 @@ public class OracleSpatial10gDialect extends Oracle10gDialect implements Spatial
return ( getFunctions().get( function.toString() ) != null );
}
@Override
public String filterExpression(String geometryParam, String filterParam) {
return sdoSupport.filterExpression( geometryParam, filterParam );
}
}

View File

@ -12,6 +12,7 @@ import org.hibernate.QueryException;
import org.hibernate.dialect.function.StandardSQLFunction;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.spatial.SpatialAnalysis;
import org.hibernate.spatial.SpatialFunction;
import org.hibernate.spatial.SpatialRelation;
import org.hibernate.spatial.dialect.SpatialFunctionsRegistry;
import org.hibernate.spatial.dialect.oracle.criterion.OracleSpatialAggregate;
@ -138,6 +139,12 @@ class OracleSpatialFunctions extends SpatialFunctionsRegistry {
new SpatialAggregationFunction( "extent", OracleSpatialAggregate.EXTENT, sdoSupport )
);
// spatial filter function
put(
SpatialFunction.filter.name(),
new StandardSQLFunction( "SDO_FILTER" )
);
//other common functions
put( "transform", new StandardSQLFunction( "SDO_CS.TRANSFORM" ) );

View File

@ -17,6 +17,7 @@ import org.hibernate.service.ServiceRegistry;
import org.hibernate.spatial.HSMessageLogger;
import org.hibernate.spatial.SpatialDialect;
import org.hibernate.spatial.SpatialFunction;
import org.hibernate.spatial.dialect.WithCustomJPAFilter;
import org.jboss.logging.Logger;
@ -25,7 +26,8 @@ import org.jboss.logging.Logger;
* <p>
* Created by Karel Maesen, Geovise BVBA on 11/02/17.
*/
public class OracleSpatialSDO10gDialect extends Oracle10gDialect implements SpatialDialect, Serializable {
public class OracleSpatialSDO10gDialect extends Oracle10gDialect
implements SpatialDialect, WithCustomJPAFilter, Serializable {
private static final HSMessageLogger log = Logger.getMessageLogger(
HSMessageLogger.class,
@ -100,5 +102,8 @@ public class OracleSpatialSDO10gDialect extends Oracle10gDialect implements Spat
return !function.equals( SpatialFunction.crosses ) && ( getFunctions().get( function.toString() ) != null );
}
@Override
public String filterExpression(String geometryParam, String filterParam) {
return sdoSupport.filterExpression( geometryParam, filterParam );
}
}

View File

@ -7,9 +7,13 @@
package org.hibernate.spatial.dialect.postgis;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import org.hibernate.QueryException;
import org.hibernate.dialect.function.StandardSQLFunction;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.spatial.SpatialFunction;
import org.hibernate.spatial.dialect.SpatialFunctionsRegistry;
import org.hibernate.type.StandardBasicTypes;
import org.hibernate.type.Type;
@ -177,6 +181,11 @@ class PostgisFunctions extends SpatialFunctionsRegistry {
"extent", new ExtentFunction()
);
//register Spatial Filter function
put(
SpatialFunction.filter.name(), new FilterFunction()
);
//other common functions
put(
"dwithin", new StandardSQLFunction(
@ -206,4 +215,26 @@ class PostgisFunctions extends SpatialFunctionsRegistry {
}
}
private static class FilterFunction extends StandardSQLFunction {
public FilterFunction() {
super( "&&" );
}
@Override
public String render(
Type firstArgumentType, List arguments, SessionFactoryImplementor sessionFactory) {
int argumentCount = arguments.size();
if ( argumentCount != 2 ) {
throw new QueryException( String.format( "2 arguments expected, received %d", argumentCount ) );
}
return Stream.of(
String.valueOf( arguments.get( 0 ) ),
getRenderedName( arguments ),
String.valueOf( arguments.get( 1 ) )
).collect( Collectors.joining( " ", "(", ")" ) );
}
}
}

View File

@ -7,6 +7,7 @@
package org.hibernate.spatial.dialect.sqlserver;
import org.hibernate.dialect.function.SQLFunctionTemplate;
import org.hibernate.spatial.SpatialFunction;
import org.hibernate.spatial.dialect.SpatialFunctionsRegistry;
import org.hibernate.type.StandardBasicTypes;
@ -62,5 +63,7 @@ class SqlServerFunctions extends SpatialFunctionsRegistry {
"pointonsurface", new SqlServerMethod( "STPointOnSurface" )
);
// Register spatial filter function.
put( SpatialFunction.filter.name(), new SQLFunctionTemplate( StandardBasicTypes.BOOLEAN, "?1.Filter(?2)" ) );
}
}

View File

@ -0,0 +1,80 @@
/*
* 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.spatial.predicate;
import java.io.Serializable;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.Expression;
import javax.persistence.criteria.Predicate;
import org.hibernate.dialect.Dialect;
import org.hibernate.query.criteria.internal.CriteriaBuilderImpl;
import org.hibernate.query.criteria.internal.ParameterRegistry;
import org.hibernate.query.criteria.internal.Renderable;
import org.hibernate.query.criteria.internal.compile.RenderingContext;
import org.hibernate.query.criteria.internal.predicate.AbstractSimplePredicate;
import org.hibernate.spatial.SpatialDialect;
import org.hibernate.spatial.SpatialFunction;
import org.hibernate.spatial.criterion.SpatialFilter;
import org.hibernate.spatial.dialect.WithCustomJPAFilter;
import org.hibernate.spatial.jts.EnvelopeAdapter;
import org.locationtech.jts.geom.Envelope;
import org.locationtech.jts.geom.Geometry;
/**
* JPA Criteria API {@link Predicate} equivalent of {@link SpatialFilter}.
*/
public class FilterPredicate extends AbstractSimplePredicate implements Serializable {
private final Expression<? extends Geometry> geometry;
private final Expression<? extends Geometry> filter;
public FilterPredicate(
CriteriaBuilder criteriaBuilder, Expression<? extends Geometry> geometry,
Expression<? extends Geometry> filter) {
super( (CriteriaBuilderImpl) criteriaBuilder );
this.geometry = geometry;
this.filter = filter;
}
public FilterPredicate(
CriteriaBuilder criteriaBuilder, Expression<? extends Geometry> geometry,
Geometry filter) {
this( criteriaBuilder, geometry, criteriaBuilder.literal( filter )
);
}
public FilterPredicate(
CriteriaBuilder criteriaBuilder, Expression<? extends Geometry> geometry,
Envelope envelope, int srid) {
this( criteriaBuilder, geometry, EnvelopeAdapter.toPolygon( envelope, srid )
);
}
@Override
public void registerParameters(ParameterRegistry registry) {
Helper.possibleParameter( geometry, registry );
Helper.possibleParameter( filter, registry );
}
@Override
public String render(boolean isNegated, RenderingContext renderingContext) {
String geometryParameter = ( (Renderable) geometry ).render( renderingContext );
String filterParameter = ( (Renderable) filter ).render( renderingContext );
Dialect dialect = renderingContext.getDialect();
if ( !( dialect instanceof SpatialDialect ) ) {
throw new IllegalStateException( "Dialect must be spatially enabled dialect" );
}
if ( dialect instanceof WithCustomJPAFilter ) {
return ( (WithCustomJPAFilter) dialect ).filterExpression( geometryParameter, filterParameter );
}
else {
return SpatialFunction.filter.name() + "(" + geometryParameter + ", " + filterParameter + ") = true";
}
}
}

View File

@ -0,0 +1,575 @@
/*
* 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.spatial.predicate;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.Expression;
import javax.persistence.criteria.Predicate;
import org.hibernate.spatial.SpatialFunction;
import org.hibernate.spatial.criterion.SpatialRestrictions;
import org.locationtech.jts.geom.Envelope;
import org.locationtech.jts.geom.Geometry;
import org.locationtech.jts.geom.Polygon;
/**
* A factory for spatial JPA Criteria API {@link Predicate}s.
*
* @author Daniel Shuy
* @see SpatialRestrictions
*/
public final class SpatialPredicates {
private SpatialPredicates() {
}
/**
* Create a predicate for testing the arguments for "spatially equal" constraint.
*
* @param criteriaBuilder CriteriaBuilder
* @param geometry1 geometry expression
* @param geometry2 geometry expression
*
* @return "spatially equal" predicate
*
* @see SpatialRestrictions#eq(String, Geometry)
*/
public static Predicate eq(
CriteriaBuilder criteriaBuilder, Expression<? extends Geometry> geometry1,
Expression<? extends Geometry> geometry2) {
return booleanExpressionToPredicate(
criteriaBuilder,
criteriaBuilder.function( SpatialFunction.equals.toString(), boolean.class,
geometry1, geometry2
)
);
}
/**
* Create a predicate for testing the arguments for "spatially equal" constraint.
*
* @param criteriaBuilder CriteriaBuilder
* @param geometry1 geometry expression
* @param geometry2 geometry value
*
* @return "spatially equal" predicate
*
* @see #eq(CriteriaBuilder, Expression, Expression)
*/
public static Predicate eq(
CriteriaBuilder criteriaBuilder, Expression<? extends Geometry> geometry1,
Geometry geometry2) {
return eq( criteriaBuilder, geometry1,
criteriaBuilder.literal( geometry2 )
);
}
/**
* Create a predicate for testing the arguments for "spatially within" constraint.
*
* @param criteriaBuilder CriteriaBuilder
* @param geometry1 geometry expression
* @param geometry2 geometry expression
*
* @return "spatially within" predicate
*
* @see SpatialRestrictions#within(String, Geometry)
*/
public static Predicate within(
CriteriaBuilder criteriaBuilder, Expression<? extends Geometry> geometry1,
Expression<? extends Geometry> geometry2) {
return booleanExpressionToPredicate(
criteriaBuilder,
criteriaBuilder.function( SpatialFunction.within.toString(), boolean.class,
geometry1, geometry2
)
);
}
/**
* Create a predicate for testing the arguments for "spatially within" constraint.
*
* @param criteriaBuilder CriteriaBuilder
* @param geometry1 geometry expression
* @param geometry2 geometry value
*
* @return "spatially within" predicate
*
* @see #within(CriteriaBuilder, Expression, Expression)
*/
public static Predicate within(
CriteriaBuilder criteriaBuilder, Expression<? extends Geometry> geometry1,
Geometry geometry2) {
return within( criteriaBuilder, geometry1,
criteriaBuilder.literal( geometry2 )
);
}
/**
* Create a predicate for testing the arguments for "spatially contains" constraint.
*
* @param criteriaBuilder CriteriaBuilder
* @param geometry1 geometry expression
* @param geometry2 geometry expression
*
* @return "spatially contains" predicate
*
* @see SpatialRestrictions#contains(String, Geometry)
*/
public static Predicate contains(
CriteriaBuilder criteriaBuilder, Expression<? extends Geometry> geometry1,
Expression<? extends Geometry> geometry2) {
return booleanExpressionToPredicate(
criteriaBuilder,
criteriaBuilder.function( SpatialFunction.contains.toString(), boolean.class,
geometry1, geometry2
)
);
}
/**
* Create a predicate for testing the arguments for "spatially contains" constraint.
*
* @param criteriaBuilder CriteriaBuilder
* @param geometry1 geometry expression
* @param geometry2 geometry value
*
* @return "spatially contains" predicate
*
* @see #contains(CriteriaBuilder, Expression, Expression)
*/
public static Predicate contains(
CriteriaBuilder criteriaBuilder, Expression<? extends Geometry> geometry1,
Geometry geometry2) {
return contains( criteriaBuilder, geometry1,
criteriaBuilder.literal( geometry2 )
);
}
/**
* Create a predicate for testing the arguments for "spatially crosses" constraint.
*
* @param criteriaBuilder CriteriaBuilder
* @param geometry1 geometry expression
* @param geometry2 geometry expression
*
* @return "spatially crosses" predicate
*
* @see SpatialRestrictions#crosses(String, Geometry)
*/
public static Predicate crosses(
CriteriaBuilder criteriaBuilder, Expression<? extends Geometry> geometry1,
Expression<? extends Geometry> geometry2) {
return booleanExpressionToPredicate(
criteriaBuilder,
criteriaBuilder.function( SpatialFunction.crosses.toString(), boolean.class,
geometry1, geometry2
)
);
}
/**
* Create a predicate for testing the arguments for "spatially crosses" constraint.
*
* @param criteriaBuilder CriteriaBuilder
* @param geometry1 geometry expression
* @param geometry2 geometry value
*
* @return "spatially crosses" predicate
*
* @see #crosses(CriteriaBuilder, Expression, Expression)
*/
public static Predicate crosses(
CriteriaBuilder criteriaBuilder, Expression<? extends Geometry> geometry1,
Geometry geometry2) {
return crosses( criteriaBuilder, geometry1,
criteriaBuilder.literal( geometry2 )
);
}
/**
* Create a predicate for testing the arguments for "spatially disjoint" constraint.
*
* @param criteriaBuilder CriteriaBuilder
* @param geometry1 geometry expression
* @param geometry2 geometry expression
*
* @return "spatially disjoint" predicate
*
* @see SpatialRestrictions#disjoint(String, Geometry)
*/
public static Predicate disjoint(
CriteriaBuilder criteriaBuilder, Expression<? extends Geometry> geometry1,
Expression<? extends Geometry> geometry2) {
return booleanExpressionToPredicate(
criteriaBuilder,
criteriaBuilder.function( SpatialFunction.disjoint.toString(), boolean.class,
geometry1, geometry2
)
);
}
/**
* Create a predicate for testing the arguments for "spatially disjoint" constraint.
*
* @param criteriaBuilder CriteriaBuilder
* @param geometry1 geometry expression
* @param geometry2 geometry value
*
* @return "spatially disjoint" predicate
*
* @see #disjoint(CriteriaBuilder, Expression, Expression)
*/
public static Predicate disjoint(
CriteriaBuilder criteriaBuilder, Expression<? extends Geometry> geometry1,
Geometry geometry2) {
return disjoint( criteriaBuilder, geometry1,
criteriaBuilder.literal( geometry2 )
);
}
/**
* Create a predicate for testing the arguments for "spatially intersects" constraint.
*
* @param criteriaBuilder CriteriaBuilder
* @param geometry1 geometry expression
* @param geometry2 geometry expression
*
* @return "spatially intersects" predicate
*
* @see SpatialRestrictions#intersects(String, Geometry)
*/
public static Predicate intersects(
CriteriaBuilder criteriaBuilder, Expression<? extends Geometry> geometry1,
Expression<? extends Geometry> geometry2) {
return booleanExpressionToPredicate(
criteriaBuilder,
criteriaBuilder.function( SpatialFunction.intersects.toString(), boolean.class,
geometry1, geometry2
)
);
}
/**
* Create a predicate for testing the arguments for "spatially intersects" constraint.
*
* @param criteriaBuilder CriteriaBuilder
* @param geometry1 geometry expression
* @param geometry2 geometry value
*
* @return "spatially intersects" predicate
*
* @see #intersects(CriteriaBuilder, Expression, Expression)
*/
public static Predicate intersects(
CriteriaBuilder criteriaBuilder, Expression<? extends Geometry> geometry1,
Geometry geometry2) {
return intersects( criteriaBuilder, geometry1,
criteriaBuilder.literal( geometry2 )
);
}
/**
* Create a predicate for testing the arguments for "spatially overlaps" constraint.
*
* @param criteriaBuilder CriteriaBuilder
* @param geometry1 geometry expression
* @param geometry2 geometry expression
*
* @return "spatially overlaps" predicate
*
* @see SpatialRestrictions#overlaps(String, Geometry)
*/
public static Predicate overlaps(
CriteriaBuilder criteriaBuilder, Expression<? extends Geometry> geometry1,
Expression<? extends Geometry> geometry2) {
return booleanExpressionToPredicate(
criteriaBuilder,
criteriaBuilder.function( SpatialFunction.overlaps.toString(), boolean.class,
geometry1, geometry2
)
);
}
/**
* Create a predicate for testing the arguments for "spatially overlaps" constraint.
*
* @param criteriaBuilder CriteriaBuilder
* @param geometry1 geometry expression
* @param geometry2 geometry value
*
* @return "spatially overlaps" predicate
*
* @see #overlaps(CriteriaBuilder, Expression, Expression)
*/
public static Predicate overlaps(
CriteriaBuilder criteriaBuilder, Expression<? extends Geometry> geometry1,
Geometry geometry2) {
return overlaps( criteriaBuilder, geometry1,
criteriaBuilder.literal( geometry2 )
);
}
/**
* Create a predicate for testing the arguments for "spatially touches" constraint.
*
* @param criteriaBuilder CriteriaBuilder
* @param geometry1 geometry expression
* @param geometry2 geometry expression
*
* @return "spatially touches" predicate
*
* @see SpatialRestrictions#touches(String, Geometry)
*/
public static Predicate touches(
CriteriaBuilder criteriaBuilder, Expression<? extends Geometry> geometry1,
Expression<? extends Geometry> geometry2) {
return booleanExpressionToPredicate(
criteriaBuilder,
criteriaBuilder.function( SpatialFunction.touches.toString(), boolean.class,
geometry1, geometry2
)
);
}
/**
* Create a predicate for testing the arguments for "spatially touches" constraint.
*
* @param criteriaBuilder CriteriaBuilder
* @param geometry1 geometry expression
* @param geometry2 geometry value
*
* @return "spatially touches" predicate
*
* @see #touches(CriteriaBuilder, Expression, Expression)
*/
public static Predicate touches(
CriteriaBuilder criteriaBuilder, Expression<? extends Geometry> geometry1,
Geometry geometry2) {
return touches( criteriaBuilder, geometry1,
criteriaBuilder.literal( geometry2 )
);
}
/**
* Create a predicate for testing the arguments for bounding box overlap constraint.
*
* @param criteriaBuilder CriteriaBuilder
* @param geometry1 geometry expression
* @param geometry2 geometry expression whose bounding box to use in the comparison
*
* @return bounding box overlap predicate
*
* @see FilterPredicate
* @see SpatialRestrictions#filter(String, Geometry)
*/
public static Predicate filter(
CriteriaBuilder criteriaBuilder, Expression<? extends Geometry> geometry1,
Expression<? extends Geometry> geometry2) {
return new FilterPredicate( criteriaBuilder, geometry1, geometry2 );
}
/**
* Create a predicate for testing the arguments for bounding box overlap constraint.
*
* @param criteriaBuilder CriteriaBuilder
* @param geometry1 geometry expression
* @param geometry2 geometry value whose bounding box to use in the comparison
*
* @return bounding box overlap predicate
*
* @see FilterPredicate
* @see SpatialRestrictions#filter(String, Geometry)
*/
public static Predicate filter(
CriteriaBuilder criteriaBuilder, Expression<? extends Geometry> geometry1,
Geometry geometry2) {
return new FilterPredicate( criteriaBuilder, geometry1, geometry2 );
}
/**
* Create a predicate for testing the arguments for bounding box overlap constraint.
*
* @param criteriaBuilder CriteriaBuilder
* @param geometry geometry expression
* @param envelope envelope or bounding box to use in the comparison
* @param srid the SRID of the bounding box
*
* @return bounding box overlap predicate
*
* @see FilterPredicate
* @see SpatialRestrictions#filter(String, Envelope, int)
*/
public static Predicate filterByPolygon(
CriteriaBuilder criteriaBuilder, Expression<? extends Geometry> geometry,
Envelope envelope, int srid) {
return new FilterPredicate( criteriaBuilder, geometry, envelope, srid );
}
/**
* Create a predicate for testing the arguments for "distance within" constraint.
*
* @param criteriaBuilder CriteriaBuilder
* @param geometry1 geometry expression
* @param geometry2 geometry expression
* @param distance distance expression
*
* @return "distance within" predicate
*
* @see SpatialRestrictions#distanceWithin(String, Geometry, double)
*/
public static Predicate distanceWithin(
CriteriaBuilder criteriaBuilder, Expression<? extends Geometry> geometry1,
Expression<? extends Geometry> geometry2, Expression<Double> distance) {
return booleanExpressionToPredicate(
criteriaBuilder,
criteriaBuilder.function( SpatialFunction.dwithin.toString(), boolean.class,
geometry1, geometry2, distance
)
);
}
/**
* Create a predicate for testing the arguments for "distance within" constraint.
*
* @param criteriaBuilder CriteriaBuilder
* @param geometry1 geometry expression
* @param geometry2 geometry value
* @param distance distance expression
*
* @return "distance within" predicate
*
* @see #distanceWithin(CriteriaBuilder, Expression, Expression, Expression)
*/
public static Predicate distanceWithin(
CriteriaBuilder criteriaBuilder, Expression<? extends Geometry> geometry1,
Geometry geometry2, Expression<Double> distance) {
return distanceWithin( criteriaBuilder, geometry1,
criteriaBuilder.literal( geometry2 ), distance
);
}
/**
* Create a predicate for testing the arguments for "distance within" constraint.
*
* @param criteriaBuilder CriteriaBuilder
* @param geometry1 geometry expression
* @param geometry2 geometry value
* @param distance distance value
*
* @return "distance within" predicate
*
* @see #distanceWithin(CriteriaBuilder, Expression, Expression, Expression)
*/
public static Predicate distanceWithin(
CriteriaBuilder criteriaBuilder, Expression<? extends Geometry> geometry1,
Geometry geometry2, double distance) {
return distanceWithin( criteriaBuilder, geometry1,
criteriaBuilder.literal( geometry2 ), criteriaBuilder.literal( distance )
);
}
/**
* Create a predicate for testing the arguments for "distance within" constraint.
*
* @param criteriaBuilder CriteriaBuilder
* @param geometry1 geometry expression
* @param geometry2 geometry expression
* @param distance distance value
*
* @return "distance within" predicate
*
* @see #distanceWithin(CriteriaBuilder, Expression, Expression, Expression)
*/
public static Predicate distanceWithin(
CriteriaBuilder criteriaBuilder, Expression<? extends Geometry> geometry1,
Expression<? extends Geometry> geometry2, double distance) {
return distanceWithin( criteriaBuilder, geometry1, geometry2,
criteriaBuilder.literal( distance )
);
}
/**
* Create a predicate for testing the arguments for "having srid" constraint.
*
* @param criteriaBuilder CriteriaBuilder
* @param geometry geometry expression
* @param srid SRID expression
*
* @return "having srid" predicate
*
* @see SpatialRestrictions#havingSRID(String, int)
*/
public static Predicate havingSRID(
CriteriaBuilder criteriaBuilder, Expression<? extends Geometry> geometry,
Expression<Integer> srid) {
return criteriaBuilder.equal(
criteriaBuilder.function( SpatialFunction.srid.toString(), int.class, geometry ),
srid
);
}
/**
* Create a predicate for testing the arguments for "having srid" constraint.
*
* @param criteriaBuilder CriteriaBuilder
* @param geometry geometry expression
* @param srid SRID expression
*
* @return "having srid" predicate
*
* @see #havingSRID(CriteriaBuilder, Expression, Expression)
*/
public static Predicate havingSRID(
CriteriaBuilder criteriaBuilder, Expression<? extends Geometry> geometry,
int srid) {
return havingSRID( criteriaBuilder, geometry,
criteriaBuilder.literal( srid )
);
}
/**
* Create a predicate for testing the arguments for "is empty" constraint.
*
* @param criteriaBuilder CriteriaBuilder
* @param geometry geometry expression
*
* @return "is empty" predicate
*
* @see SpatialRestrictions#isEmpty(String)
*/
public static Predicate isEmpty(CriteriaBuilder criteriaBuilder, Expression<? extends Geometry> geometry) {
return booleanExpressionToPredicate(
criteriaBuilder,
criteriaBuilder.function( SpatialFunction.isempty.toString(), boolean.class,
geometry
)
);
}
/**
* Create a predicate for testing the arguments for "is not empty" constraint.
*
* @param criteriaBuilder CriteriaBuilder
* @param geometry geometry expression
*
* @return "is not empty" predicate
*
* @see SpatialRestrictions#isNotEmpty(String)
*/
public static Predicate isNotEmpty(CriteriaBuilder criteriaBuilder, Expression<? extends Geometry> geometry) {
return isEmpty( criteriaBuilder, geometry )
.not();
}
private static Predicate booleanExpressionToPredicate(
CriteriaBuilder criteriaBuilder,
Expression<Boolean> expression) {
return criteriaBuilder.equal( expression, true );
}
}

View File

@ -0,0 +1,264 @@
/*
* 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.spatial.integration;
import java.sql.SQLException;
import java.util.List;
import java.util.Map;
import java.util.function.BiFunction;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;
import org.hibernate.Session;
import org.hibernate.Transaction;
import org.hibernate.spatial.HSMessageLogger;
import org.hibernate.spatial.SpatialFunction;
import org.hibernate.spatial.dialect.hana.HANASpatialDialect;
import org.hibernate.spatial.integration.jts.JtsGeomEntity;
import org.hibernate.spatial.predicate.SpatialPredicates;
import org.hibernate.spatial.testing.SpatialDialectMatcher;
import org.hibernate.spatial.testing.SpatialFunctionalTestCase;
import org.hibernate.testing.Skip;
import org.hibernate.testing.SkipForDialect;
import org.junit.Test;
import org.jboss.logging.Logger;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.fail;
/**
* @see TestSpatialRestrictions
*/
@Skip(condition = SpatialDialectMatcher.class, message = "No Spatial Dialect")
@SkipForDialect(value = HANASpatialDialect.class, comment = "The HANA dialect is tested via org.hibernate.spatial.dialect.hana.TestHANASpatialFunctions", jiraKey = "HHH-12426")
public class TestSpatialPredicates extends SpatialFunctionalTestCase {
private static HSMessageLogger LOG = Logger.getMessageLogger(
HSMessageLogger.class,
TestSpatialPredicates.class.getName()
);
protected HSMessageLogger getLogger() {
return LOG;
}
@Test
public void within() throws SQLException {
if ( !isSupportedByDialect( SpatialFunction.within ) ) {
return;
}
Map<Integer, Boolean> dbexpected = expectationsFactory.getWithin( expectationsFactory.getTestPolygon() );
BiFunction<CriteriaBuilder, Root<JtsGeomEntity>, Predicate> predicateFactory = (criteriaBuilder, root) ->
SpatialPredicates.within( criteriaBuilder, root.get( "geom" ), expectationsFactory.getTestPolygon() );
retrieveAndCompare( dbexpected, predicateFactory );
}
@Test
public void filter() throws SQLException {
if ( !dialectSupportsFiltering() ) {
LOG.info( "Filtering is not supported by Dialect" );
return;
}
Map<Integer, Boolean> dbexpected = expectationsFactory.getFilter( expectationsFactory.getTestPolygon() );
BiFunction<CriteriaBuilder, Root<JtsGeomEntity>, Predicate> predicateFactory = (criteriaBuilder, root) ->
SpatialPredicates.filter( criteriaBuilder, root.get( "geom" ), expectationsFactory.getTestPolygon() );
retrieveAndCompare( dbexpected, predicateFactory );
}
@Test
public void contains() throws SQLException {
if ( !isSupportedByDialect( SpatialFunction.contains ) ) {
return;
}
Map<Integer, Boolean> dbexpected = expectationsFactory.getContains( expectationsFactory.getTestPolygon() );
BiFunction<CriteriaBuilder, Root<JtsGeomEntity>, Predicate> predicateFactory = (criteriaBuilder, root) ->
SpatialPredicates.contains(
criteriaBuilder,
root.get( "geom" ),
expectationsFactory.getTestPolygon()
);
retrieveAndCompare( dbexpected, predicateFactory );
}
@Test
public void crosses() throws SQLException {
if ( !isSupportedByDialect( SpatialFunction.crosses ) ) {
return;
}
Map<Integer, Boolean> dbexpected = expectationsFactory.getCrosses( expectationsFactory.getTestPolygon() );
BiFunction<CriteriaBuilder, Root<JtsGeomEntity>, Predicate> predicateFactory = (criteriaBuilder, root) ->
SpatialPredicates.crosses( criteriaBuilder, root.get( "geom" ), expectationsFactory.getTestPolygon() );
retrieveAndCompare( dbexpected, predicateFactory );
}
@Test
public void touches() throws SQLException {
if ( !isSupportedByDialect( SpatialFunction.touches ) ) {
return;
}
Map<Integer, Boolean> dbexpected = expectationsFactory.getTouches( expectationsFactory.getTestPolygon() );
BiFunction<CriteriaBuilder, Root<JtsGeomEntity>, Predicate> predicateFactory = (criteriaBuilder, root) ->
SpatialPredicates.touches( criteriaBuilder, root.get( "geom" ), expectationsFactory.getTestPolygon() );
retrieveAndCompare( dbexpected, predicateFactory );
}
@Test
public void disjoint() throws SQLException {
if ( !isSupportedByDialect( SpatialFunction.disjoint ) ) {
return;
}
Map<Integer, Boolean> dbexpected = expectationsFactory.getDisjoint( expectationsFactory.getTestPolygon() );
BiFunction<CriteriaBuilder, Root<JtsGeomEntity>, Predicate> predicateFactory = (criteriaBuilder, root) ->
SpatialPredicates.disjoint(
criteriaBuilder,
root.get( "geom" ),
expectationsFactory.getTestPolygon()
);
retrieveAndCompare( dbexpected, predicateFactory );
}
@Test
public void eq() throws SQLException {
if ( !isSupportedByDialect( SpatialFunction.equals ) ) {
return;
}
Map<Integer, Boolean> dbexpected = expectationsFactory.getEquals( expectationsFactory.getTestPolygon() );
BiFunction<CriteriaBuilder, Root<JtsGeomEntity>, Predicate> predicateFactory = (criteriaBuilder, root) ->
SpatialPredicates.eq( criteriaBuilder, root.get( "geom" ), expectationsFactory.getTestPolygon() );
retrieveAndCompare( dbexpected, predicateFactory );
}
@Test
public void intersects() throws SQLException {
if ( !isSupportedByDialect( SpatialFunction.intersects ) ) {
return;
}
Map<Integer, Boolean> dbexpected = expectationsFactory.getIntersects( expectationsFactory.getTestPolygon() );
BiFunction<CriteriaBuilder, Root<JtsGeomEntity>, Predicate> predicateFactory = (criteriaBuilder, root) ->
SpatialPredicates.intersects(
criteriaBuilder,
root.get( "geom" ),
expectationsFactory.getTestPolygon()
);
retrieveAndCompare( dbexpected, predicateFactory );
}
@Test
public void overlaps() throws SQLException {
if ( !isSupportedByDialect( SpatialFunction.overlaps ) ) {
return;
}
Map<Integer, Boolean> dbexpected = expectationsFactory.getOverlaps( expectationsFactory.getTestPolygon() );
BiFunction<CriteriaBuilder, Root<JtsGeomEntity>, Predicate> predicateFactory = (criteriaBuilder, root) ->
SpatialPredicates.overlaps(
criteriaBuilder,
root.get( "geom" ),
expectationsFactory.getTestPolygon()
);
retrieveAndCompare( dbexpected, predicateFactory );
}
@Test
public void dwithin() throws SQLException {
if ( !isSupportedByDialect( SpatialFunction.dwithin ) ) {
return;
}
Map<Integer, Boolean> dbexpected = expectationsFactory.getDwithin( expectationsFactory.getTestPoint(), 30.0 );
BiFunction<CriteriaBuilder, Root<JtsGeomEntity>, Predicate> predicateFactory = (criteriaBuilder, root) ->
SpatialPredicates.distanceWithin(
criteriaBuilder,
root.get( "geom" ),
expectationsFactory.getTestPoint(),
30.0
);
retrieveAndCompare( dbexpected, predicateFactory );
}
@Test
public void isEmpty() throws SQLException {
if ( !isSupportedByDialect( SpatialFunction.isempty ) ) {
return;
}
Map<Integer, Boolean> dbexpected = expectationsFactory.getIsEmpty();
BiFunction<CriteriaBuilder, Root<JtsGeomEntity>, Predicate> predicateFactory = (criteriaBuilder, root) ->
SpatialPredicates.isEmpty( criteriaBuilder, root.get( "geom" ) );
retrieveAndCompare( dbexpected, predicateFactory );
}
@Test
public void isNotEmpty() throws SQLException {
if ( !isSupportedByDialect( SpatialFunction.isempty ) ) {
return;
}
Map<Integer, Boolean> dbexpected = expectationsFactory.getIsNotEmpty();
BiFunction<CriteriaBuilder, Root<JtsGeomEntity>, Predicate> predicateFactory = (criteriaBuilder, root) ->
SpatialPredicates.isNotEmpty( criteriaBuilder, root.get( "geom" ) );
retrieveAndCompare( dbexpected, predicateFactory );
}
@Test
public void havingSRID() throws SQLException {
if ( !isSupportedByDialect( SpatialFunction.srid ) ) {
return;
}
Map<Integer, Boolean> dbexpected = expectationsFactory.havingSRID( 4326 );
BiFunction<CriteriaBuilder, Root<JtsGeomEntity>, Predicate> predicateFactory = (criteriaBuilder, root) ->
SpatialPredicates.havingSRID( criteriaBuilder, root.get( "geom" ), 4326 );
retrieveAndCompare( dbexpected, predicateFactory );
dbexpected = expectationsFactory.havingSRID( 31370 );
predicateFactory = (criteriaBuilder, root) ->
SpatialPredicates.havingSRID( criteriaBuilder, root.get( "geom" ), 31370 );
retrieveAndCompare( dbexpected, predicateFactory );
}
private void retrieveAndCompare(
Map<Integer, Boolean> dbexpected,
BiFunction<CriteriaBuilder, Root<JtsGeomEntity>, Predicate> predicateFactory) {
try (Session session = openSession()) {
Transaction tx = null;
try {
tx = session.beginTransaction();
CriteriaBuilder criteriaBuilder = session.getCriteriaBuilder();
CriteriaQuery<JtsGeomEntity> criteriaQuery = criteriaBuilder.createQuery( JtsGeomEntity.class );
Root<JtsGeomEntity> root = criteriaQuery.from( JtsGeomEntity.class );
criteriaQuery.select( root )
.where( predicateFactory.apply( criteriaBuilder, root ) );
List<JtsGeomEntity> list = session.createQuery( criteriaQuery )
.getResultList();
compare( dbexpected, list );
}
finally {
if ( tx != null ) {
tx.rollback();
}
}
}
}
private void compare(Map<Integer, Boolean> dbexpected, List<JtsGeomEntity> list) {
int cnt = dbexpected.entrySet()
.stream()
.filter( Map.Entry::getValue )
.reduce( 0, (accumulator, entry) -> {
if ( !findInList( entry.getKey(), list ) ) {
fail( String.format( "Expected object with id= %d, but not found in result", entry.getKey() ) );
}
return accumulator + 1;
}, Integer::sum );
assertEquals( cnt, list.size() );
LOG.infof( "Found %d objects within testsuite-suite polygon.", cnt );
}
private boolean findInList(Integer id, List<JtsGeomEntity> list) {
return list.stream()
.anyMatch( entity -> entity.getId().equals( id ) );
}
}

View File

@ -38,7 +38,6 @@ public class TestSupportFactories {
private static Class<? extends TestSupport> getSupportFactoryClass(Dialect dialect) {
String canonicalName = dialect.getClass().getCanonicalName();
if ( ( dialect instanceof SpatialDialect ) && PostgreSQL82Dialect.class.isAssignableFrom( dialect.getClass() ) ) {
//this test works because all postgis dialects ultimately derive of the Postgresql82Dialect
return PostgisTestSupport.class;

View File

@ -8,6 +8,9 @@
package org.hibernate.spatial.testing.dialects.postgis;
import org.hibernate.spatial.integration.TestSpatialFunctions;
import org.hibernate.spatial.integration.TestSpatialPredicates;
import org.hibernate.spatial.integration.TestSpatialRestrictions;
import org.hibernate.spatial.testing.AbstractExpectationsFactory;
import org.hibernate.spatial.testing.DataSourceUtils;
import org.hibernate.spatial.testing.SQLExpressionTemplate;
@ -24,8 +27,10 @@ public class PostgisTestSupport extends TestSupport {
public TestData createTestData(BaseCoreFunctionalTestCase testcase) {
if ( testcase.getClass().getCanonicalName().contains( "TestSpatialFunctions" ) ||
testcase.getClass().getCanonicalName().contains( "TestSpatialRestrictions" ) ) {
Class<? extends BaseCoreFunctionalTestCase> testcaseClass = testcase.getClass();
if ( testcaseClass == TestSpatialFunctions.class ||
testcaseClass == TestSpatialRestrictions.class ||
testcaseClass == TestSpatialPredicates.class ) {
return TestData.fromFile( "postgis-functions-test.xml" );
}
return TestData.fromFile( "test-data-set.xml" );

32
test-case-guide.adoc Normal file
View File

@ -0,0 +1,32 @@
= Test Case Guide
:toc:
This is meant as a guide for writing test cases to be attached to bug reports in the Hibernate Jira. Really most of the information here works just as well when asking for help on community help channels (forums, IRC, HipChat, etc).
== Write a good test
There are a number of tenants that make up a good test case as opposed to a poor one. In fact there are a few guides for this across the web including (http://stackoverflow.com/help/mcve[MCVE]) and (http://sscce.org/[SSCCE]). These guides all assert the same ideas albeit using different terms. Given the ubiquity of StackOverflow and the fact that the MCVE guidelines were written specifically for StackOverflow, we will use those terms here as we assume most developers have seen them before:
* (M)inimal - Provide just the minimal information needed. If second level caching is irrelevant to the bug report then the test should not use second level caching. If entity inheritance is irrelevant then do not use it in the test. If your application uses Spring Data, remove Spring Data from the test.
* (C)omplete - Provide all information needed to reproduce the problem. If a bug only occurs when using bytecode enhancement, then the test should include bytecode enhancement. In other words the test should be self-contained.
* (V)erifiable - The test should actually reproduce the problem being reported.
== Test templates
The Hibernate team maintains a set of "test templates" intended to help developers write tests. These test templates are maintained in GitHub @ https://github.com/hibernate/hibernate-test-case-templates/tree/master/orm[hibernate-test-case-templates]
* If you want to use the Hibernate native API, you should follow the instructions from http://in.relation.to/2015/06/26/hibernate-test-case-templates/[this article].
* If you want to use JPA, you should use the JPA templates that were detailed in http://in.relation.to/2016/01/14/hibernate-jpa-test-case-template/[this article].
NOTE: the test templates are generally not a good starting point for problems building the SessionFactory/EntityManager. In JUnit terms they manage the SessionFactory/EntityManager as set-up and teardown constructs._
== Annotations
When using "test templates" you can annotate a single test or a whole test class with one of the following annotations:
* FailureExpected - allows to skip a single test or all test of a class, because test failures are expected. The test will acutally run, but not lead to an error report. In fact if a test is marked with `@FailureExpected` and the test actually succeed an error occurs. As a parameters to this annotation a jira key is required.
* RequiresDialect - tests methods/classes annotated with `@RequiresDialect` will only run if the current Dialect is matching the one specified on as annotation parameter. You can also specify a comment and/or jira key explaining why this test requires a certain dialect
* RequiresDialectFeature - tests methods/classes annotated with `@RequiresDialectFeature` will only run if the current Dialect offers the specified feature. Examples for this features are `SupportsSequences`, `SupportsExpectedLobUsagePattern` or `SupportsIdentityColumns`. You can add more feature if you need to. Have a look at `DialectChecks`.
* SkipForDialect - tests methods/classes annotated with `@SkipForDialect` will not run if the current Dialect is matching the one specified on as annotation parameter. You can also specify a comment and/or jira key explaining why this test has to be skipped for the Dialect.

View File

@ -6,6 +6,7 @@
*/
package org.hibernate.orm.tooling.gradle;
import org.gradle.api.Action;
import org.gradle.api.Plugin;
import org.gradle.api.Project;
import org.gradle.api.Task;
@ -43,10 +44,35 @@ public class HibernatePlugin implements Plugin<Project> {
final Task compileTask = project.getTasks().findByName( sourceSet.getCompileJavaTaskName() );
assert compileTask != null;
compileTask.doLast(
task -> EnhancementHelper.enhance( sourceSet, hibernateExtension.enhance, project )
);
compileTask.doLast(new EnhancerAction( sourceSet, hibernateExtension, project ));
}
}
/**
* Gradle doesn't allow lambdas in doLast or doFirst configurations and causing up-to-date checks
* to fail. Extracting the lambda to an inner class works around this issue.
*
* @link https://github.com/gradle/gradle/issues/5510
*/
private static class EnhancerAction implements Action<Task> {
private final SourceSet sourceSet;
private final HibernateExtension hibernateExtension;
private final Project project;
private EnhancerAction(SourceSet sourceSet, HibernateExtension hibernateExtension, Project project) {
this.sourceSet = sourceSet;
this.hibernateExtension = hibernateExtension;
this.project = project;
}
@Override
public void execute(Task task) {
EnhancementHelper.enhance( sourceSet, hibernateExtension.enhance, project );
}
}
}