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

This commit is contained in:
Andrea Boriero 2020-05-14 10:00:59 +01:00
commit 257e479e92
27 changed files with 2223 additions and 718 deletions

View File

@ -277,8 +277,9 @@ If for some reason it is not able to determine the proper one or you want to use
|Firebird |Support for the Firebird database
|FrontBase |Support for the Frontbase database
|H2 |Support for the H2 database
|HANAColumnStore |Support for the SAP HANA database column store. This is the recommended dialect for the SAP HANA database.
|HANARowStore |Support for the SAP HANA database row store
|HANACloudColumnStore |Support for the SAP HANA Cloud database column store.
|HANAColumnStore |Support for the SAP HANA database column store, version 2.x. This is the recommended dialect for the SAP HANA database. May work with SAP HANA, version 1.x
|HANARowStore |Support for the SAP HANA database row store, version 2.x. May work with SAP HANA, version 1.x
|HSQL |Support for the HSQL (HyperSQL) database
|Informix |Support for the Informix database
|Ingres |Support for the Ingres database, version 9.2

View File

@ -18,7 +18,7 @@ ext {
jnpVersion = '5.0.6.CR1'
hibernateCommonsVersion = '5.1.0.Final'
hibernateValidatorVersion = '6.0.13.Final'
hibernateValidatorVersion = '6.1.5.Final'
validationApiVersion = '2.0.1.Final'
elVersion = '3.0.1-b09'

View File

@ -21,6 +21,7 @@ import org.hibernate.dialect.DerbyTenSixDialect;
import org.hibernate.dialect.Dialect;
import org.hibernate.dialect.FirebirdDialect;
import org.hibernate.dialect.H2Dialect;
import org.hibernate.dialect.HANACloudColumnStoreDialect;
import org.hibernate.dialect.HANAColumnStoreDialect;
import org.hibernate.dialect.HANARowStoreDialect;
import org.hibernate.dialect.HSQLDialect;
@ -124,6 +125,9 @@ public class DefaultDialectSelector implements LazyServiceResolver<Dialect> {
if ( name.equals( "H2" ) ) {
return H2Dialect.class;
}
if ( name.equals( "HANACloudColumnStore" ) ) {
return HANACloudColumnStoreDialect.class;
}
if ( name.equals( "HANAColumnStore" ) ) {
return HANAColumnStoreDialect.class;
}

View File

@ -11,6 +11,9 @@ import static net.bytebuddy.matcher.ElementMatchers.named;
import javax.persistence.Id;
import net.bytebuddy.description.NamedElement;
import net.bytebuddy.description.type.TypeDefinition;
import net.bytebuddy.matcher.ElementMatcher;
import net.bytebuddy.utility.OpenedClassReader;
import org.hibernate.bytecode.enhance.internal.bytebuddy.EnhancerImpl.AnnotatedFieldDescription;
import org.hibernate.bytecode.enhance.spi.EnhancementException;
@ -63,10 +66,11 @@ final class FieldAccessEnhancer implements AsmVisitorWrapper.ForDeclaredMethods.
return;
}
AnnotatedFieldDescription field = findField( owner, name, desc );
TypeDescription declaredOwnerType = findDeclaredType( owner );
AnnotatedFieldDescription field = findField( declaredOwnerType, name, desc );
if ( ( enhancementContext.isEntityClass( field.getDeclaringType().asErasure() )
|| enhancementContext.isCompositeClass( field.getDeclaringType().asErasure() ) )
if ( ( enhancementContext.isEntityClass( declaredOwnerType.asErasure() )
|| enhancementContext.isCompositeClass( declaredOwnerType.asErasure() ) )
&& !field.getType().asErasure().equals( managedCtClass )
&& enhancementContext.isPersistentField( field )
&& !field.hasAnnotation( Id.class )
@ -110,23 +114,37 @@ final class FieldAccessEnhancer implements AsmVisitorWrapper.ForDeclaredMethods.
};
}
private AnnotatedFieldDescription findField(String owner, String name, String desc) {
private TypeDescription findDeclaredType(String name) {
//Classpool#describe does not accept '/' in the description name as it expects a class name
final String cleanedOwner = owner.replace( '/', '.' );
final TypePool.Resolution resolution = classPool.describe( cleanedOwner );
final String cleanedName = name.replace( '/', '.' );
final TypePool.Resolution resolution = classPool.describe( cleanedName );
if ( !resolution.isResolved() ) {
final String msg = String.format(
"Unable to perform extended enhancement - Unable to locate [%s]",
cleanedOwner
cleanedName
);
throw new EnhancementException( msg );
}
FieldList<?> fields = resolution.resolve().getDeclaredFields().filter( named( name ).and( hasDescriptor( desc ) ) );
return resolution.resolve();
}
private AnnotatedFieldDescription findField(TypeDescription declaredOwnedType, String name, String desc) {
TypeDefinition ownerType = declaredOwnedType;
ElementMatcher.Junction<NamedElement.WithDescriptor> fieldFilter = named( name ).and( hasDescriptor( desc ) );
FieldList<?> fields = ownerType.getDeclaredFields().filter( fieldFilter );
// Look in the superclasses if necessary
while ( fields.isEmpty() && ownerType.getSuperClass() != null ) {
ownerType = ownerType.getSuperClass();
fields = ownerType.getDeclaredFields().filter( fieldFilter );
}
if ( fields.size() != 1 ) {
final String msg = String.format(
"Unable to perform extended enhancement - No unique field [%s] defined by [%s]",
name,
cleanedOwner
declaredOwnedType.getName()
);
throw new EnhancementException( msg );
}

View File

@ -305,4 +305,9 @@ public class EnhancementAsProxyLazinessInterceptor extends AbstractLazyLoadInter
public Object getIdentifier() {
return entityKey.getIdentifier();
}
//Mostly useful for testing
public boolean isInitialized() {
return initialized;
}
}

View File

@ -1312,8 +1312,8 @@ public class SessionImpl
}
private void doFlush() {
checkTransactionNeededForUpdateOperation();
pulseTransactionCoordinator();
checkTransactionNeededForUpdateOperation();
try {
if ( persistenceContext.getCascadeLevel() > 0 ) {

View File

@ -92,6 +92,8 @@ import org.hibernate.engine.spi.SelfDirtinessTracker;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.engine.spi.SharedSessionContractImplementor;
import org.hibernate.engine.spi.ValueInclusion;
import org.hibernate.event.spi.EventSource;
import org.hibernate.event.spi.LoadEvent;
import org.hibernate.id.IdentifierGenerator;
import org.hibernate.id.PostInsertIdentifierGenerator;
import org.hibernate.id.PostInsertIdentityPersister;
@ -235,7 +237,6 @@ public abstract class AbstractEntityPersister
public static final String ENTITY_CLASS = "class";
private final String sqlAliasStem;
private final SingleIdEntityLoader singleIdEntityLoader;
@ -244,9 +245,6 @@ public abstract class AbstractEntityPersister
private SqmMultiTableMutationStrategy sqmMultiTableMutationStrategy;
private final NavigableRole navigableRole;
// moved up from AbstractEntityPersister ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@ -331,7 +329,6 @@ public abstract class AbstractEntityPersister
private final Set<String> affectingFetchProfileNames = new HashSet<>();
private final Map uniqueKeyLoaders = new HashMap();
private final Map lockers = new HashMap();
@ -2610,7 +2607,6 @@ public abstract class AbstractEntityPersister
}
public Object loadByUniqueKey(
String propertyName,
Object uniqueKey,
@ -4503,12 +4499,21 @@ public abstract class AbstractEntityPersister
final EntityKey entityKey = proxyInterceptor.getEntityKey();
final Serializable identifier = entityKey.getIdentifier();
final Object loaded = singleIdEntityLoader.load(
identifier,
entity,
LockOptions.READ,
session
);
LoadEvent loadEvent = new LoadEvent( identifier, entity, (EventSource)session, false );
Object loaded = null;
if ( canReadFromCache ) {
loaded = CacheEntityLoaderHelper.INSTANCE.loadFromSecondLevelCache( loadEvent, this, entityKey );
}
if ( loaded == null ) {
loaded = singleIdEntityLoader.load(
identifier,
entity,
LockOptions.READ,
session
);
}
if ( loaded == null ) {
final PersistenceContext persistenceContext = session.getPersistenceContext();

View File

@ -56,6 +56,7 @@ public class HibernateSchemaManagementTool implements SchemaManagementTool, Serv
private static final Logger log = Logger.getLogger( HibernateSchemaManagementTool.class );
private ServiceRegistry serviceRegistry;
private GenerationTarget customTarget;
@Override
public void injectServices(ServiceRegistryImplementor serviceRegistry) {
@ -107,6 +108,15 @@ public class HibernateSchemaManagementTool implements SchemaManagementTool, Serv
return JdbcMetadaAccessStrategy.interpretSetting( options );
}
@Override
public void setCustomDatabaseGenerationTarget(GenerationTarget generationTarget) {
this.customTarget = generationTarget;
}
GenerationTarget getCustomDatabaseGenerationTarget() {
return customTarget;
}
GenerationTarget[] buildGenerationTargets(
TargetDescriptor targetDescriptor,
JdbcContext jdbcContext,
@ -132,7 +142,10 @@ public class HibernateSchemaManagementTool implements SchemaManagementTool, Serv
}
if ( targetDescriptor.getTargetTypes().contains( TargetType.DATABASE ) ) {
targets[index] = new GenerationTargetToDatabase( getDdlTransactionIsolator( jdbcContext ), true );
targets[index] = customTarget == null
? new GenerationTargetToDatabase( getDdlTransactionIsolator( jdbcContext ), true )
: customTarget;
index++;
}
return targets;

View File

@ -422,7 +422,7 @@ public class SchemaDropperImpl implements SchemaDropper {
SourceDescriptor sourceDescriptor) {
final JournalingGenerationTarget target = new JournalingGenerationTarget();
doDrop( metadata, options, tool.getServiceRegistry().getService( JdbcEnvironment.class ).getDialect(), sourceDescriptor, target );
return new DelayedDropActionImpl( target.commands );
return new DelayedDropActionImpl( target.commands, tool.getCustomDatabaseGenerationTarget() );
}
/**
@ -513,9 +513,11 @@ public class SchemaDropperImpl implements SchemaDropper {
private static final CoreMessageLogger log = CoreLogging.messageLogger( DelayedDropActionImpl.class );
private final ArrayList<String> commands;
private GenerationTarget target;
public DelayedDropActionImpl(ArrayList<String> commands) {
public DelayedDropActionImpl(ArrayList<String> commands, GenerationTarget target) {
this.commands = commands;
this.target = target;
}
@Override
@ -523,10 +525,14 @@ public class SchemaDropperImpl implements SchemaDropper {
log.startingDelayedSchemaDrop();
final JdbcContext jdbcContext = new JdbcContextDelayedDropImpl( serviceRegistry );
final GenerationTargetToDatabase target = new GenerationTargetToDatabase(
serviceRegistry.getService( TransactionCoordinatorBuilder.class ).buildDdlTransactionIsolator( jdbcContext ),
true
);
if ( target == null ) {
target = new GenerationTargetToDatabase(
serviceRegistry.getService( TransactionCoordinatorBuilder.class )
.buildDdlTransactionIsolator( jdbcContext ),
true
);
}
target.prepare();
try {

View File

@ -10,6 +10,7 @@ import java.util.Map;
import org.hibernate.Incubating;
import org.hibernate.service.Service;
import org.hibernate.tool.schema.internal.exec.GenerationTarget;
/**
* Contract for schema management tool integration.
@ -22,4 +23,13 @@ public interface SchemaManagementTool extends Service {
SchemaDropper getSchemaDropper(Map options);
SchemaMigrator getSchemaMigrator(Map options);
SchemaValidator getSchemaValidator(Map options);
/**
* This allows to set an alternative implementation for the Database
* generation target.
* Used by Hibernate Reactive so that it can use the reactive database
* access rather than needing a JDBC connection.
* @param generationTarget the custom instance to use.
*/
void setCustomDatabaseGenerationTarget(GenerationTarget generationTarget);
}

View File

@ -8,7 +8,7 @@ package org.hibernate.test.bytecode.enhancement.basic;
import org.hibernate.engine.spi.ManagedEntity;
import org.hibernate.engine.spi.PersistentAttributeInterceptable;
import org.hibernate.engine.spi.PersistentAttributeInterceptor;
import org.hibernate.testing.bytecode.enhancement.BytecodeEnhancerRunner;
import org.hibernate.testing.bytecode.enhancement.EnhancerTestUtils;
import org.junit.Assert;
@ -20,7 +20,6 @@ import javax.persistence.Id;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Set;
import static org.hibernate.testing.junit4.ExtraAssertions.assertTyping;
import static org.junit.Assert.assertArrayEquals;
@ -115,104 +114,6 @@ public class BasicEnhancementTest {
// --- //
public static class ObjectAttributeMarkerInterceptor implements PersistentAttributeInterceptor {
public static final Object READ_MARKER = new Object();
public static final Object WRITE_MARKER = new Object();
@Override
public boolean readBoolean(Object obj, String name, boolean oldValue) {
return oldValue;
}
@Override
public boolean writeBoolean(Object obj, String name, boolean oldValue, boolean newValue) {
return newValue;
}
@Override
public byte readByte(Object obj, String name, byte oldValue) {
return oldValue;
}
@Override
public byte writeByte(Object obj, String name, byte oldValue, byte newValue) {
return newValue;
}
@Override
public char readChar(Object obj, String name, char oldValue) {
return oldValue;
}
@Override
public char writeChar(Object obj, String name, char oldValue, char newValue) {
return newValue;
}
@Override
public short readShort(Object obj, String name, short oldValue) {
return oldValue;
}
@Override
public short writeShort(Object obj, String name, short oldValue, short newValue) {
return newValue;
}
@Override
public int readInt(Object obj, String name, int oldValue) {
return oldValue;
}
@Override
public int writeInt(Object obj, String name, int oldValue, int newValue) {
return newValue;
}
@Override
public float readFloat(Object obj, String name, float oldValue) {
return oldValue;
}
@Override
public float writeFloat(Object obj, String name, float oldValue, float newValue) {
return newValue;
}
@Override
public double readDouble(Object obj, String name, double oldValue) {
return oldValue;
}
@Override
public double writeDouble(Object obj, String name, double oldValue, double newValue) {
return newValue;
}
@Override
public long readLong(Object obj, String name, long oldValue) {
return oldValue;
}
@Override
public long writeLong(Object obj, String name, long oldValue, long newValue) {
return newValue;
}
@Override
public Object readObject(Object obj, String name, Object oldValue) {
return READ_MARKER;
}
@Override
public Object writeObject(Object obj, String name, Object oldValue, Object newValue) {
return WRITE_MARKER;
}
}
// --- //
@Entity
private static class SimpleEntity {

View File

@ -2,10 +2,13 @@ package org.hibernate.test.bytecode.enhancement.basic;
import org.hibernate.bytecode.enhance.spi.DefaultEnhancementContext;
import org.hibernate.bytecode.enhance.spi.UnloadedClass;
import org.hibernate.engine.spi.PersistentAttributeInterceptable;
import org.hibernate.testing.TestForIssue;
import org.hibernate.testing.bytecode.enhancement.BytecodeEnhancerRunner;
import org.hibernate.testing.bytecode.enhancement.CustomEnhancementContext;
import org.hibernate.testing.bytecode.enhancement.EnhancerTestContext;
import org.hibernate.testing.bytecode.enhancement.EnhancerTestUtils;
import org.junit.Test;
import org.junit.runner.RunWith;
@ -15,6 +18,9 @@ import javax.persistence.Version;
import static org.hibernate.testing.bytecode.enhancement.EnhancerTestUtils.checkDirtyTracking;
import static org.hibernate.testing.bytecode.enhancement.EnhancerTestUtils.clearDirtyTracking;
import static org.junit.Assert.assertNotSame;
import static org.junit.Assert.assertSame;
import static org.junit.Assume.assumeTrue;
/**
* @author Luis Barreiro
@ -54,11 +60,39 @@ public class InheritedTest {
checkDirtyTracking( bob, "rate", "oca" );
}
// Adapted from BasicEnhancementTest#basicExtendedEnhancementTest
@Test
@TestForIssue(jiraKey = "HHH-14006")
public void extendedEnhancementTest() {
// This test only works if lazy loading bytecode enhancement is enabled,
// otherwise extended bytecode enhancement does not do anything we can check.
assumeTrue( PersistentAttributeInterceptable.class.isAssignableFrom( Employee.class ) );
Employee entity = new Employee();
( (PersistentAttributeInterceptable) entity ).$$_hibernate_setInterceptor( new ObjectAttributeMarkerInterceptor() );
Object decoy = new Object();
// This accesses "anUnspecifiedObject" on a variable of type Employee,
// but "anUnspecifiedObject" is defined the superclass Person.
// Such "virtual" access used to break extended bytecode enhancement.
entity.anUnspecifiedObject = decoy;
Object gotByReflection = EnhancerTestUtils.getFieldByReflection( entity, "anUnspecifiedObject" );
assertNotSame( decoy, gotByReflection );
assertSame( ObjectAttributeMarkerInterceptor.WRITE_MARKER, gotByReflection );
Object gotByEnhancedDirectAccess = entity.anUnspecifiedObject;
assertNotSame( decoy, gotByEnhancedDirectAccess );
assertSame( ObjectAttributeMarkerInterceptor.READ_MARKER, gotByEnhancedDirectAccess );
}
// --- //
@Entity
private static abstract class Person {
Object anUnspecifiedObject;
@Id
String name;

View File

@ -2,10 +2,14 @@ package org.hibernate.test.bytecode.enhancement.basic;
import org.hibernate.bytecode.enhance.spi.DefaultEnhancementContext;
import org.hibernate.bytecode.enhance.spi.UnloadedClass;
import org.hibernate.engine.spi.PersistentAttributeInterceptable;
import org.hibernate.testing.TestForIssue;
import org.hibernate.testing.bytecode.enhancement.BytecodeEnhancerRunner;
import org.hibernate.testing.bytecode.enhancement.CustomEnhancementContext;
import org.hibernate.testing.bytecode.enhancement.EnhancerTestContext;
import org.hibernate.testing.bytecode.enhancement.EnhancerTestUtils;
import org.junit.Assume;
import org.junit.Test;
import org.junit.runner.RunWith;
@ -16,6 +20,9 @@ import javax.persistence.Version;
import static org.hibernate.testing.bytecode.enhancement.EnhancerTestUtils.checkDirtyTracking;
import static org.hibernate.testing.bytecode.enhancement.EnhancerTestUtils.clearDirtyTracking;
import static org.junit.Assert.assertNotSame;
import static org.junit.Assert.assertSame;
import static org.junit.Assume.assumeTrue;
/**
* @author Luis Barreiro
@ -41,11 +48,39 @@ public class MappedSuperclassTest {
checkDirtyTracking( charles, "title", "oca" );
}
// Adapted from BasicEnhancementTest#basicExtendedEnhancementTest
@Test
@TestForIssue(jiraKey = "HHH-14006")
public void extendedEnhancementTest() {
// This test only works if lazy loading bytecode enhancement is enabled,
// otherwise extended bytecode enhancement does not do anything we can check.
assumeTrue( PersistentAttributeInterceptable.class.isAssignableFrom( Employee.class ) );
Employee entity = new Employee();
( (PersistentAttributeInterceptable) entity ).$$_hibernate_setInterceptor( new ObjectAttributeMarkerInterceptor() );
Object decoy = new Object();
// This accesses "name" on a variable of type Employee,
// but "anUnspecifiedObject" is defined the superclass Person.
// Such "virtual" access used to break extended bytecode enhancement.
entity.anUnspecifiedObject = decoy;
Object gotByReflection = EnhancerTestUtils.getFieldByReflection( entity, "anUnspecifiedObject" );
assertNotSame( decoy, gotByReflection );
assertSame( ObjectAttributeMarkerInterceptor.WRITE_MARKER, gotByReflection );
Object gotByEnhancedDirectAccess = entity.anUnspecifiedObject;
assertNotSame( decoy, gotByEnhancedDirectAccess );
assertSame( ObjectAttributeMarkerInterceptor.READ_MARKER, gotByEnhancedDirectAccess );
}
// --- //
@MappedSuperclass
private static class Person {
Object anUnspecifiedObject;
@Id
String name;

View File

@ -0,0 +1,105 @@
/*
* 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.bytecode.enhancement.basic;
import org.hibernate.engine.spi.PersistentAttributeInterceptor;
public class ObjectAttributeMarkerInterceptor implements PersistentAttributeInterceptor {
public static final Object READ_MARKER = new Object();
public static final Object WRITE_MARKER = new Object();
@Override
public boolean readBoolean(Object obj, String name, boolean oldValue) {
return oldValue;
}
@Override
public boolean writeBoolean(Object obj, String name, boolean oldValue, boolean newValue) {
return newValue;
}
@Override
public byte readByte(Object obj, String name, byte oldValue) {
return oldValue;
}
@Override
public byte writeByte(Object obj, String name, byte oldValue, byte newValue) {
return newValue;
}
@Override
public char readChar(Object obj, String name, char oldValue) {
return oldValue;
}
@Override
public char writeChar(Object obj, String name, char oldValue, char newValue) {
return newValue;
}
@Override
public short readShort(Object obj, String name, short oldValue) {
return oldValue;
}
@Override
public short writeShort(Object obj, String name, short oldValue, short newValue) {
return newValue;
}
@Override
public int readInt(Object obj, String name, int oldValue) {
return oldValue;
}
@Override
public int writeInt(Object obj, String name, int oldValue, int newValue) {
return newValue;
}
@Override
public float readFloat(Object obj, String name, float oldValue) {
return oldValue;
}
@Override
public float writeFloat(Object obj, String name, float oldValue, float newValue) {
return newValue;
}
@Override
public double readDouble(Object obj, String name, double oldValue) {
return oldValue;
}
@Override
public double writeDouble(Object obj, String name, double oldValue, double newValue) {
return newValue;
}
@Override
public long readLong(Object obj, String name, long oldValue) {
return oldValue;
}
@Override
public long writeLong(Object obj, String name, long oldValue, long newValue) {
return newValue;
}
@Override
public Object readObject(Object obj, String name, Object oldValue) {
return READ_MARKER;
}
@Override
public Object writeObject(Object obj, String name, Object oldValue, Object newValue) {
return WRITE_MARKER;
}
}

View File

@ -0,0 +1,50 @@
/*
* 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.cache;
import javax.persistence.Cacheable;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import org.hibernate.annotations.CacheConcurrencyStrategy;
@Entity
@Cacheable
@org.hibernate.annotations.Cache(usage = CacheConcurrencyStrategy.READ_WRITE)
public class Continent {
private Long id;
private String code;
private String name;
@Id
@GeneratedValue
public Long getId() {
return id;
}
public void setId(final Long id) {
this.id = id;
}
public String getCode() {
return code;
}
public void setCode(final String code) {
this.code = code;
}
public String getName() {
return name;
}
public void setName(final String name) {
this.name = name;
}
}

View File

@ -0,0 +1,64 @@
/*
* 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.cache;
import javax.persistence.Cacheable;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.ManyToOne;
import org.hibernate.annotations.Cache;
import org.hibernate.annotations.CacheConcurrencyStrategy;
@Entity
@Cacheable
@org.hibernate.annotations.Cache(usage = CacheConcurrencyStrategy.READ_WRITE)
public class Country {
private Long id;
private String code;
private String name;
private Continent continent;
@Id
@GeneratedValue
public Long getId() {
return id;
}
public void setId(final Long id) {
this.id = id;
}
public String getCode() {
return code;
}
public void setCode(final String code) {
this.code = code;
}
public String getName() {
return name;
}
public void setName(final String name) {
this.name = name;
}
@ManyToOne(fetch = FetchType.LAZY)
@Cache(usage = CacheConcurrencyStrategy.READ_ONLY)
public Continent getContinent() {
return continent;
}
public void setContinent(final Continent continent) {
this.continent = continent;
}
}

View File

@ -0,0 +1,160 @@
/*
* 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.cache;
import java.util.concurrent.atomic.AtomicLong;
import org.hibernate.bytecode.enhance.spi.interceptor.EnhancementAsProxyLazinessInterceptor;
import org.hibernate.bytecode.enhance.spi.interceptor.LazyAttributeLoadingInterceptor;
import org.hibernate.cache.spi.CacheImplementor;
import org.hibernate.cfg.AvailableSettings;
import org.hibernate.cfg.Configuration;
import org.hibernate.cfg.Environment;
import org.hibernate.engine.spi.PersistentAttributeInterceptable;
import org.hibernate.stat.Statistics;
import org.hibernate.testing.TestForIssue;
import org.hibernate.testing.bytecode.enhancement.BytecodeEnhancerRunner;
import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase;
import org.junit.Test;
import org.junit.runner.RunWith;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
/**
* Tests to verify that even when dealing with Enhanced Proxies, we will still attempt
* to load them from 2LC in preference of loading from the DB.
*
* @author Sanne Grinovero
*/
@TestForIssue( jiraKey = "HHH-14004" )
@RunWith(BytecodeEnhancerRunner.class)
public class EnhancedProxyCacheTest extends BaseCoreFunctionalTestCase {
private static final AtomicLong countryId = new AtomicLong();
@Override
protected void configure(Configuration cfg) {
super.configure( cfg );
cfg.setProperty( AvailableSettings.ALLOW_ENHANCEMENT_AS_PROXY, "true" );
cfg.setProperty( Environment.GENERATE_STATISTICS, "true" );
cfg.setProperty( Environment.USE_SECOND_LEVEL_CACHE, "true" );
}
@Override
protected Class<?>[] getAnnotatedClasses() {
return new Class[] { Country.class, Continent.class };
}
@Test
public void testPreferenceFor2LCOverUninitializedProxy() throws Exception {
final Statistics stats = sessionFactory().getStatistics();
storeTestData();
clearAllCaches();
stats.clear();
assertTrue( stats.isStatisticsEnabled() );
assertEquals( 0, stats.getEntityFetchCount() );
assertEquals( 0, stats.getSecondLevelCacheHitCount() );
// First we load the Country once, then trigger initialization of the related Continent proxy.
// 2LC is empty, so stats should show that these objects are being loaded from the DB.
inSession( s -> {
Country nl = s.get( Country.class, countryId.get() );
assertNotNull( nl );
assertEquals( 0, stats.getSecondLevelCacheHitCount() );
assertEquals( 1, stats.getSecondLevelCacheMissCount() );
assertEquals( 1, stats.getEntityLoadCount() );
Continent continent = nl.getContinent();
//Check that this is indeed an enhanced proxy so to ensure we're testing in the right conditions.
//The following casts should not fail:
final PersistentAttributeInterceptable interceptable = (PersistentAttributeInterceptable) continent;
final EnhancementAsProxyLazinessInterceptor interceptor = (EnhancementAsProxyLazinessInterceptor) interceptable.$$_hibernate_getInterceptor();
assertFalse( interceptor.isInitialized() );
assertFalse( interceptor.isAttributeLoaded( "code" ) );
//Trigger initialization of the enhanced proxy:
assertEquals( "EU", continent.getCode() );
assertTrue( interceptor.isInitialized() );
assertEquals( 0, stats.getSecondLevelCacheHitCount() );
assertEquals( 2, stats.getEntityLoadCount() );
} );
stats.clear();
//Now load the same objects again; we expect to hit 2LC this time,
//and we should see no needs to hit the DB.
//Also, since all data is readily available we won't need to make
//all attributes lazy.
inSession( s -> {
assertEquals( 0, stats.getSecondLevelCacheHitCount() );
assertEquals( 0, stats.getSecondLevelCacheMissCount() );
assertEquals( 0, stats.getEntityLoadCount() );
Country nl = s.get( Country.class, countryId.get() );
assertNotNull( nl );
assertEquals( 1, stats.getSecondLevelCacheHitCount() );
assertEquals( 0, stats.getSecondLevelCacheMissCount() );
assertEquals( 0, stats.getEntityLoadCount() );
Continent continent = nl.getContinent();
final PersistentAttributeInterceptable interceptable = (PersistentAttributeInterceptable) continent;
final EnhancementAsProxyLazinessInterceptor interceptor = (EnhancementAsProxyLazinessInterceptor) interceptable.$$_hibernate_getInterceptor();
assertFalse( interceptor.isInitialized() );
assertFalse( interceptor.isAttributeLoaded( "code" ) );
assertEquals( 1, stats.getSecondLevelCacheHitCount() );
assertEquals( 0, stats.getSecondLevelCacheMissCount() );
assertEquals( 0, stats.getEntityLoadCount() );
//Trigger initialization of the enhanced proxy:
assertEquals( "EU", continent.getCode() );
assertTrue( interceptor.isInitialized() );
assertEquals( 2, stats.getSecondLevelCacheHitCount() );
assertEquals( 0, stats.getSecondLevelCacheMissCount() );
assertEquals( 0, stats.getEntityLoadCount() );
} );
}
private void clearAllCaches() {
final CacheImplementor cache = sessionFactory().getCache();
for (String name : cache.getCacheRegionNames() ) {
cache.getRegion( name ).clear();
}
}
private void storeTestData() {
inTransaction( s -> {
Continent continent = new Continent();
continent.setCode( "EU" );
continent.setName( "Europe" );
s.persist( continent );
Country c = new Country();
c.setCode( "NL" );
c.setName( "Nederland" );
c.setContinent( continent );
s.persist( c );
countryId.set( c.getId() );
} );
}
}

View File

@ -0,0 +1,85 @@
/*
* 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.flush;
import java.util.Map;
import javax.persistence.TransactionRequiredException;
import org.hibernate.Session;
import org.hibernate.cfg.AvailableSettings;
import org.junit.Test;
import org.hibernate.testing.TestForIssue;
import org.hibernate.testing.jta.TestingJtaBootstrap;
import org.hibernate.testing.jta.TestingJtaPlatformImpl;
import org.hibernate.testing.junit4.BaseNonConfigCoreFunctionalTestCase;
import static org.junit.Assert.fail;
/**
* @author Michiel Hendriks
*/
@TestForIssue(jiraKey = "HHH-13936")
public class TestFlushJoinTransaction extends BaseNonConfigCoreFunctionalTestCase {
@Override
protected void addSettings(Map settings) {
super.addSettings( settings );
TestingJtaBootstrap.prepare( settings );
settings.put( AvailableSettings.TRANSACTION_COORDINATOR_STRATEGY, "jta" );
}
@Test
public void testFlush() throws Exception {
Session session = openSession();
try {
TestingJtaPlatformImpl.INSTANCE.getTransactionManager().begin();
session.flush();
TestingJtaPlatformImpl.INSTANCE.getTransactionManager().commit();
}
catch (TransactionRequiredException e) {
fail("No TransactionRequiredException expected.");
}
finally {
session.close();
}
}
@Test
public void testIsConnectedFlush() throws Exception {
Session session = openSession();
try {
TestingJtaPlatformImpl.INSTANCE.getTransactionManager().begin();
session.isConnected();
session.flush();
TestingJtaPlatformImpl.INSTANCE.getTransactionManager().commit();
}
catch (TransactionRequiredException e) {
fail("No TransactionRequiredException expected.");
}
finally {
session.close();
}
}
@Test
public void testIsConnectedFlushShouldThrowExceptionIfNoTransaction() {
Session session = openSession();
try {
session.isConnected();
session.flush();
fail("A TransactionRequiredException should be thrown");
}
catch (TransactionRequiredException e) {
//expected
}
finally {
session.close();
}
}
}

View File

@ -0,0 +1,104 @@
/*
* 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 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.dialect.WithCustomJPAFilter;
import org.geolatte.geom.Envelope;
import org.geolatte.geom.Geometry;
import org.geolatte.geom.Polygon;
import org.geolatte.geom.Position;
import org.geolatte.geom.PositionSequence;
import org.geolatte.geom.PositionSequenceBuilders;
import org.geolatte.geom.crs.CoordinateReferenceSystem;
/**
* {@link JTSFilterPredicate}, but for geolatte-geom.
*/
public class GeolatteFilterPredicate extends AbstractSimplePredicate implements Serializable {
private final Expression<? extends Geometry> geometry;
private final Expression<? extends Geometry> filter;
public GeolatteFilterPredicate(
CriteriaBuilder criteriaBuilder, Expression<? extends Geometry> geometry,
Expression<? extends Geometry> filter) {
super( (CriteriaBuilderImpl) criteriaBuilder );
this.geometry = geometry;
this.filter = filter;
}
public GeolatteFilterPredicate(
CriteriaBuilder criteriaBuilder, Expression<? extends Geometry> geometry,
Geometry filter) {
this( criteriaBuilder, geometry, criteriaBuilder.literal( filter )
);
}
public GeolatteFilterPredicate(
CriteriaBuilder criteriaBuilder, Expression<? extends Geometry> geometry,
Envelope envelope) {
this( criteriaBuilder, geometry, fromEnvelope( envelope )
);
}
@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";
}
}
private static <P extends Position> Polygon<P> fromEnvelope(Envelope<P> envelope) {
CoordinateReferenceSystem<P> crs = envelope.getCoordinateReferenceSystem();
P lowerLeft = envelope.lowerLeft();
P upperLeft = envelope.upperLeft();
P upperRight = envelope.upperRight();
P lowerRight = envelope.lowerRight();
PositionSequence<P> positionSequence = PositionSequenceBuilders.fixedSized(
5,
crs.getPositionClass()
)
.add( lowerLeft )
.add( upperLeft )
.add( upperRight )
.add( lowerRight )
.add( lowerLeft )
.toPositionSequence();
return new Polygon<>( positionSequence, crs );
}
}

View File

@ -0,0 +1,571 @@
/*
* 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.geolatte.geom.Envelope;
import org.geolatte.geom.Geometry;
/**
* {@link JTSSpatialPredicates}, but for geolatte-geom.
*
* @author Daniel Shuy
*/
public class GeolatteSpatialPredicates {
protected GeolatteSpatialPredicates() {
}
/**
* 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 JTSSpatialPredicates#eq(CriteriaBuilder, Expression, Expression)
*/
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 JTSSpatialPredicates#within(CriteriaBuilder, Expression, Expression)
*/
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 JTSSpatialPredicates#contains(CriteriaBuilder, Expression, Expression)
*/
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 JTSSpatialPredicates#crosses(CriteriaBuilder, Expression, Expression)
*/
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 JTSSpatialPredicates#disjoint(CriteriaBuilder, Expression, Expression)
*/
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 JTSSpatialPredicates#intersects(CriteriaBuilder, Expression, Expression)
*/
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 JTSSpatialPredicates#overlaps(CriteriaBuilder, Expression, Expression)
*/
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 JTSSpatialPredicates#touches(CriteriaBuilder, Expression, Expression)
*/
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 GeolatteFilterPredicate
* @see JTSSpatialPredicates#filter(CriteriaBuilder, Expression, Expression)
*/
public static Predicate filter(
CriteriaBuilder criteriaBuilder, Expression<? extends Geometry> geometry1,
Expression<? extends Geometry> geometry2) {
return new GeolatteFilterPredicate( 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 GeolatteFilterPredicate
* @see JTSSpatialPredicates#filter(CriteriaBuilder, Expression, org.locationtech.jts.geom.Geometry)
*/
public static Predicate filter(
CriteriaBuilder criteriaBuilder, Expression<? extends Geometry> geometry1,
Geometry geometry2) {
return new GeolatteFilterPredicate( 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
*
* @return bounding box overlap predicate
*
* @see GeolatteFilterPredicate
* @see JTSSpatialPredicates#filterByPolygon(CriteriaBuilder, Expression, org.locationtech.jts.geom.Envelope, int)
*/
public static Predicate filterByPolygon(
CriteriaBuilder criteriaBuilder, Expression<? extends Geometry> geometry,
Envelope envelope) {
return new GeolatteFilterPredicate( criteriaBuilder, geometry, envelope );
}
/**
* 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 JTSSpatialPredicates#distanceWithin(CriteriaBuilder, Expression, Expression, Expression)
*/
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 JTSSpatialPredicates#havingSRID(CriteriaBuilder, Expression, Expression)
*/
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 JTSSpatialPredicates#isEmpty(CriteriaBuilder, Expression)
*/
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 JTSSpatialPredicates#isNotEmpty(CriteriaBuilder, Expression)
*/
public static Predicate isNotEmpty(CriteriaBuilder criteriaBuilder, Expression<? extends Geometry> geometry) {
return isEmpty( criteriaBuilder, geometry )
.not();
}
private static Predicate booleanExpressionToPredicate(
CriteriaBuilder criteriaBuilder,
Expression<Boolean> expression) {
return criteriaBuilder.equal( expression, true );
}
}

View File

@ -29,12 +29,12 @@ import org.locationtech.jts.geom.Geometry;
/**
* JPA Criteria API {@link Predicate} equivalent of {@link SpatialFilter}.
*/
public class FilterPredicate extends AbstractSimplePredicate implements Serializable {
public class JTSFilterPredicate extends AbstractSimplePredicate implements Serializable {
private final Expression<? extends Geometry> geometry;
private final Expression<? extends Geometry> filter;
public FilterPredicate(
public JTSFilterPredicate(
CriteriaBuilder criteriaBuilder, Expression<? extends Geometry> geometry,
Expression<? extends Geometry> filter) {
super( (CriteriaBuilderImpl) criteriaBuilder );
@ -42,14 +42,14 @@ public class FilterPredicate extends AbstractSimplePredicate implements Serializ
this.filter = filter;
}
public FilterPredicate(
public JTSFilterPredicate(
CriteriaBuilder criteriaBuilder, Expression<? extends Geometry> geometry,
Geometry filter) {
this( criteriaBuilder, geometry, criteriaBuilder.literal( filter )
);
}
public FilterPredicate(
public JTSFilterPredicate(
CriteriaBuilder criteriaBuilder, Expression<? extends Geometry> geometry,
Envelope envelope, int srid) {
this( criteriaBuilder, geometry, EnvelopeAdapter.toPolygon( envelope, srid )

View File

@ -0,0 +1,574 @@
/*
* 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;
/**
* A factory for spatial JPA Criteria API {@link Predicate}s.
*
* @author Daniel Shuy
* @see SpatialRestrictions
*/
public class JTSSpatialPredicates {
protected JTSSpatialPredicates() {
}
/**
* 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 JTSFilterPredicate
* @see SpatialRestrictions#filter(String, Geometry)
*/
public static Predicate filter(
CriteriaBuilder criteriaBuilder, Expression<? extends Geometry> geometry1,
Expression<? extends Geometry> geometry2) {
return new JTSFilterPredicate( 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 JTSFilterPredicate
* @see SpatialRestrictions#filter(String, Geometry)
*/
public static Predicate filter(
CriteriaBuilder criteriaBuilder, Expression<? extends Geometry> geometry1,
Geometry geometry2) {
return new JTSFilterPredicate( 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 JTSFilterPredicate
* @see SpatialRestrictions#filter(String, Envelope, int)
*/
public static Predicate filterByPolygon(
CriteriaBuilder criteriaBuilder, Expression<? extends Geometry> geometry,
Envelope envelope, int srid) {
return new JTSFilterPredicate( criteriaBuilder, geometry, envelope, srid );
}
/**
* Create a predicate for testing the arguments for "distance within" constraint.
*
* @param criteriaBuilder CriteriaBuilder
* @param geometry1 geometry expression
* @param geometry2 geometry expression
* @param distance distance expression
*
* @return "distance within" predicate
*
* @see SpatialRestrictions#distanceWithin(String, Geometry, double)
*/
public static Predicate distanceWithin(
CriteriaBuilder criteriaBuilder, Expression<? extends Geometry> geometry1,
Expression<? extends Geometry> geometry2, Expression<Double> distance) {
return booleanExpressionToPredicate(
criteriaBuilder,
criteriaBuilder.function( SpatialFunction.dwithin.toString(), boolean.class,
geometry1, geometry2, distance
)
);
}
/**
* Create a predicate for testing the arguments for "distance within" constraint.
*
* @param criteriaBuilder CriteriaBuilder
* @param geometry1 geometry expression
* @param geometry2 geometry value
* @param distance distance expression
*
* @return "distance within" predicate
*
* @see #distanceWithin(CriteriaBuilder, Expression, Expression, Expression)
*/
public static Predicate distanceWithin(
CriteriaBuilder criteriaBuilder, Expression<? extends Geometry> geometry1,
Geometry geometry2, Expression<Double> distance) {
return distanceWithin( criteriaBuilder, geometry1,
criteriaBuilder.literal( geometry2 ), distance
);
}
/**
* Create a predicate for testing the arguments for "distance within" constraint.
*
* @param criteriaBuilder CriteriaBuilder
* @param geometry1 geometry expression
* @param geometry2 geometry value
* @param distance distance value
*
* @return "distance within" predicate
*
* @see #distanceWithin(CriteriaBuilder, Expression, Expression, Expression)
*/
public static Predicate distanceWithin(
CriteriaBuilder criteriaBuilder, Expression<? extends Geometry> geometry1,
Geometry geometry2, double distance) {
return distanceWithin( criteriaBuilder, geometry1,
criteriaBuilder.literal( geometry2 ), criteriaBuilder.literal( distance )
);
}
/**
* Create a predicate for testing the arguments for "distance within" constraint.
*
* @param criteriaBuilder CriteriaBuilder
* @param geometry1 geometry expression
* @param geometry2 geometry expression
* @param distance distance value
*
* @return "distance within" predicate
*
* @see #distanceWithin(CriteriaBuilder, Expression, Expression, Expression)
*/
public static Predicate distanceWithin(
CriteriaBuilder criteriaBuilder, Expression<? extends Geometry> geometry1,
Expression<? extends Geometry> geometry2, double distance) {
return distanceWithin( criteriaBuilder, geometry1, geometry2,
criteriaBuilder.literal( distance )
);
}
/**
* Create a predicate for testing the arguments for "having srid" constraint.
*
* @param criteriaBuilder CriteriaBuilder
* @param geometry geometry expression
* @param srid SRID expression
*
* @return "having srid" predicate
*
* @see SpatialRestrictions#havingSRID(String, int)
*/
public static Predicate havingSRID(
CriteriaBuilder criteriaBuilder, Expression<? extends Geometry> geometry,
Expression<Integer> srid) {
return criteriaBuilder.equal(
criteriaBuilder.function( SpatialFunction.srid.toString(), int.class, geometry ),
srid
);
}
/**
* Create a predicate for testing the arguments for "having srid" constraint.
*
* @param criteriaBuilder CriteriaBuilder
* @param geometry geometry expression
* @param srid SRID expression
*
* @return "having srid" predicate
*
* @see #havingSRID(CriteriaBuilder, Expression, Expression)
*/
public static Predicate havingSRID(
CriteriaBuilder criteriaBuilder, Expression<? extends Geometry> geometry,
int srid) {
return havingSRID( criteriaBuilder, geometry,
criteriaBuilder.literal( srid )
);
}
/**
* Create a predicate for testing the arguments for "is empty" constraint.
*
* @param criteriaBuilder CriteriaBuilder
* @param geometry geometry expression
*
* @return "is empty" predicate
*
* @see SpatialRestrictions#isEmpty(String)
*/
public static Predicate isEmpty(CriteriaBuilder criteriaBuilder, Expression<? extends Geometry> geometry) {
return booleanExpressionToPredicate(
criteriaBuilder,
criteriaBuilder.function( SpatialFunction.isempty.toString(), boolean.class,
geometry
)
);
}
/**
* Create a predicate for testing the arguments for "is not empty" constraint.
*
* @param criteriaBuilder CriteriaBuilder
* @param geometry geometry expression
*
* @return "is not empty" predicate
*
* @see SpatialRestrictions#isNotEmpty(String)
*/
public static Predicate isNotEmpty(CriteriaBuilder criteriaBuilder, Expression<? extends Geometry> geometry) {
return isEmpty( criteriaBuilder, geometry )
.not();
}
private static Predicate booleanExpressionToPredicate(
CriteriaBuilder criteriaBuilder,
Expression<Boolean> expression) {
return criteriaBuilder.equal( expression, true );
}
}

View File

@ -6,570 +6,12 @@
*/
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
* @deprecated Use {@link JTSSpatialPredicates} instead.
*/
public final class SpatialPredicates {
@Deprecated
public class SpatialPredicates extends JTSSpatialPredicates {
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 );
protected SpatialPredicates() {
}
}

View File

@ -0,0 +1,284 @@
/*
* 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.geolatte.GeomEntity;
import org.hibernate.spatial.predicate.GeolatteSpatialPredicates;
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 TestJTSSpatialPredicates
*/
@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 TestGeolatteSpatialPredicates extends SpatialFunctionalTestCase {
private static HSMessageLogger LOG = Logger.getMessageLogger(
HSMessageLogger.class,
TestGeolatteSpatialPredicates.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<GeomEntity>, Predicate> predicateFactory = (criteriaBuilder, root) ->
GeolatteSpatialPredicates.within(
criteriaBuilder,
root.get( "geom" ),
org.geolatte.geom.jts.JTS.from( 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<GeomEntity>, Predicate> predicateFactory = (criteriaBuilder, root) ->
GeolatteSpatialPredicates.filter(
criteriaBuilder,
root.get( "geom" ),
org.geolatte.geom.jts.JTS.from( 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<GeomEntity>, Predicate> predicateFactory = (criteriaBuilder, root) ->
GeolatteSpatialPredicates.contains(
criteriaBuilder,
root.get( "geom" ),
org.geolatte.geom.jts.JTS.from( 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<GeomEntity>, Predicate> predicateFactory = (criteriaBuilder, root) ->
GeolatteSpatialPredicates.crosses(
criteriaBuilder,
root.get( "geom" ),
org.geolatte.geom.jts.JTS.from( 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<GeomEntity>, Predicate> predicateFactory = (criteriaBuilder, root) ->
GeolatteSpatialPredicates.touches(
criteriaBuilder,
root.get( "geom" ),
org.geolatte.geom.jts.JTS.from( 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<GeomEntity>, Predicate> predicateFactory = (criteriaBuilder, root) ->
GeolatteSpatialPredicates.disjoint(
criteriaBuilder,
root.get( "geom" ),
org.geolatte.geom.jts.JTS.from( 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<GeomEntity>, Predicate> predicateFactory = (criteriaBuilder, root) ->
GeolatteSpatialPredicates.eq(
criteriaBuilder,
root.get( "geom" ),
org.geolatte.geom.jts.JTS.from( 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<GeomEntity>, Predicate> predicateFactory = (criteriaBuilder, root) ->
GeolatteSpatialPredicates.intersects(
criteriaBuilder,
root.get( "geom" ),
org.geolatte.geom.jts.JTS.from( 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<GeomEntity>, Predicate> predicateFactory = (criteriaBuilder, root) ->
GeolatteSpatialPredicates.overlaps(
criteriaBuilder,
root.get( "geom" ),
org.geolatte.geom.jts.JTS.from( 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<GeomEntity>, Predicate> predicateFactory = (criteriaBuilder, root) ->
GeolatteSpatialPredicates.distanceWithin(
criteriaBuilder,
root.get( "geom" ),
org.geolatte.geom.jts.JTS.from( 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<GeomEntity>, Predicate> predicateFactory = (criteriaBuilder, root) ->
GeolatteSpatialPredicates.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<GeomEntity>, Predicate> predicateFactory = (criteriaBuilder, root) ->
GeolatteSpatialPredicates.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<GeomEntity>, Predicate> predicateFactory = (criteriaBuilder, root) ->
GeolatteSpatialPredicates.havingSRID( criteriaBuilder, root.get( "geom" ), 4326 );
retrieveAndCompare( dbexpected, predicateFactory );
dbexpected = expectationsFactory.havingSRID( 31370 );
predicateFactory = (criteriaBuilder, root) ->
GeolatteSpatialPredicates.havingSRID( criteriaBuilder, root.get( "geom" ), 31370 );
retrieveAndCompare( dbexpected, predicateFactory );
}
private void retrieveAndCompare(
Map<Integer, Boolean> dbexpected,
BiFunction<CriteriaBuilder, Root<GeomEntity>, Predicate> predicateFactory) {
try (Session session = openSession()) {
Transaction tx = null;
try {
tx = session.beginTransaction();
CriteriaBuilder criteriaBuilder = session.getCriteriaBuilder();
CriteriaQuery<GeomEntity> criteriaQuery = criteriaBuilder.createQuery( GeomEntity.class );
Root<GeomEntity> root = criteriaQuery.from( GeomEntity.class );
criteriaQuery.select( root )
.where( predicateFactory.apply( criteriaBuilder, root ) );
List<GeomEntity> list = session.createQuery( criteriaQuery )
.getResultList();
compare( dbexpected, list );
}
finally {
if ( tx != null ) {
tx.rollback();
}
}
}
}
private void compare(Map<Integer, Boolean> dbexpected, List<GeomEntity> 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<GeomEntity> list) {
return list.stream()
.anyMatch( entity -> entity.getId().equals( id ) );
}
}

View File

@ -21,7 +21,7 @@ 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.predicate.JTSSpatialPredicates;
import org.hibernate.spatial.testing.SpatialDialectMatcher;
import org.hibernate.spatial.testing.SpatialFunctionalTestCase;
@ -39,11 +39,11 @@ import static org.junit.Assert.fail;
*/
@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 {
public class TestJTSSpatialPredicates extends SpatialFunctionalTestCase {
private static HSMessageLogger LOG = Logger.getMessageLogger(
HSMessageLogger.class,
TestSpatialPredicates.class.getName()
TestJTSSpatialPredicates.class.getName()
);
protected HSMessageLogger getLogger() {
@ -57,7 +57,11 @@ public class TestSpatialPredicates extends SpatialFunctionalTestCase {
}
Map<Integer, Boolean> dbexpected = expectationsFactory.getWithin( expectationsFactory.getTestPolygon() );
BiFunction<CriteriaBuilder, Root<JtsGeomEntity>, Predicate> predicateFactory = (criteriaBuilder, root) ->
SpatialPredicates.within( criteriaBuilder, root.get( "geom" ), expectationsFactory.getTestPolygon() );
JTSSpatialPredicates.within(
criteriaBuilder,
root.get( "geom" ),
expectationsFactory.getTestPolygon()
);
retrieveAndCompare( dbexpected, predicateFactory );
}
@ -69,7 +73,11 @@ public class TestSpatialPredicates extends SpatialFunctionalTestCase {
}
Map<Integer, Boolean> dbexpected = expectationsFactory.getFilter( expectationsFactory.getTestPolygon() );
BiFunction<CriteriaBuilder, Root<JtsGeomEntity>, Predicate> predicateFactory = (criteriaBuilder, root) ->
SpatialPredicates.filter( criteriaBuilder, root.get( "geom" ), expectationsFactory.getTestPolygon() );
JTSSpatialPredicates.filter(
criteriaBuilder,
root.get( "geom" ),
expectationsFactory.getTestPolygon()
);
retrieveAndCompare( dbexpected, predicateFactory );
}
@ -80,7 +88,7 @@ public class TestSpatialPredicates extends SpatialFunctionalTestCase {
}
Map<Integer, Boolean> dbexpected = expectationsFactory.getContains( expectationsFactory.getTestPolygon() );
BiFunction<CriteriaBuilder, Root<JtsGeomEntity>, Predicate> predicateFactory = (criteriaBuilder, root) ->
SpatialPredicates.contains(
JTSSpatialPredicates.contains(
criteriaBuilder,
root.get( "geom" ),
expectationsFactory.getTestPolygon()
@ -95,7 +103,11 @@ public class TestSpatialPredicates extends SpatialFunctionalTestCase {
}
Map<Integer, Boolean> dbexpected = expectationsFactory.getCrosses( expectationsFactory.getTestPolygon() );
BiFunction<CriteriaBuilder, Root<JtsGeomEntity>, Predicate> predicateFactory = (criteriaBuilder, root) ->
SpatialPredicates.crosses( criteriaBuilder, root.get( "geom" ), expectationsFactory.getTestPolygon() );
JTSSpatialPredicates.crosses(
criteriaBuilder,
root.get( "geom" ),
expectationsFactory.getTestPolygon()
);
retrieveAndCompare( dbexpected, predicateFactory );
}
@ -106,7 +118,11 @@ public class TestSpatialPredicates extends SpatialFunctionalTestCase {
}
Map<Integer, Boolean> dbexpected = expectationsFactory.getTouches( expectationsFactory.getTestPolygon() );
BiFunction<CriteriaBuilder, Root<JtsGeomEntity>, Predicate> predicateFactory = (criteriaBuilder, root) ->
SpatialPredicates.touches( criteriaBuilder, root.get( "geom" ), expectationsFactory.getTestPolygon() );
JTSSpatialPredicates.touches(
criteriaBuilder,
root.get( "geom" ),
expectationsFactory.getTestPolygon()
);
retrieveAndCompare( dbexpected, predicateFactory );
}
@ -117,7 +133,7 @@ public class TestSpatialPredicates extends SpatialFunctionalTestCase {
}
Map<Integer, Boolean> dbexpected = expectationsFactory.getDisjoint( expectationsFactory.getTestPolygon() );
BiFunction<CriteriaBuilder, Root<JtsGeomEntity>, Predicate> predicateFactory = (criteriaBuilder, root) ->
SpatialPredicates.disjoint(
JTSSpatialPredicates.disjoint(
criteriaBuilder,
root.get( "geom" ),
expectationsFactory.getTestPolygon()
@ -132,7 +148,7 @@ public class TestSpatialPredicates extends SpatialFunctionalTestCase {
}
Map<Integer, Boolean> dbexpected = expectationsFactory.getEquals( expectationsFactory.getTestPolygon() );
BiFunction<CriteriaBuilder, Root<JtsGeomEntity>, Predicate> predicateFactory = (criteriaBuilder, root) ->
SpatialPredicates.eq( criteriaBuilder, root.get( "geom" ), expectationsFactory.getTestPolygon() );
JTSSpatialPredicates.eq( criteriaBuilder, root.get( "geom" ), expectationsFactory.getTestPolygon() );
retrieveAndCompare( dbexpected, predicateFactory );
}
@ -143,7 +159,7 @@ public class TestSpatialPredicates extends SpatialFunctionalTestCase {
}
Map<Integer, Boolean> dbexpected = expectationsFactory.getIntersects( expectationsFactory.getTestPolygon() );
BiFunction<CriteriaBuilder, Root<JtsGeomEntity>, Predicate> predicateFactory = (criteriaBuilder, root) ->
SpatialPredicates.intersects(
JTSSpatialPredicates.intersects(
criteriaBuilder,
root.get( "geom" ),
expectationsFactory.getTestPolygon()
@ -158,7 +174,7 @@ public class TestSpatialPredicates extends SpatialFunctionalTestCase {
}
Map<Integer, Boolean> dbexpected = expectationsFactory.getOverlaps( expectationsFactory.getTestPolygon() );
BiFunction<CriteriaBuilder, Root<JtsGeomEntity>, Predicate> predicateFactory = (criteriaBuilder, root) ->
SpatialPredicates.overlaps(
JTSSpatialPredicates.overlaps(
criteriaBuilder,
root.get( "geom" ),
expectationsFactory.getTestPolygon()
@ -173,7 +189,7 @@ public class TestSpatialPredicates extends SpatialFunctionalTestCase {
}
Map<Integer, Boolean> dbexpected = expectationsFactory.getDwithin( expectationsFactory.getTestPoint(), 30.0 );
BiFunction<CriteriaBuilder, Root<JtsGeomEntity>, Predicate> predicateFactory = (criteriaBuilder, root) ->
SpatialPredicates.distanceWithin(
JTSSpatialPredicates.distanceWithin(
criteriaBuilder,
root.get( "geom" ),
expectationsFactory.getTestPoint(),
@ -189,7 +205,7 @@ public class TestSpatialPredicates extends SpatialFunctionalTestCase {
}
Map<Integer, Boolean> dbexpected = expectationsFactory.getIsEmpty();
BiFunction<CriteriaBuilder, Root<JtsGeomEntity>, Predicate> predicateFactory = (criteriaBuilder, root) ->
SpatialPredicates.isEmpty( criteriaBuilder, root.get( "geom" ) );
JTSSpatialPredicates.isEmpty( criteriaBuilder, root.get( "geom" ) );
retrieveAndCompare( dbexpected, predicateFactory );
}
@ -200,7 +216,7 @@ public class TestSpatialPredicates extends SpatialFunctionalTestCase {
}
Map<Integer, Boolean> dbexpected = expectationsFactory.getIsNotEmpty();
BiFunction<CriteriaBuilder, Root<JtsGeomEntity>, Predicate> predicateFactory = (criteriaBuilder, root) ->
SpatialPredicates.isNotEmpty( criteriaBuilder, root.get( "geom" ) );
JTSSpatialPredicates.isNotEmpty( criteriaBuilder, root.get( "geom" ) );
retrieveAndCompare( dbexpected, predicateFactory );
}
@ -211,11 +227,11 @@ public class TestSpatialPredicates extends SpatialFunctionalTestCase {
}
Map<Integer, Boolean> dbexpected = expectationsFactory.havingSRID( 4326 );
BiFunction<CriteriaBuilder, Root<JtsGeomEntity>, Predicate> predicateFactory = (criteriaBuilder, root) ->
SpatialPredicates.havingSRID( criteriaBuilder, root.get( "geom" ), 4326 );
JTSSpatialPredicates.havingSRID( criteriaBuilder, root.get( "geom" ), 4326 );
retrieveAndCompare( dbexpected, predicateFactory );
dbexpected = expectationsFactory.havingSRID( 31370 );
predicateFactory = (criteriaBuilder, root) ->
SpatialPredicates.havingSRID( criteriaBuilder, root.get( "geom" ), 31370 );
JTSSpatialPredicates.havingSRID( criteriaBuilder, root.get( "geom" ), 31370 );
retrieveAndCompare( dbexpected, predicateFactory );
}

View File

@ -8,8 +8,9 @@
package org.hibernate.spatial.testing.dialects.postgis;
import org.hibernate.spatial.integration.TestGeolatteSpatialPredicates;
import org.hibernate.spatial.integration.TestSpatialFunctions;
import org.hibernate.spatial.integration.TestSpatialPredicates;
import org.hibernate.spatial.integration.TestJTSSpatialPredicates;
import org.hibernate.spatial.integration.TestSpatialRestrictions;
import org.hibernate.spatial.testing.AbstractExpectationsFactory;
import org.hibernate.spatial.testing.DataSourceUtils;
@ -30,7 +31,8 @@ public class PostgisTestSupport extends TestSupport {
Class<? extends BaseCoreFunctionalTestCase> testcaseClass = testcase.getClass();
if ( testcaseClass == TestSpatialFunctions.class ||
testcaseClass == TestSpatialRestrictions.class ||
testcaseClass == TestSpatialPredicates.class ) {
testcaseClass == TestJTSSpatialPredicates.class ||
testcaseClass == TestGeolatteSpatialPredicates.class ) {
return TestData.fromFile( "postgis-functions-test.xml" );
}
return TestData.fromFile( "test-data-set.xml" );

View File

@ -32,7 +32,7 @@ public abstract class EnhancerTestUtils extends BaseUnitTestCase {
public static Object getFieldByReflection(Object entity, String fieldName) {
try {
Field field = entity.getClass().getDeclaredField( fieldName );
Field field = findField( entity.getClass(), fieldName );
ReflectHelper.ensureAccessibility( field );
return field.get( entity );
}
@ -75,4 +75,20 @@ public abstract class EnhancerTestUtils extends BaseUnitTestCase {
);
}
private static Field findField(Class<?> clazz, String fieldName) throws NoSuchFieldException {
NoSuchFieldException exception = null;
while ( clazz != null ) {
try {
return clazz.getDeclaredField( fieldName );
}
catch (NoSuchFieldException e) {
if ( exception == null ) {
exception = e;
}
clazz = clazz.getSuperclass();
}
}
throw exception;
}
}