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.
|
||||
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.
|
||||
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
|
||||
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
|
||||
|
@ -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
|
||||
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
|
||||
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.
|
||||
|
||||
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:
|
||||
|
||||
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::
|
||||
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;
|
||||
}
|
||||
|
||||
for ( LockMode lockMode : LockMode.values() ) {
|
||||
if ( lockMode.externalForm.equals( externalForm ) ) {
|
||||
return lockMode;
|
||||
}
|
||||
}
|
||||
|
||||
for ( LockMode lockMode : LockMode.values() ) {
|
||||
if ( lockMode.externalForm.equalsIgnoreCase( externalForm ) ) {
|
||||
return lockMode;
|
||||
|
|
|
@ -6,117 +6,117 @@
|
|||
*/
|
||||
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.Function;
|
||||
|
||||
/**
|
||||
* A general-purpose stack impl.
|
||||
* A general-purpose stack impl supporting null values.
|
||||
*
|
||||
* @param <T> The type of things stored in the stack
|
||||
*
|
||||
* @author Steve Ebersole
|
||||
* @author Sanne Grinovero
|
||||
*/
|
||||
public final class StandardStack<T> implements Stack<T> {
|
||||
@SuppressWarnings("unchecked")
|
||||
private final T nullMarker = (T) new Object();
|
||||
|
||||
private T current;
|
||||
|
||||
private final LinkedList<T> internalStack = new LinkedList<>();
|
||||
private ArrayDeque<T> internalStack;
|
||||
private static final Object NULL_TOKEN = new Object();
|
||||
|
||||
public StandardStack() {
|
||||
}
|
||||
|
||||
public StandardStack(T initial) {
|
||||
current = initial;
|
||||
stackInstanceExpected().addFirst( initial );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void push(T newCurrent) {
|
||||
Object toStore = newCurrent;
|
||||
if ( newCurrent == null ) {
|
||||
newCurrent = nullMarker;
|
||||
toStore = NULL_TOKEN;
|
||||
}
|
||||
stackInstanceExpected().addFirst( toStore );
|
||||
}
|
||||
|
||||
if ( current != null ) {
|
||||
internalStack.addFirst( current );
|
||||
private Deque stackInstanceExpected() {
|
||||
if ( internalStack == null ) {
|
||||
//"7" picked to use 8, but skipping the odd initialCapacity method
|
||||
internalStack = new ArrayDeque<>( 7 );
|
||||
}
|
||||
|
||||
current = newCurrent;
|
||||
return internalStack;
|
||||
}
|
||||
|
||||
@Override
|
||||
public T pop() {
|
||||
final T popped = this.current;
|
||||
if ( internalStack.isEmpty() ) {
|
||||
this.current = null;
|
||||
}
|
||||
else {
|
||||
this.current = internalStack.removeFirst();
|
||||
}
|
||||
return convert( stackInstanceExpected().removeFirst() );
|
||||
}
|
||||
|
||||
return popped == nullMarker ? null : popped;
|
||||
private T convert(final Object internalStoredObject) {
|
||||
if ( internalStoredObject == NULL_TOKEN ) {
|
||||
return null;
|
||||
}
|
||||
return (T) internalStoredObject;
|
||||
}
|
||||
|
||||
@Override
|
||||
public T getCurrent() {
|
||||
return current == nullMarker ? null : current;
|
||||
if ( internalStack == null ) {
|
||||
return null;
|
||||
}
|
||||
return convert( internalStack.peek() );
|
||||
}
|
||||
|
||||
@Override
|
||||
public int depth() {
|
||||
if ( current == null ) {
|
||||
if ( internalStack == null ) {
|
||||
return 0;
|
||||
}
|
||||
else if ( internalStack.isEmpty() ) {
|
||||
return 1;
|
||||
}
|
||||
else {
|
||||
return internalStack.size() + 1;
|
||||
}
|
||||
return internalStack.size();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEmpty() {
|
||||
return current == null;
|
||||
if ( internalStack == null ) {
|
||||
return true;
|
||||
}
|
||||
return internalStack.isEmpty();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clear() {
|
||||
current = null;
|
||||
internalStack.clear();
|
||||
if ( internalStack != null ) {
|
||||
internalStack.clear();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitRootFirst(Consumer<T> action) {
|
||||
final int stackSize = internalStack.size();
|
||||
for ( int i = stackSize - 1; i >= 0; i-- ) {
|
||||
action.accept( internalStack.get( i ) );
|
||||
if ( internalStack == null ) {
|
||||
return;
|
||||
}
|
||||
if ( current != null ) {
|
||||
action.accept( current );
|
||||
final Iterator<T> iterator = internalStack.descendingIterator();
|
||||
while ( iterator.hasNext() ) {
|
||||
action.accept( iterator.next() );
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public <X> X findCurrentFirst(Function<T, X> function) {
|
||||
if ( current != null ) {
|
||||
{
|
||||
final X result = function.apply( current );
|
||||
|
||||
if ( result != null ) {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
for ( T t : internalStack ) {
|
||||
final X result = function.apply( t );
|
||||
if ( result != null ) {
|
||||
return result;
|
||||
}
|
||||
if ( internalStack == null ) {
|
||||
return null;
|
||||
}
|
||||
final Iterator<T> iterator = internalStack.iterator();
|
||||
while ( iterator.hasNext() ) {
|
||||
final X result = function.apply( iterator.next() );
|
||||
if ( result != null ) {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -39,21 +39,10 @@ public final class LockModeTypeHelper {
|
|||
return getLockMode( (LockModeType) value );
|
||||
}
|
||||
else if ( String.class.isInstance( value ) ) {
|
||||
// first try LockMode name
|
||||
LockMode lockMode = LockMode.valueOf( (String) value );
|
||||
if ( lockMode == null ) {
|
||||
try {
|
||||
lockMode = getLockMode( LockModeType.valueOf( (String) value ) );
|
||||
}
|
||||
catch ( Exception ignore ) {
|
||||
}
|
||||
}
|
||||
if ( lockMode != null ) {
|
||||
return lockMode;
|
||||
}
|
||||
return LockMode.fromExternalForm( (String) value );
|
||||
}
|
||||
|
||||
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.util.StringHelper;
|
||||
import org.hibernate.internal.util.collections.CollectionHelper;
|
||||
import org.hibernate.jpa.internal.util.LockModeTypeHelper;
|
||||
import org.hibernate.jpa.spi.NativeQueryTupleTransformer;
|
||||
import org.hibernate.metamodel.model.domain.AllowableParameterType;
|
||||
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.ParameterMetadataImplementor;
|
||||
import org.hibernate.query.spi.QueryEngine;
|
||||
import org.hibernate.query.spi.QueryImplementor;
|
||||
import org.hibernate.query.spi.QueryInterpretationCache;
|
||||
import org.hibernate.query.spi.QueryParameterBindings;
|
||||
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.ExecutionContext;
|
||||
import org.hibernate.sql.results.jdbc.spi.JdbcValuesMappingProducer;
|
||||
import org.hibernate.sql.results.spi.RowTransformer;
|
||||
import org.hibernate.transform.ResultTransformer;
|
||||
import org.hibernate.type.BasicType;
|
||||
import org.hibernate.type.BasicTypeReference;
|
||||
|
@ -1067,6 +1066,9 @@ public class NativeQueryImpl<R>
|
|||
else if ( value instanceof LockModeType ) {
|
||||
applyLockModeTypeHint( (LockModeType) value );
|
||||
}
|
||||
else if ( String.class.isInstance( value ) ) {
|
||||
applyHibernateLockModeHint( LockModeTypeHelper.interpretLockMode( value ) );
|
||||
}
|
||||
else {
|
||||
throw new IllegalArgumentException(
|
||||
String.format(
|
||||
|
|
|
@ -16,8 +16,10 @@ import jakarta.persistence.NamedQueries;
|
|||
import jakarta.persistence.NamedQuery;
|
||||
import jakarta.persistence.Query;
|
||||
|
||||
import org.hibernate.LockMode;
|
||||
import org.hibernate.Session;
|
||||
import org.hibernate.orm.test.jpa.BaseEntityManagerFunctionalTestCase;
|
||||
import org.hibernate.jpa.QueryHints;
|
||||
import org.hibernate.query.NativeQuery;
|
||||
|
||||
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")
|
||||
@NamedQueries(@NamedQuery(name = "NamedQuery", query = "select g from Game g where title = ?1"))
|
||||
@NamedNativeQueries(@NamedNativeQuery(name = "NamedNativeQuery", query = "select * from Game g where title = ?"))
|
||||
|
|
Loading…
Reference in New Issue