Merge remote-tracking branch 'upstream/main' into wip/6.0_merge

This commit is contained in:
Andrea Boriero 2021-10-19 16:23:07 +02:00
commit 7f46f11f3b
6 changed files with 81 additions and 70 deletions

View File

@ -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.

View File

@ -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;

View File

@ -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;
} }
} }

View File

@ -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() );
} }
} }

View File

@ -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(

View File

@ -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 = ?"))