Merge remote-tracking branch 'upstream/main' into wip/6.0_merge
This commit is contained in:
commit
7f46f11f3b
|
@ -12,10 +12,10 @@ and it allows you to deal with geographic data in a standardized way.
|
||||||
|
|
||||||
Hibernate Spatial provides a standardized, cross-database interface to geographic data storage and query functions.
|
Hibernate Spatial provides a standardized, cross-database interface to geographic data storage and query functions.
|
||||||
It supports most of the functions described by the OGC Simple Feature Specification. Supported databases are Oracle 10g/11g,
|
It supports most of the functions described by the OGC Simple Feature Specification. Supported databases are Oracle 10g/11g,
|
||||||
PostgreSQL/PostGIS, MySQL, Microsoft SQL Server and H2/GeoDB.
|
PostgreSQL/PostGIS, MySQL, Microsoft SQL Server, DB2, CockroachDB and H2/GeoDB.
|
||||||
|
|
||||||
Spatial data types are not part of the Java standard library, and they are absent from the JDBC specification.
|
Spatial data types are not part of the Java standard library, and they are absent from the JDBC specification.
|
||||||
Over the years https://tsusiatsoftware.net/jts/main.html[JTS] has emerged the _de facto_ standard to fill this gap. JTS is
|
Over the years https://tsusiatsoftware.net/jts/main.html[JTS] has emerged as the _de facto_ standard to fill this gap. JTS is
|
||||||
an implementation of the https://portal.opengeospatial.org/files/?artifact_id=829[Simple Feature Specification (SFS)]. Many databases
|
an implementation of the https://portal.opengeospatial.org/files/?artifact_id=829[Simple Feature Specification (SFS)]. Many databases
|
||||||
on the other hand implement the SQL/MM - Part 3: Spatial Data specification - a related, but broader specification. The biggest difference is that
|
on the other hand implement the SQL/MM - Part 3: Spatial Data specification - a related, but broader specification. The biggest difference is that
|
||||||
SFS is limited to 2D geometries in the projected plane (although JTS supports 3D coordinates), whereas
|
SFS is limited to 2D geometries in the projected plane (although JTS supports 3D coordinates), whereas
|
||||||
|
@ -26,7 +26,7 @@ https://github.com/GeoLatte/geolatte-geom[geolatte-geom]. As already mentioned,
|
||||||
standard. Geolatte-geom (also written by the lead developer of Hibernate Spatial) is a more recent library that
|
standard. Geolatte-geom (also written by the lead developer of Hibernate Spatial) is a more recent library that
|
||||||
supports many features specified in SQL/MM but not available in JTS (such as support for 4D geometries, and support for extended WKT/WKB formats).
|
supports many features specified in SQL/MM but not available in JTS (such as support for 4D geometries, and support for extended WKT/WKB formats).
|
||||||
Geolatte-geom also implements encoders/decoders for the database native types. Geolatte-geom has good interoperability with
|
Geolatte-geom also implements encoders/decoders for the database native types. Geolatte-geom has good interoperability with
|
||||||
JTS. Converting a Geolatte `geometry` to a JTS `geometry, for instance, doesn't require copying of the coordinates.
|
JTS. Converting a Geolatte `geometry` to a JTS `geometry`, for instance, doesn't require copying of the coordinates.
|
||||||
It also delegates spatial processing to JTS.
|
It also delegates spatial processing to JTS.
|
||||||
|
|
||||||
Whether you use JTS or Geolatte-geom, Hibernate spatial maps the database spatial types to your geometry model of choice. It will, however,
|
Whether you use JTS or Geolatte-geom, Hibernate spatial maps the database spatial types to your geometry model of choice. It will, however,
|
||||||
|
@ -260,7 +260,7 @@ create transform for db2gse.st_geometry db2_program (
|
||||||
Hibernate Spatial comes with the following types:
|
Hibernate Spatial comes with the following types:
|
||||||
|
|
||||||
jts_geometry::
|
jts_geometry::
|
||||||
Handled by `org.hibernate.spatial.JTSGeometryType` it maps a database geometry column type to a `org.locationtech.jts.geom.Geometry` entity property type.
|
Handled by `org.hibernate.spatial.JTSGeometryType`, it maps a database geometry column type to a `org.locationtech.jts.geom.Geometry` entity property type.
|
||||||
geolatte_geometry::
|
geolatte_geometry::
|
||||||
Handled by `org.hibernate.spatial.GeolatteGeometryType`, it maps a database geometry column type to an `org.geolatte.geom.Geometry` entity property type.
|
Handled by `org.hibernate.spatial.GeolatteGeometryType`, it maps a database geometry column type to an `org.geolatte.geom.Geometry` entity property type.
|
||||||
|
|
||||||
|
|
|
@ -147,6 +147,12 @@ public enum LockMode {
|
||||||
return NONE;
|
return NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for ( LockMode lockMode : LockMode.values() ) {
|
||||||
|
if ( lockMode.externalForm.equals( externalForm ) ) {
|
||||||
|
return lockMode;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
for ( LockMode lockMode : LockMode.values() ) {
|
for ( LockMode lockMode : LockMode.values() ) {
|
||||||
if ( lockMode.externalForm.equalsIgnoreCase( externalForm ) ) {
|
if ( lockMode.externalForm.equalsIgnoreCase( externalForm ) ) {
|
||||||
return lockMode;
|
return lockMode;
|
||||||
|
|
|
@ -6,117 +6,117 @@
|
||||||
*/
|
*/
|
||||||
package org.hibernate.internal.util.collections;
|
package org.hibernate.internal.util.collections;
|
||||||
|
|
||||||
import java.util.LinkedList;
|
import java.util.ArrayDeque;
|
||||||
|
import java.util.Deque;
|
||||||
|
import java.util.Iterator;
|
||||||
import java.util.function.Consumer;
|
import java.util.function.Consumer;
|
||||||
import java.util.function.Function;
|
import java.util.function.Function;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A general-purpose stack impl.
|
* A general-purpose stack impl supporting null values.
|
||||||
*
|
*
|
||||||
* @param <T> The type of things stored in the stack
|
* @param <T> The type of things stored in the stack
|
||||||
*
|
*
|
||||||
* @author Steve Ebersole
|
* @author Steve Ebersole
|
||||||
|
* @author Sanne Grinovero
|
||||||
*/
|
*/
|
||||||
public final class StandardStack<T> implements Stack<T> {
|
public final class StandardStack<T> implements Stack<T> {
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
private final T nullMarker = (T) new Object();
|
|
||||||
|
|
||||||
private T current;
|
private ArrayDeque<T> internalStack;
|
||||||
|
private static final Object NULL_TOKEN = new Object();
|
||||||
private final LinkedList<T> internalStack = new LinkedList<>();
|
|
||||||
|
|
||||||
public StandardStack() {
|
public StandardStack() {
|
||||||
}
|
}
|
||||||
|
|
||||||
public StandardStack(T initial) {
|
public StandardStack(T initial) {
|
||||||
current = initial;
|
stackInstanceExpected().addFirst( initial );
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void push(T newCurrent) {
|
public void push(T newCurrent) {
|
||||||
|
Object toStore = newCurrent;
|
||||||
if ( newCurrent == null ) {
|
if ( newCurrent == null ) {
|
||||||
newCurrent = nullMarker;
|
toStore = NULL_TOKEN;
|
||||||
}
|
}
|
||||||
|
stackInstanceExpected().addFirst( toStore );
|
||||||
|
}
|
||||||
|
|
||||||
if ( current != null ) {
|
private Deque stackInstanceExpected() {
|
||||||
internalStack.addFirst( current );
|
if ( internalStack == null ) {
|
||||||
|
//"7" picked to use 8, but skipping the odd initialCapacity method
|
||||||
|
internalStack = new ArrayDeque<>( 7 );
|
||||||
}
|
}
|
||||||
|
return internalStack;
|
||||||
current = newCurrent;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public T pop() {
|
public T pop() {
|
||||||
final T popped = this.current;
|
return convert( stackInstanceExpected().removeFirst() );
|
||||||
if ( internalStack.isEmpty() ) {
|
}
|
||||||
this.current = null;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
this.current = internalStack.removeFirst();
|
|
||||||
}
|
|
||||||
|
|
||||||
return popped == nullMarker ? null : popped;
|
private T convert(final Object internalStoredObject) {
|
||||||
|
if ( internalStoredObject == NULL_TOKEN ) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return (T) internalStoredObject;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public T getCurrent() {
|
public T getCurrent() {
|
||||||
return current == nullMarker ? null : current;
|
if ( internalStack == null ) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return convert( internalStack.peek() );
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int depth() {
|
public int depth() {
|
||||||
if ( current == null ) {
|
if ( internalStack == null ) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
else if ( internalStack.isEmpty() ) {
|
return internalStack.size();
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
return internalStack.size() + 1;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isEmpty() {
|
public boolean isEmpty() {
|
||||||
return current == null;
|
if ( internalStack == null ) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return internalStack.isEmpty();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void clear() {
|
public void clear() {
|
||||||
current = null;
|
if ( internalStack != null ) {
|
||||||
internalStack.clear();
|
internalStack.clear();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visitRootFirst(Consumer<T> action) {
|
public void visitRootFirst(Consumer<T> action) {
|
||||||
final int stackSize = internalStack.size();
|
if ( internalStack == null ) {
|
||||||
for ( int i = stackSize - 1; i >= 0; i-- ) {
|
return;
|
||||||
action.accept( internalStack.get( i ) );
|
|
||||||
}
|
}
|
||||||
if ( current != null ) {
|
final Iterator<T> iterator = internalStack.descendingIterator();
|
||||||
action.accept( current );
|
while ( iterator.hasNext() ) {
|
||||||
|
action.accept( iterator.next() );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public <X> X findCurrentFirst(Function<T, X> function) {
|
public <X> X findCurrentFirst(Function<T, X> function) {
|
||||||
if ( current != null ) {
|
if ( internalStack == null ) {
|
||||||
{
|
return null;
|
||||||
final X result = function.apply( current );
|
}
|
||||||
|
final Iterator<T> iterator = internalStack.iterator();
|
||||||
if ( result != null ) {
|
while ( iterator.hasNext() ) {
|
||||||
return result;
|
final X result = function.apply( iterator.next() );
|
||||||
}
|
if ( result != null ) {
|
||||||
}
|
return result;
|
||||||
|
|
||||||
for ( T t : internalStack ) {
|
|
||||||
final X result = function.apply( t );
|
|
||||||
if ( result != null ) {
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -39,21 +39,10 @@ public final class LockModeTypeHelper {
|
||||||
return getLockMode( (LockModeType) value );
|
return getLockMode( (LockModeType) value );
|
||||||
}
|
}
|
||||||
else if ( String.class.isInstance( value ) ) {
|
else if ( String.class.isInstance( value ) ) {
|
||||||
// first try LockMode name
|
return LockMode.fromExternalForm( (String) value );
|
||||||
LockMode lockMode = LockMode.valueOf( (String) value );
|
|
||||||
if ( lockMode == null ) {
|
|
||||||
try {
|
|
||||||
lockMode = getLockMode( LockModeType.valueOf( (String) value ) );
|
|
||||||
}
|
|
||||||
catch ( Exception ignore ) {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if ( lockMode != null ) {
|
|
||||||
return lockMode;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
throw new IllegalArgumentException( "Unknown lock mode source : " + value );
|
throw new IllegalArgumentException( "Unknown lock mode source: '" + value + "'; can't convert from value of type " + value.getClass() );
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -49,6 +49,7 @@ import org.hibernate.graph.spi.RootGraphImplementor;
|
||||||
import org.hibernate.internal.AbstractSharedSessionContract;
|
import org.hibernate.internal.AbstractSharedSessionContract;
|
||||||
import org.hibernate.internal.util.StringHelper;
|
import org.hibernate.internal.util.StringHelper;
|
||||||
import org.hibernate.internal.util.collections.CollectionHelper;
|
import org.hibernate.internal.util.collections.CollectionHelper;
|
||||||
|
import org.hibernate.jpa.internal.util.LockModeTypeHelper;
|
||||||
import org.hibernate.jpa.spi.NativeQueryTupleTransformer;
|
import org.hibernate.jpa.spi.NativeQueryTupleTransformer;
|
||||||
import org.hibernate.metamodel.model.domain.AllowableParameterType;
|
import org.hibernate.metamodel.model.domain.AllowableParameterType;
|
||||||
import org.hibernate.metamodel.model.domain.BasicDomainType;
|
import org.hibernate.metamodel.model.domain.BasicDomainType;
|
||||||
|
@ -77,7 +78,6 @@ import org.hibernate.query.spi.MutableQueryOptions;
|
||||||
import org.hibernate.query.spi.NonSelectQueryPlan;
|
import org.hibernate.query.spi.NonSelectQueryPlan;
|
||||||
import org.hibernate.query.spi.ParameterMetadataImplementor;
|
import org.hibernate.query.spi.ParameterMetadataImplementor;
|
||||||
import org.hibernate.query.spi.QueryEngine;
|
import org.hibernate.query.spi.QueryEngine;
|
||||||
import org.hibernate.query.spi.QueryImplementor;
|
|
||||||
import org.hibernate.query.spi.QueryInterpretationCache;
|
import org.hibernate.query.spi.QueryInterpretationCache;
|
||||||
import org.hibernate.query.spi.QueryParameterBindings;
|
import org.hibernate.query.spi.QueryParameterBindings;
|
||||||
import org.hibernate.query.spi.QueryParameterImplementor;
|
import org.hibernate.query.spi.QueryParameterImplementor;
|
||||||
|
@ -94,7 +94,6 @@ import org.hibernate.sql.exec.internal.CallbackImpl;
|
||||||
import org.hibernate.sql.exec.spi.Callback;
|
import org.hibernate.sql.exec.spi.Callback;
|
||||||
import org.hibernate.sql.exec.spi.ExecutionContext;
|
import org.hibernate.sql.exec.spi.ExecutionContext;
|
||||||
import org.hibernate.sql.results.jdbc.spi.JdbcValuesMappingProducer;
|
import org.hibernate.sql.results.jdbc.spi.JdbcValuesMappingProducer;
|
||||||
import org.hibernate.sql.results.spi.RowTransformer;
|
|
||||||
import org.hibernate.transform.ResultTransformer;
|
import org.hibernate.transform.ResultTransformer;
|
||||||
import org.hibernate.type.BasicType;
|
import org.hibernate.type.BasicType;
|
||||||
import org.hibernate.type.BasicTypeReference;
|
import org.hibernate.type.BasicTypeReference;
|
||||||
|
@ -1067,6 +1066,9 @@ public class NativeQueryImpl<R>
|
||||||
else if ( value instanceof LockModeType ) {
|
else if ( value instanceof LockModeType ) {
|
||||||
applyLockModeTypeHint( (LockModeType) value );
|
applyLockModeTypeHint( (LockModeType) value );
|
||||||
}
|
}
|
||||||
|
else if ( String.class.isInstance( value ) ) {
|
||||||
|
applyHibernateLockModeHint( LockModeTypeHelper.interpretLockMode( value ) );
|
||||||
|
}
|
||||||
else {
|
else {
|
||||||
throw new IllegalArgumentException(
|
throw new IllegalArgumentException(
|
||||||
String.format(
|
String.format(
|
||||||
|
|
|
@ -16,8 +16,10 @@ import jakarta.persistence.NamedQueries;
|
||||||
import jakarta.persistence.NamedQuery;
|
import jakarta.persistence.NamedQuery;
|
||||||
import jakarta.persistence.Query;
|
import jakarta.persistence.Query;
|
||||||
|
|
||||||
|
import org.hibernate.LockMode;
|
||||||
import org.hibernate.Session;
|
import org.hibernate.Session;
|
||||||
import org.hibernate.orm.test.jpa.BaseEntityManagerFunctionalTestCase;
|
import org.hibernate.orm.test.jpa.BaseEntityManagerFunctionalTestCase;
|
||||||
|
import org.hibernate.jpa.QueryHints;
|
||||||
import org.hibernate.query.NativeQuery;
|
import org.hibernate.query.NativeQuery;
|
||||||
|
|
||||||
import org.hibernate.testing.TestForIssue;
|
import org.hibernate.testing.TestForIssue;
|
||||||
|
@ -192,6 +194,18 @@ public class NamedQueryTest extends BaseEntityManagerFunctionalTestCase {
|
||||||
} );
|
} );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestForIssue(jiraKey = "HHH-14816")
|
||||||
|
public void testQueryHintLockMode() {
|
||||||
|
doInJPA( this::entityManagerFactory, entityManager -> {
|
||||||
|
Query query = entityManager.createNamedQuery( "NamedNativeQuery" );
|
||||||
|
query.setHint( QueryHints.HINT_NATIVE_LOCKMODE, "none" );
|
||||||
|
query.setParameter( 1, GAME_TITLES[0] );
|
||||||
|
assertEquals( LockMode.NONE, query.getHints().get( QueryHints.HINT_NATIVE_LOCKMODE ) );
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
@Entity(name = "Game")
|
@Entity(name = "Game")
|
||||||
@NamedQueries(@NamedQuery(name = "NamedQuery", query = "select g from Game g where title = ?1"))
|
@NamedQueries(@NamedQuery(name = "NamedQuery", query = "select g from Game g where title = ?1"))
|
||||||
@NamedNativeQueries(@NamedNativeQuery(name = "NamedNativeQuery", query = "select * from Game g where title = ?"))
|
@NamedNativeQueries(@NamedNativeQuery(name = "NamedNativeQuery", query = "select * from Game g where title = ?"))
|
||||||
|
|
Loading…
Reference in New Issue