Merge remote-tracking branch 'upstream/master' into wip/6.0
This commit is contained in:
commit
abe1e656f7
|
@ -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]
|
||||
----
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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 -> {
|
||||
|
|
|
@ -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() {
|
||||
|
|
|
@ -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 );
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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 );
|
||||
|
|
|
@ -979,7 +979,7 @@ public class SessionImpl
|
|||
}
|
||||
|
||||
@Override
|
||||
public final Object internalLoad(
|
||||
public Object internalLoad(
|
||||
String entityName,
|
||||
Object id,
|
||||
boolean eager,
|
||||
|
|
|
@ -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" );
|
||||
|
|
|
@ -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 );
|
||||
}
|
||||
}
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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 );
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
}
|
|
@ -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();
|
||||
}
|
||||
}
|
|
@ -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();
|
||||
}
|
||||
}
|
|
@ -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 );
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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();
|
||||
}
|
|
@ -80,7 +80,7 @@ public abstract class BaseEntityManagerFunctionalTestCase extends BaseUnitTestCa
|
|||
afterEntityManagerFactoryBuilt();
|
||||
}
|
||||
|
||||
private PersistenceUnitDescriptor buildPersistenceUnitDescriptor() {
|
||||
protected PersistenceUnitDescriptor buildPersistenceUnitDescriptor() {
|
||||
return new TestingPersistenceUnitDescriptorImpl( getClass().getSimpleName() );
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
|
@ -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() {
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -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 ) );
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
@ -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) {
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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="$@"
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
|
@ -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( " ", "(", ")" ) );
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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' ";
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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 );
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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" ) );
|
||||
|
|
|
@ -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 );
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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( " ", "(", ")" ) );
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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)" ) );
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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";
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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 );
|
||||
}
|
||||
}
|
|
@ -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 ) );
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
|
|
|
@ -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" );
|
||||
|
|
|
@ -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.
|
|
@ -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 );
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue