HHH-14600 verify UUID
This commit is contained in:
parent
0f683ff25d
commit
d53216306f
|
@ -9,6 +9,7 @@ package org.hibernate.boot.model;
|
|||
import org.hibernate.type.BasicType;
|
||||
import org.hibernate.type.StandardBasicTypeTemplate;
|
||||
import org.hibernate.type.descriptor.java.spi.JavaTypeDescriptorRegistry;
|
||||
import org.hibernate.type.descriptor.jdbc.spi.JdbcTypeDescriptorRegistry;
|
||||
import org.hibernate.type.descriptor.jdbc.JdbcTypeDescriptor;
|
||||
import org.hibernate.type.descriptor.java.JavaTypeDescriptor;
|
||||
import org.hibernate.type.spi.TypeConfiguration;
|
||||
|
@ -29,8 +30,8 @@ public interface TypeContributions {
|
|||
void contributeJavaTypeDescriptor(JavaTypeDescriptor descriptor);
|
||||
|
||||
/**
|
||||
* Add the JavaTypeDescriptor to the {@link TypeConfiguration}'s
|
||||
* {@link JavaTypeDescriptorRegistry}
|
||||
* Add the JdbcTypeDescriptor to the {@link TypeConfiguration}'s
|
||||
* {@link JdbcTypeDescriptorRegistry}
|
||||
*/
|
||||
void contributeJdbcTypeDescriptor(JdbcTypeDescriptor descriptor);
|
||||
|
||||
|
|
|
@ -6,6 +6,16 @@
|
|||
*/
|
||||
package org.hibernate.dialect;
|
||||
|
||||
import java.sql.CallableStatement;
|
||||
import java.sql.DatabaseMetaData;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.sql.Types;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import javax.persistence.TemporalType;
|
||||
|
||||
import org.hibernate.LockMode;
|
||||
import org.hibernate.LockOptions;
|
||||
import org.hibernate.PessimisticLockException;
|
||||
|
@ -41,28 +51,11 @@ import org.hibernate.sql.ast.SqlAstTranslatorFactory;
|
|||
import org.hibernate.sql.ast.spi.StandardSqlAstTranslatorFactory;
|
||||
import org.hibernate.sql.ast.tree.Statement;
|
||||
import org.hibernate.sql.exec.spi.JdbcOperation;
|
||||
import org.hibernate.type.PostgresUUIDType;
|
||||
import org.hibernate.type.StandardBasicTypes;
|
||||
import org.hibernate.type.descriptor.ValueBinder;
|
||||
import org.hibernate.type.descriptor.ValueExtractor;
|
||||
import org.hibernate.type.descriptor.WrapperOptions;
|
||||
import org.hibernate.type.descriptor.java.BasicJavaDescriptor;
|
||||
import org.hibernate.type.descriptor.java.JavaTypeDescriptor;
|
||||
import org.hibernate.type.descriptor.jdbc.BasicBinder;
|
||||
import org.hibernate.type.descriptor.jdbc.BasicExtractor;
|
||||
import org.hibernate.type.descriptor.jdbc.BlobTypeDescriptor;
|
||||
import org.hibernate.type.descriptor.jdbc.ClobTypeDescriptor;
|
||||
import org.hibernate.type.descriptor.jdbc.JdbcLiteralFormatter;
|
||||
import org.hibernate.type.descriptor.jdbc.JdbcTypeDescriptor;
|
||||
import org.hibernate.type.descriptor.jdbc.spi.JdbcTypeDescriptorRegistry;
|
||||
import org.hibernate.type.spi.TypeConfiguration;
|
||||
|
||||
import java.sql.*;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
|
||||
import javax.persistence.TemporalType;
|
||||
|
||||
import static org.hibernate.exception.spi.TemplatedViolatedConstraintNameExtractor.extractUsingTemplate;
|
||||
import static org.hibernate.query.TemporalUnit.*;
|
||||
|
@ -110,9 +103,13 @@ public class PostgreSQLDialect extends Dialect {
|
|||
registerColumnType( Types.LONGVARCHAR, "text" );
|
||||
registerColumnType( Types.LONGNVARCHAR, "text" );
|
||||
|
||||
if ( getVersion() >= 820 ) {
|
||||
registerColumnType( PostgresUUIDType.INSTANCE.sqlType(), "uuid" );
|
||||
|
||||
if ( getVersion() >= 920 ) {
|
||||
registerColumnType( Types.JAVA_OBJECT, "json" );
|
||||
}
|
||||
}
|
||||
|
||||
getDefaultProperties().setProperty( Environment.STATEMENT_BATCH_SIZE, DEFAULT_BATCH_SIZE );
|
||||
getDefaultProperties().setProperty( Environment.NON_CONTEXTUAL_LOB_CREATION, "true" );
|
||||
|
@ -823,91 +820,7 @@ public class PostgreSQLDialect extends Dialect {
|
|||
|
||||
if ( getVersion() >= 820 ) {
|
||||
// HHH-9562
|
||||
typeContributions.contributeJdbcTypeDescriptor( PostgresUUIDType.INSTANCE );
|
||||
}
|
||||
}
|
||||
|
||||
private static class PostgresUUIDType implements JdbcTypeDescriptor {
|
||||
/**
|
||||
* Singleton access
|
||||
*/
|
||||
private static final PostgresUUIDType INSTANCE = new PostgresUUIDType();
|
||||
|
||||
/**
|
||||
* Postgres reports its UUID type as {@link java.sql.Types#OTHER}. Unfortunately
|
||||
* it reports a lot of its types as {@link java.sql.Types#OTHER}, making that
|
||||
* value useless for distinguishing one SqlTypeDescriptor from another.
|
||||
* So here we define a "magic value" that is a (hopefully no collisions)
|
||||
* unique key within the {@link JdbcTypeDescriptorRegistry}
|
||||
*/
|
||||
private static final int JDBC_TYPE_CODE = 3975;
|
||||
|
||||
@Override
|
||||
public int getJdbcType() {
|
||||
return JDBC_TYPE_CODE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getJdbcTypeCode() {
|
||||
return getJdbcType();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canBeRemapped() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <J> BasicJavaDescriptor<J> getJdbcRecommendedJavaTypeMapping(TypeConfiguration typeConfiguration) {
|
||||
return (BasicJavaDescriptor<J>) typeConfiguration.getJavaTypeDescriptorRegistry().resolveDescriptor( UUID.class );
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> JdbcLiteralFormatter<T> getJdbcLiteralFormatter(JavaTypeDescriptor<T> javaTypeDescriptor) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <X> ValueBinder<X> getBinder(JavaTypeDescriptor<X> javaTypeDescriptor) {
|
||||
return new BasicBinder<X>( javaTypeDescriptor, this ) {
|
||||
@Override
|
||||
protected void doBind(
|
||||
PreparedStatement st,
|
||||
X value,
|
||||
int index,
|
||||
WrapperOptions wrapperOptions) throws SQLException {
|
||||
st.setObject( index, javaTypeDescriptor.unwrap( value, UUID.class, wrapperOptions ), Types.OTHER );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doBind(
|
||||
CallableStatement st,
|
||||
X value,
|
||||
String name,
|
||||
WrapperOptions wrapperOptions) throws SQLException {
|
||||
st.setObject( name, javaTypeDescriptor.unwrap( value, UUID.class, wrapperOptions ), Types.OTHER );
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public <X> ValueExtractor<X> getExtractor(JavaTypeDescriptor<X> javaTypeDescriptor) {
|
||||
return new BasicExtractor<X>( javaTypeDescriptor, this ) {
|
||||
@Override
|
||||
protected X doExtract(ResultSet rs, int position, WrapperOptions wrapperOptions) throws SQLException {
|
||||
return javaTypeDescriptor.wrap( rs.getObject( position ), wrapperOptions );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected X doExtract(CallableStatement statement, int position, WrapperOptions wrapperOptions) throws SQLException {
|
||||
return javaTypeDescriptor.wrap( statement.getObject( position ), wrapperOptions );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected X doExtract(CallableStatement statement, String name, WrapperOptions wrapperOptions) throws SQLException {
|
||||
return javaTypeDescriptor.wrap( statement.getObject( name ), wrapperOptions );
|
||||
}
|
||||
};
|
||||
typeContributions.contributeType( PostgresUUIDType.INSTANCE );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -21,7 +21,9 @@ import org.hibernate.type.descriptor.java.JavaTypeDescriptor;
|
|||
import org.hibernate.type.descriptor.java.UUIDTypeDescriptor;
|
||||
import org.hibernate.type.descriptor.jdbc.BasicBinder;
|
||||
import org.hibernate.type.descriptor.jdbc.BasicExtractor;
|
||||
import org.hibernate.type.descriptor.jdbc.JdbcLiteralFormatter;
|
||||
import org.hibernate.type.descriptor.jdbc.JdbcTypeDescriptor;
|
||||
import org.hibernate.type.descriptor.jdbc.spi.JdbcTypeDescriptorRegistry;
|
||||
import org.hibernate.type.spi.TypeConfiguration;
|
||||
|
||||
/**
|
||||
|
@ -48,22 +50,29 @@ public class PostgresUUIDType extends AbstractSingleColumnStandardBasicType<UUID
|
|||
return true;
|
||||
}
|
||||
|
||||
public static class PostgresUUIDJdbcTypeDescriptor implements JdbcTypeDescriptor {
|
||||
public static final PostgresUUIDJdbcTypeDescriptor INSTANCE = new PostgresUUIDJdbcTypeDescriptor();
|
||||
private static class PostgresUUIDJdbcTypeDescriptor implements JdbcTypeDescriptor {
|
||||
/**
|
||||
* Singleton access
|
||||
*/
|
||||
private static final PostgresUUIDJdbcTypeDescriptor INSTANCE = new PostgresUUIDJdbcTypeDescriptor();
|
||||
|
||||
/**
|
||||
* Postgres reports its UUID type as {@link java.sql.Types#OTHER}. Unfortunately
|
||||
* it reports a lot of its types as {@link java.sql.Types#OTHER}, making that
|
||||
* value useless for distinguishing one SqlTypeDescriptor from another.
|
||||
* So here we define a "magic value" that is a (hopefully no collisions)
|
||||
* unique key within the {@link JdbcTypeDescriptorRegistry}
|
||||
*/
|
||||
private static final int JDBC_TYPE_CODE = 3975;
|
||||
|
||||
@Override
|
||||
public int getJdbcType() {
|
||||
// ugh
|
||||
return Types.OTHER;
|
||||
return JDBC_TYPE_CODE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getFriendlyName() {
|
||||
return "OTHER (pg-uuid)";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "PostgresUUIDSqlTypeDescriptor";
|
||||
public int getJdbcTypeCode() {
|
||||
return getJdbcType();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -72,41 +81,63 @@ public class PostgresUUIDType extends AbstractSingleColumnStandardBasicType<UUID
|
|||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public BasicJavaDescriptor getJdbcRecommendedJavaTypeMapping(TypeConfiguration typeConfiguration) {
|
||||
return (BasicJavaDescriptor) typeConfiguration.getJavaTypeDescriptorRegistry().getDescriptor( UUID.class );
|
||||
public <J> BasicJavaDescriptor<J> getJdbcRecommendedJavaTypeMapping(TypeConfiguration typeConfiguration) {
|
||||
return (BasicJavaDescriptor<J>) typeConfiguration.getJavaTypeDescriptorRegistry().resolveDescriptor( UUID.class );
|
||||
}
|
||||
|
||||
public <X> ValueBinder<X> getBinder(final JavaTypeDescriptor<X> javaTypeDescriptor) {
|
||||
@Override
|
||||
public <T> JdbcLiteralFormatter<T> getJdbcLiteralFormatter(JavaTypeDescriptor<T> javaTypeDescriptor) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <X> ValueBinder<X> getBinder(JavaTypeDescriptor<X> javaTypeDescriptor) {
|
||||
return new BasicBinder<X>( javaTypeDescriptor, this ) {
|
||||
|
||||
@Override
|
||||
protected void doBind(PreparedStatement st, X value, int index, WrapperOptions options) throws SQLException {
|
||||
st.setObject( index, javaTypeDescriptor.unwrap( value, UUID.class, options ), getJdbcType() );
|
||||
protected void doBindNull(PreparedStatement st, int index, WrapperOptions wrapperOptions) throws SQLException {
|
||||
st.setNull( index, Types.OTHER );
|
||||
}
|
||||
@Override
|
||||
protected void doBind(
|
||||
PreparedStatement st,
|
||||
X value,
|
||||
int index,
|
||||
WrapperOptions wrapperOptions) throws SQLException {
|
||||
st.setObject( index, javaTypeDescriptor.unwrap( value, UUID.class, wrapperOptions ), Types.OTHER );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doBind(CallableStatement st, X value, String name, WrapperOptions options)
|
||||
throws SQLException {
|
||||
st.setObject( name, javaTypeDescriptor.unwrap( value, UUID.class, options ), getJdbcType() );
|
||||
protected void doBindNull(CallableStatement st, String name, WrapperOptions wrapperOptions) throws SQLException {
|
||||
st.setNull( name, Types.OTHER );
|
||||
}
|
||||
@Override
|
||||
protected void doBind(
|
||||
CallableStatement st,
|
||||
X value,
|
||||
String name,
|
||||
WrapperOptions wrapperOptions) throws SQLException {
|
||||
st.setObject( name, javaTypeDescriptor.unwrap( value, UUID.class, wrapperOptions ), Types.OTHER );
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public <X> ValueExtractor<X> getExtractor(final JavaTypeDescriptor<X> javaTypeDescriptor) {
|
||||
@Override
|
||||
public <X> ValueExtractor<X> getExtractor(JavaTypeDescriptor<X> javaTypeDescriptor) {
|
||||
return new BasicExtractor<X>( javaTypeDescriptor, this ) {
|
||||
@Override
|
||||
protected X doExtract(ResultSet rs, int name, WrapperOptions options) throws SQLException {
|
||||
return javaTypeDescriptor.wrap( rs.getObject( name ), options );
|
||||
protected X doExtract(ResultSet rs, int position, WrapperOptions wrapperOptions) throws SQLException {
|
||||
return javaTypeDescriptor.wrap( rs.getObject( position ), wrapperOptions );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected X doExtract(CallableStatement statement, int index, WrapperOptions options) throws SQLException {
|
||||
return javaTypeDescriptor.wrap( statement.getObject( index ), options );
|
||||
protected X doExtract(CallableStatement statement, int position, WrapperOptions wrapperOptions) throws SQLException {
|
||||
return javaTypeDescriptor.wrap( statement.getObject( position ), wrapperOptions );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected X doExtract(CallableStatement statement, String name, WrapperOptions options) throws SQLException {
|
||||
return javaTypeDescriptor.wrap( statement.getObject( name ), options );
|
||||
protected X doExtract(CallableStatement statement, String name, WrapperOptions wrapperOptions) throws SQLException {
|
||||
return javaTypeDescriptor.wrap( statement.getObject( name ), wrapperOptions );
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
|
@ -124,6 +124,16 @@ public interface JdbcTypeDescriptor extends Serializable {
|
|||
return false;
|
||||
}
|
||||
|
||||
default boolean isBinary() {
|
||||
switch ( getJdbcType() ) {
|
||||
case Types.BINARY:
|
||||
case Types.VARBINARY:
|
||||
case Types.LONGVARBINARY:
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
default boolean isString() {
|
||||
switch ( getJdbcType() ) {
|
||||
case Types.CHAR:
|
||||
|
|
|
@ -0,0 +1,92 @@
|
|||
/*
|
||||
* 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.orm.test.id.uuid;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.GeneratedValue;
|
||||
import javax.persistence.Id;
|
||||
|
||||
import org.hibernate.dialect.PostgreSQLDialect;
|
||||
import org.hibernate.query.NativeQuery;
|
||||
import org.hibernate.type.PostgresUUIDType;
|
||||
|
||||
import org.hibernate.testing.orm.junit.DomainModel;
|
||||
import org.hibernate.testing.orm.junit.RequiresDialect;
|
||||
import org.hibernate.testing.orm.junit.SessionFactory;
|
||||
import org.hibernate.testing.orm.junit.SessionFactoryScope;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static org.hamcrest.MatcherAssert.assertThat;
|
||||
import static org.hamcrest.Matchers.hasSize;
|
||||
import static org.hamcrest.Matchers.notNullValue;
|
||||
|
||||
/**
|
||||
* @author Vlad Mihalcea
|
||||
*/
|
||||
@RequiresDialect(value = PostgreSQLDialect.class, version = 940)
|
||||
@DomainModel(annotatedClasses = { PostgreSQLUUIDGeneratedValueTest.Book.class })
|
||||
@SessionFactory
|
||||
public class PostgreSQLUUIDGeneratedValueTest {
|
||||
|
||||
private UUID id;
|
||||
|
||||
@BeforeEach
|
||||
void setUp(SessionFactoryScope scope) {
|
||||
id = scope.fromTransaction( session -> {
|
||||
final Book book = new Book();
|
||||
book.title = "High-Performance Java Persistence";
|
||||
book.author = "Vlad Mihalcea";
|
||||
session.persist( book );
|
||||
return book.id;
|
||||
} );
|
||||
assertThat( id, notNullValue() );
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testJPQL(SessionFactoryScope scope) {
|
||||
scope.inTransaction( session -> {
|
||||
final List<UUID> books = session.createQuery(
|
||||
"select b.id " +
|
||||
"from Book b " +
|
||||
"where b.id = :id", UUID.class)
|
||||
.setParameter( "id", id )
|
||||
.getResultList();
|
||||
assertThat( books, hasSize( 1 ) );
|
||||
} );
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNativeSQL(SessionFactoryScope scope) {
|
||||
scope.inTransaction( session -> {
|
||||
final List<?> books = session.createNativeQuery(
|
||||
"select b.id as id " +
|
||||
"from Book b " +
|
||||
"where b.id = :id")
|
||||
.setParameter( "id", id )
|
||||
.unwrap( NativeQuery.class )
|
||||
.addScalar( "id", PostgresUUIDType.INSTANCE )
|
||||
.getResultList();
|
||||
assertThat( books, hasSize( 1 ) );
|
||||
} );
|
||||
}
|
||||
|
||||
@Entity(name = "Book")
|
||||
static class Book {
|
||||
|
||||
@Id
|
||||
@GeneratedValue
|
||||
UUID id;
|
||||
|
||||
String title;
|
||||
|
||||
String author;
|
||||
|
||||
}
|
||||
}
|
|
@ -0,0 +1,70 @@
|
|||
package org.hibernate.orm.test.id.uuid.generator;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.ElementCollection;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.GeneratedValue;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.JoinTable;
|
||||
|
||||
import org.hibernate.annotations.GenericGenerator;
|
||||
import org.hibernate.dialect.SQLServerDialect;
|
||||
|
||||
import org.hibernate.testing.orm.junit.DomainModel;
|
||||
import org.hibernate.testing.orm.junit.JiraKey;
|
||||
import org.hibernate.testing.orm.junit.RequiresDialect;
|
||||
import org.hibernate.testing.orm.junit.SessionFactory;
|
||||
import org.hibernate.testing.orm.junit.SessionFactoryScope;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static org.hamcrest.MatcherAssert.assertThat;
|
||||
import static org.hamcrest.Matchers.hasSize;
|
||||
import static org.hamcrest.Matchers.notNullValue;
|
||||
|
||||
/**
|
||||
* @author Vlad Mihalcea
|
||||
*/
|
||||
@RequiresDialect( SQLServerDialect.class )
|
||||
@JiraKey( "HHH-12943" )
|
||||
@DomainModel(annotatedClasses = { UUID2GeneratorBinaryUniqueIdentifierIdTest.FooEntity.class })
|
||||
@SessionFactory
|
||||
public class UUID2GeneratorBinaryUniqueIdentifierIdTest {
|
||||
|
||||
@Test
|
||||
public void testPaginationQuery(SessionFactoryScope scope) {
|
||||
final byte[] id = scope.fromTransaction( session -> {
|
||||
final FooEntity entity = new FooEntity();
|
||||
entity.fooValues.add("one");
|
||||
entity.fooValues.add("two");
|
||||
entity.fooValues.add("three");
|
||||
session.persist( entity );
|
||||
return entity.id;
|
||||
} );
|
||||
|
||||
assertThat( id, notNullValue() );
|
||||
|
||||
scope.inTransaction( session -> {
|
||||
final FooEntity entity = session.find(FooEntity.class, id);
|
||||
assertThat( entity, notNullValue() );
|
||||
assertThat( entity.fooValues, hasSize( 3 ) );
|
||||
} );
|
||||
}
|
||||
|
||||
@Entity(name = "FooEntity")
|
||||
static class FooEntity {
|
||||
|
||||
@Id
|
||||
@GenericGenerator(name = "uuid", strategy = "uuid2")
|
||||
@GeneratedValue(generator = "uuid")
|
||||
@Column(columnDefinition = "UNIQUEIDENTIFIER")
|
||||
byte[] id;
|
||||
|
||||
@ElementCollection
|
||||
@JoinTable(name = "foo_values")
|
||||
@Column(name = "foo_value")
|
||||
final Set<String> fooValues = new HashSet<>();
|
||||
|
||||
}
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
package org.hibernate.test.id.uuid;
|
||||
package org.hibernate.orm.test.id.uuid.generator;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
|
@ -0,0 +1,71 @@
|
|||
package org.hibernate.orm.test.id.uuid.generator;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.ElementCollection;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.GeneratedValue;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.JoinTable;
|
||||
|
||||
import org.hibernate.annotations.GenericGenerator;
|
||||
import org.hibernate.dialect.SQLServerDialect;
|
||||
|
||||
import org.hibernate.testing.orm.junit.DomainModel;
|
||||
import org.hibernate.testing.orm.junit.JiraKey;
|
||||
import org.hibernate.testing.orm.junit.RequiresDialect;
|
||||
import org.hibernate.testing.orm.junit.SessionFactory;
|
||||
import org.hibernate.testing.orm.junit.SessionFactoryScope;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static org.hamcrest.CoreMatchers.notNullValue;
|
||||
import static org.hamcrest.MatcherAssert.assertThat;
|
||||
import static org.hamcrest.Matchers.hasSize;
|
||||
|
||||
/**
|
||||
* @author Vlad Mihalcea
|
||||
*/
|
||||
@RequiresDialect( SQLServerDialect.class )
|
||||
@JiraKey( "HHH-12943" )
|
||||
@DomainModel(annotatedClasses = { UUID2GeneratorUniqueIdentifierIdTest.FooEntity.class })
|
||||
@SessionFactory
|
||||
public class UUID2GeneratorUniqueIdentifierIdTest {
|
||||
|
||||
@Test
|
||||
public void testPaginationQuery(SessionFactoryScope scope) {
|
||||
final UUID id = scope.fromTransaction( session -> {
|
||||
final FooEntity entity = new FooEntity();
|
||||
entity.fooValues.add("one");
|
||||
entity.fooValues.add("two");
|
||||
entity.fooValues.add("three");
|
||||
session.persist( entity );
|
||||
return entity.id;
|
||||
} );
|
||||
|
||||
assertThat( id, notNullValue() );
|
||||
|
||||
scope.inTransaction( session -> {
|
||||
final FooEntity entity = session.find(FooEntity.class, id);
|
||||
assertThat( entity, notNullValue() );
|
||||
assertThat( entity.fooValues, hasSize( 3 ) );
|
||||
} );
|
||||
}
|
||||
|
||||
@Entity(name = "FootEntity")
|
||||
static class FooEntity {
|
||||
|
||||
@Id
|
||||
@GenericGenerator(name = "uuid", strategy = "uuid2")
|
||||
@GeneratedValue(generator = "uuid")
|
||||
@Column(columnDefinition = "UNIQUEIDENTIFIER")
|
||||
UUID id;
|
||||
|
||||
@ElementCollection
|
||||
@JoinTable(name = "foo_values")
|
||||
@Column(name = "foo_value")
|
||||
final Set<String> fooValues = new HashSet<>();
|
||||
|
||||
}
|
||||
}
|
|
@ -0,0 +1,84 @@
|
|||
/*
|
||||
* 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.orm.test.id.uuid.interpretation;
|
||||
|
||||
import java.util.UUID;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.GeneratedValue;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.Table;
|
||||
|
||||
import org.hibernate.dialect.H2Dialect;
|
||||
import org.hibernate.dialect.MySQLDialect;
|
||||
import org.hibernate.dialect.PostgreSQLDialect;
|
||||
import org.hibernate.mapping.PersistentClass;
|
||||
import org.hibernate.type.PostgresUUIDType;
|
||||
import org.hibernate.type.Type;
|
||||
import org.hibernate.type.UUIDBinaryType;
|
||||
|
||||
import org.hibernate.testing.orm.junit.DomainModel;
|
||||
import org.hibernate.testing.orm.junit.DomainModelScope;
|
||||
import org.hibernate.testing.orm.junit.JiraKey;
|
||||
import org.hibernate.testing.orm.junit.RequiresDialect;
|
||||
import org.hibernate.testing.orm.junit.SessionFactory;
|
||||
import org.hibernate.testing.orm.junit.SessionFactoryScope;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static org.hamcrest.MatcherAssert.assertThat;
|
||||
import static org.hamcrest.core.IsInstanceOf.instanceOf;
|
||||
|
||||
/**
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
@DomainModel(annotatedClasses = { UUIDBasedIdInterpretationTest.UuidIdEntity.class })
|
||||
@SessionFactory
|
||||
public class UUIDBasedIdInterpretationTest {
|
||||
|
||||
@Test
|
||||
@JiraKey( "HHH-10564" )
|
||||
@RequiresDialect( H2Dialect.class )
|
||||
public void testH2(DomainModelScope scope) {
|
||||
checkUuidTypeUsed( scope, UUIDBinaryType.class );
|
||||
}
|
||||
|
||||
@Test
|
||||
@JiraKey( "HHH-10564" )
|
||||
@RequiresDialect( value = MySQLDialect.class, version = 500 )
|
||||
public void testMySQL(DomainModelScope scope) {
|
||||
checkUuidTypeUsed( scope, UUIDBinaryType.class );
|
||||
}
|
||||
|
||||
@Test
|
||||
@JiraKey( "HHH-10564" )
|
||||
@RequiresDialect( value = PostgreSQLDialect.class, version = 940 )
|
||||
public void testPostgreSQL(DomainModelScope scope) {
|
||||
checkUuidTypeUsed( scope, PostgresUUIDType.class );
|
||||
}
|
||||
|
||||
@Test
|
||||
@JiraKey( "HHH-10564" )
|
||||
@RequiresDialect(H2Dialect.class)
|
||||
public void testBinaryRuntimeUsage(SessionFactoryScope scope) {
|
||||
scope.inTransaction( session -> {
|
||||
session.byId( UuidIdEntity.class ).load( UUID.randomUUID() );
|
||||
} );
|
||||
}
|
||||
|
||||
private void checkUuidTypeUsed(DomainModelScope scope, Class<? extends Type> uuidTypeClass) {
|
||||
final PersistentClass entityBinding = scope.getDomainModel().getEntityBinding( UuidIdEntity.class.getName() );
|
||||
final Type idPropertyType = entityBinding.getIdentifier().getType();
|
||||
assertThat( idPropertyType, instanceOf( uuidTypeClass ) );
|
||||
}
|
||||
|
||||
@Entity(name = "UuidIdEntity")
|
||||
@Table(name = "UUID_ID_ENTITY")
|
||||
public static class UuidIdEntity {
|
||||
@Id
|
||||
@GeneratedValue
|
||||
private UUID id;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,112 @@
|
|||
/*
|
||||
* 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.orm.test.id.uuid.sqlrep.sqlbinary;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.GeneratedValue;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.ManyToOne;
|
||||
|
||||
import org.hibernate.annotations.Type;
|
||||
import org.hibernate.dialect.PostgreSQLDialect;
|
||||
import org.hibernate.metamodel.MappingMetamodel;
|
||||
import org.hibernate.metamodel.mapping.JdbcMapping;
|
||||
import org.hibernate.persister.entity.EntityPersister;
|
||||
|
||||
import org.hibernate.testing.orm.junit.DomainModel;
|
||||
import org.hibernate.testing.orm.junit.SessionFactory;
|
||||
import org.hibernate.testing.orm.junit.SessionFactoryScope;
|
||||
import org.hibernate.testing.orm.junit.SkipForDialect;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static org.hamcrest.CoreMatchers.is;
|
||||
import static org.hamcrest.CoreMatchers.notNullValue;
|
||||
import static org.hamcrest.MatcherAssert.assertThat;
|
||||
import static org.hamcrest.Matchers.hasSize;
|
||||
|
||||
/**
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
@DomainModel(annotatedClasses = { UUIDBinaryTest.Node.class })
|
||||
@SessionFactory
|
||||
@SkipForDialect(dialectClass = PostgreSQLDialect.class, reason = "Postgres has its own UUID type")
|
||||
public class UUIDBinaryTest {
|
||||
|
||||
private static class UUIDPair {
|
||||
UUID rootId;
|
||||
UUID childId;
|
||||
|
||||
public UUIDPair(UUID rootId, UUID childId) {
|
||||
this.rootId = rootId;
|
||||
this.childId = childId;
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUsage(SessionFactoryScope scope) {
|
||||
final MappingMetamodel domainModel = scope.getSessionFactory().getDomainModel();
|
||||
final EntityPersister entityDescriptor = domainModel.findEntityDescriptor( UUIDBinaryTest.Node.class );
|
||||
final List<JdbcMapping> identifierJdbcMappings = entityDescriptor.getIdentifierMapping().getJdbcMappings();
|
||||
assertThat( identifierJdbcMappings, hasSize( 1 ) );
|
||||
final JdbcMapping jdbcMapping = identifierJdbcMappings.get( 0 );
|
||||
assertThat( jdbcMapping.getJdbcTypeDescriptor().isBinary(), is( true ) );
|
||||
|
||||
final UUIDPair uuidPair = scope.fromTransaction( session -> {
|
||||
final Node root = new Node( "root" );
|
||||
session.save( root );
|
||||
assertThat( root.id, notNullValue());
|
||||
|
||||
final Node child = new Node( "child", root );
|
||||
session.save( child );
|
||||
assertThat( child.id, notNullValue() );
|
||||
|
||||
return new UUIDPair(root.id, child.id);
|
||||
} );
|
||||
|
||||
scope.inTransaction( session -> {
|
||||
final Node root = session.get( Node.class, uuidPair.rootId );
|
||||
assertThat( root, notNullValue() );
|
||||
final Node child = session.get( Node.class, uuidPair.childId );
|
||||
assertThat( child, notNullValue() );
|
||||
} );
|
||||
|
||||
scope.inTransaction( session -> {
|
||||
final Node node = session.createQuery( "from Node n join fetch n.parent where n.parent is not null", Node.class ).uniqueResult();
|
||||
assertThat( node, notNullValue() );
|
||||
assertThat( node.parent, notNullValue() );
|
||||
} );
|
||||
}
|
||||
|
||||
@Entity(name = "Node")
|
||||
static class Node {
|
||||
|
||||
@Id
|
||||
@GeneratedValue
|
||||
@Type(type = "uuid-binary")
|
||||
UUID id;
|
||||
|
||||
String name;
|
||||
|
||||
@ManyToOne
|
||||
Node parent;
|
||||
|
||||
Node() {
|
||||
}
|
||||
|
||||
Node(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
Node(String name, Node parent) {
|
||||
this.name = name;
|
||||
this.parent = parent;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,111 @@
|
|||
/*
|
||||
* 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.orm.test.id.uuid.sqlrep.sqlchar;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.GeneratedValue;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.ManyToOne;
|
||||
|
||||
import org.hibernate.annotations.Type;
|
||||
import org.hibernate.dialect.PostgreSQLDialect;
|
||||
import org.hibernate.metamodel.MappingMetamodel;
|
||||
import org.hibernate.metamodel.mapping.JdbcMapping;
|
||||
import org.hibernate.persister.entity.EntityPersister;
|
||||
|
||||
import org.hibernate.testing.orm.junit.DomainModel;
|
||||
import org.hibernate.testing.orm.junit.SessionFactory;
|
||||
import org.hibernate.testing.orm.junit.SessionFactoryScope;
|
||||
import org.hibernate.testing.orm.junit.SkipForDialect;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static org.hamcrest.CoreMatchers.is;
|
||||
import static org.hamcrest.CoreMatchers.notNullValue;
|
||||
import static org.hamcrest.MatcherAssert.assertThat;
|
||||
import static org.hamcrest.Matchers.hasSize;
|
||||
|
||||
/**
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
@DomainModel(annotatedClasses = { UUIDCharTest.Node.class })
|
||||
@SessionFactory
|
||||
@SkipForDialect(dialectClass = PostgreSQLDialect.class, reason = "Postgres has its own UUID type")
|
||||
public class UUIDCharTest {
|
||||
|
||||
private static class UUIDPair {
|
||||
UUID rootId;
|
||||
UUID childId;
|
||||
|
||||
public UUIDPair(UUID rootId, UUID childId) {
|
||||
this.rootId = rootId;
|
||||
this.childId = childId;
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUsage(SessionFactoryScope scope) {
|
||||
final MappingMetamodel domainModel = scope.getSessionFactory().getDomainModel();
|
||||
final EntityPersister entityDescriptor = domainModel.findEntityDescriptor( UUIDCharTest.Node.class );
|
||||
final List<JdbcMapping> identifierJdbcMappings = entityDescriptor.getIdentifierMapping().getJdbcMappings();
|
||||
assertThat( identifierJdbcMappings, hasSize( 1 ) );
|
||||
final JdbcMapping jdbcMapping = identifierJdbcMappings.get( 0 );
|
||||
assertThat( jdbcMapping.getJdbcTypeDescriptor().isString(), is( true ) );
|
||||
|
||||
final UUIDPair uuidPair = scope.fromTransaction( session -> {
|
||||
final Node root = new Node( "root" );
|
||||
session.save( root );
|
||||
assertThat( root.id, notNullValue());
|
||||
|
||||
final Node child = new Node( "child", root );
|
||||
session.save( child );
|
||||
assertThat( child.id, notNullValue() );
|
||||
|
||||
return new UUIDPair( root.id, child.id );
|
||||
} );
|
||||
|
||||
scope.inTransaction( session -> {
|
||||
final Node root = session.get( Node.class, uuidPair.rootId );
|
||||
assertThat( root, notNullValue() );
|
||||
final Node child = session.get( Node.class, uuidPair.childId );
|
||||
assertThat( child, notNullValue() );
|
||||
} );
|
||||
|
||||
scope.inTransaction( session -> {
|
||||
final Node node = session.createQuery( "from Node n join fetch n.parent where n.parent is not null", Node.class ).uniqueResult();
|
||||
assertThat( node, notNullValue() );
|
||||
assertThat( node.parent, notNullValue() );
|
||||
} );
|
||||
}
|
||||
|
||||
@Entity(name = "Node")
|
||||
static class Node {
|
||||
|
||||
@Id
|
||||
@GeneratedValue
|
||||
@Type(type = "uuid-char")
|
||||
UUID id;
|
||||
|
||||
String name;
|
||||
|
||||
@ManyToOne
|
||||
Node parent;
|
||||
|
||||
Node() {
|
||||
}
|
||||
|
||||
Node(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
Node(String name, Node parent) {
|
||||
this.name = name;
|
||||
this.parent = parent;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,67 @@
|
|||
/*
|
||||
* 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.orm.test.id.uuid.strategy;
|
||||
|
||||
import java.util.UUID;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.GeneratedValue;
|
||||
import javax.persistence.Id;
|
||||
|
||||
import org.hibernate.annotations.GenericGenerator;
|
||||
import org.hibernate.annotations.Parameter;
|
||||
|
||||
import org.hibernate.testing.orm.junit.DomainModel;
|
||||
import org.hibernate.testing.orm.junit.SessionFactory;
|
||||
import org.hibernate.testing.orm.junit.SessionFactoryScope;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static org.hamcrest.CoreMatchers.is;
|
||||
import static org.hamcrest.CoreMatchers.notNullValue;
|
||||
import static org.hamcrest.MatcherAssert.assertThat;
|
||||
|
||||
|
||||
/**
|
||||
* @author Steve Ebersole
|
||||
* @author Nathan Xu
|
||||
*/
|
||||
@DomainModel(
|
||||
annotatedClasses = CustomStrategyTest.Node.class
|
||||
)
|
||||
@SessionFactory
|
||||
public class CustomStrategyTest {
|
||||
|
||||
@Test
|
||||
public void testUsage(SessionFactoryScope scope) {
|
||||
scope.inTransaction( session -> {
|
||||
Node node = new Node();
|
||||
session.save( node );
|
||||
assertThat(node.id, notNullValue());
|
||||
assertThat(node.id.variant(), is(2));
|
||||
assertThat(node.id.version(), is(1));
|
||||
} );
|
||||
}
|
||||
|
||||
@Entity(name = "Node")
|
||||
static class Node {
|
||||
|
||||
@Id
|
||||
@GeneratedValue( generator = "custom-uuid" )
|
||||
@GenericGenerator(
|
||||
name = "custom-uuid",
|
||||
strategy = "org.hibernate.id.UUIDGenerator",
|
||||
parameters = {
|
||||
@Parameter(
|
||||
name = "uuid_gen_strategy_class",
|
||||
value = "org.hibernate.id.uuid.CustomVersionOneStrategy"
|
||||
)
|
||||
}
|
||||
)
|
||||
UUID id;
|
||||
|
||||
String name;
|
||||
}
|
||||
}
|
|
@ -4,7 +4,7 @@
|
|||
* 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.orm.test.id.uuid;
|
||||
package org.hibernate.orm.test.id.uuid.strategy;
|
||||
|
||||
import java.util.UUID;
|
||||
|
|
@ -1,122 +0,0 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
|
||||
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
|
||||
*/
|
||||
package org.hibernate.test.id.uuid;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.GeneratedValue;
|
||||
import javax.persistence.Id;
|
||||
|
||||
import org.hibernate.dialect.PostgreSQLDialect;
|
||||
import org.hibernate.jpa.test.BaseEntityManagerFunctionalTestCase;
|
||||
import org.hibernate.query.NativeQuery;
|
||||
import org.hibernate.type.PostgresUUIDType;
|
||||
import org.hibernate.type.UUIDBinaryType;
|
||||
|
||||
import org.hibernate.testing.RequiresDialect;
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.hibernate.testing.transaction.TransactionUtil.doInJPA;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
|
||||
/**
|
||||
* @author Vlad Mihalcea
|
||||
*/
|
||||
@RequiresDialect(PostgreSQLDialect.class)
|
||||
public class PostgreSQLUUIDGeneratedValueTest extends BaseEntityManagerFunctionalTestCase {
|
||||
|
||||
@Override
|
||||
protected Class<?>[] getAnnotatedClasses() {
|
||||
return new Class<?>[] {
|
||||
Book.class
|
||||
};
|
||||
}
|
||||
|
||||
private Book book;
|
||||
|
||||
@Override
|
||||
protected void afterEntityManagerFactoryBuilt() {
|
||||
book = new Book();
|
||||
|
||||
doInJPA( this::entityManagerFactory, entityManager -> {
|
||||
book.setTitle( "High-Performance Java Persistence" );
|
||||
book.setAuthor( "Vlad Mihalcea" );
|
||||
|
||||
entityManager.persist( book );
|
||||
} );
|
||||
|
||||
assertNotNull( book.getId() );
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testJPQL() {
|
||||
doInJPA( this::entityManagerFactory, entityManager -> {
|
||||
List<UUID> books = entityManager.createQuery(
|
||||
"select b.id " +
|
||||
"from Book b " +
|
||||
"where b.id = :id")
|
||||
.setParameter( "id", book.id )
|
||||
.getResultList();
|
||||
|
||||
assertEquals(1, books.size());
|
||||
} );
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNativeSQL() {
|
||||
doInJPA( this::entityManagerFactory, entityManager -> {
|
||||
List<UUID> books = entityManager.createNativeQuery(
|
||||
"select b.id as id " +
|
||||
"from Book b " +
|
||||
"where b.id = :id")
|
||||
.setParameter( "id", book.id )
|
||||
.unwrap( NativeQuery.class )
|
||||
.addScalar( "id", PostgresUUIDType.INSTANCE )
|
||||
.getResultList();
|
||||
|
||||
assertEquals(1, books.size());
|
||||
} );
|
||||
}
|
||||
|
||||
@Entity(name = "Book")
|
||||
public static class Book {
|
||||
|
||||
@Id
|
||||
@GeneratedValue
|
||||
private UUID id;
|
||||
|
||||
private String title;
|
||||
|
||||
private String author;
|
||||
|
||||
public UUID getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(UUID id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getTitle() {
|
||||
return title;
|
||||
}
|
||||
|
||||
public void setTitle(String title) {
|
||||
this.title = title;
|
||||
}
|
||||
|
||||
public String getAuthor() {
|
||||
return author;
|
||||
}
|
||||
|
||||
public void setAuthor(String author) {
|
||||
this.author = author;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,88 +0,0 @@
|
|||
package org.hibernate.test.id.uuid;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.ElementCollection;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.GeneratedValue;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.JoinTable;
|
||||
import javax.persistence.Table;
|
||||
|
||||
import org.hibernate.annotations.GenericGenerator;
|
||||
import org.hibernate.dialect.SQLServerDialect;
|
||||
import org.hibernate.jpa.test.BaseEntityManagerFunctionalTestCase;
|
||||
|
||||
import org.hibernate.testing.RequiresDialect;
|
||||
import org.hibernate.testing.TestForIssue;
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.hibernate.testing.transaction.TransactionUtil.doInJPA;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
/**
|
||||
* @author Vlad Mihalcea
|
||||
*/
|
||||
@RequiresDialect( SQLServerDialect.class )
|
||||
@TestForIssue( jiraKey = "HHH-12943" )
|
||||
public class UUID2GeneratorBinaryUniqueIdentifierIdTest extends BaseEntityManagerFunctionalTestCase {
|
||||
@Override
|
||||
protected Class<?>[] getAnnotatedClasses() {
|
||||
return new Class<?>[] { FooEntity.class };
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPaginationQuery() {
|
||||
byte[] id = doInJPA( this::entityManagerFactory, entityManager -> {
|
||||
FooEntity entity = new FooEntity();
|
||||
entity.getFooValues().add("one");
|
||||
entity.getFooValues().add("two");
|
||||
entity.getFooValues().add("three");
|
||||
|
||||
entityManager.persist(entity);
|
||||
|
||||
return entity.getId();
|
||||
} );
|
||||
|
||||
assertNotNull(id);
|
||||
|
||||
doInJPA( this::entityManagerFactory, entityManager -> {
|
||||
FooEntity entity = entityManager.find(FooEntity.class, id);
|
||||
assertNotNull(entity);
|
||||
|
||||
assertTrue(entity.getFooValues().size() == 3);
|
||||
} );
|
||||
}
|
||||
|
||||
@Entity
|
||||
@Table(name = "foo")
|
||||
public static class FooEntity {
|
||||
|
||||
@Id
|
||||
@GenericGenerator(name = "uuid", strategy = "uuid2")
|
||||
@GeneratedValue(generator = "uuid")
|
||||
@Column(columnDefinition = "UNIQUEIDENTIFIER")
|
||||
private byte[] id;
|
||||
|
||||
@ElementCollection
|
||||
@JoinTable(name = "foo_values")
|
||||
@Column(name = "foo_value")
|
||||
private final Set<String> fooValues = new HashSet<>();
|
||||
|
||||
public byte[] getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(byte[] id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public Set<String> getFooValues() {
|
||||
return fooValues;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
|
@ -1,88 +0,0 @@
|
|||
package org.hibernate.test.id.uuid;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.ElementCollection;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.GeneratedValue;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.JoinTable;
|
||||
import javax.persistence.Table;
|
||||
|
||||
import org.hibernate.annotations.GenericGenerator;
|
||||
import org.hibernate.dialect.SQLServerDialect;
|
||||
import org.hibernate.jpa.test.BaseEntityManagerFunctionalTestCase;
|
||||
|
||||
import org.hibernate.testing.RequiresDialect;
|
||||
import org.hibernate.testing.TestForIssue;
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.hibernate.testing.transaction.TransactionUtil.doInJPA;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
/**
|
||||
* @author Vlad Mihalcea
|
||||
*/
|
||||
@RequiresDialect( SQLServerDialect.class )
|
||||
@TestForIssue( jiraKey = "HHH-12943" )
|
||||
public class UUID2GeneratorUniqueIdentifierIdTest extends BaseEntityManagerFunctionalTestCase {
|
||||
@Override
|
||||
protected Class<?>[] getAnnotatedClasses() {
|
||||
return new Class<?>[] { FooEntity.class };
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPaginationQuery() {
|
||||
UUID id = doInJPA( this::entityManagerFactory, entityManager -> {
|
||||
FooEntity entity = new FooEntity();
|
||||
entity.getFooValues().add("one");
|
||||
entity.getFooValues().add("two");
|
||||
entity.getFooValues().add("three");
|
||||
|
||||
entityManager.persist(entity);
|
||||
|
||||
return entity.getId();
|
||||
} );
|
||||
|
||||
assertNotNull(id);
|
||||
|
||||
doInJPA( this::entityManagerFactory, entityManager -> {
|
||||
FooEntity entity = entityManager.find(FooEntity.class, id);
|
||||
assertNotNull(entity);
|
||||
|
||||
assertTrue(entity.getFooValues().size() == 3);
|
||||
} );
|
||||
}
|
||||
|
||||
@Entity
|
||||
@Table(name = "foo")
|
||||
public static class FooEntity {
|
||||
|
||||
@Id
|
||||
@GenericGenerator(name = "uuid", strategy = "uuid2")
|
||||
@GeneratedValue(generator = "uuid")
|
||||
@Column(columnDefinition = "UNIQUEIDENTIFIER")
|
||||
private UUID id;
|
||||
|
||||
@ElementCollection
|
||||
@JoinTable(name = "foo_values")
|
||||
@Column(name = "foo_value")
|
||||
private final Set<String> fooValues = new HashSet<>();
|
||||
|
||||
public UUID getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(UUID id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public Set<String> getFooValues() {
|
||||
return fooValues;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
|
@ -1,140 +0,0 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
|
||||
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
|
||||
*/
|
||||
package org.hibernate.test.id.uuid.interpretation;
|
||||
|
||||
import java.util.UUID;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.GeneratedValue;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.Table;
|
||||
|
||||
import org.hibernate.Session;
|
||||
import org.hibernate.SessionFactory;
|
||||
import org.hibernate.boot.Metadata;
|
||||
import org.hibernate.boot.MetadataSources;
|
||||
import org.hibernate.boot.registry.StandardServiceRegistry;
|
||||
import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
|
||||
import org.hibernate.cfg.AvailableSettings;
|
||||
import org.hibernate.dialect.Dialect;
|
||||
import org.hibernate.dialect.H2Dialect;
|
||||
import org.hibernate.dialect.MySQL5Dialect;
|
||||
import org.hibernate.dialect.PostgreSQL94Dialect;
|
||||
import org.hibernate.mapping.PersistentClass;
|
||||
import org.hibernate.tool.schema.Action;
|
||||
import org.hibernate.type.PostgresUUIDType;
|
||||
import org.hibernate.type.Type;
|
||||
import org.hibernate.type.UUIDBinaryType;
|
||||
|
||||
import org.hibernate.testing.RequiresDialect;
|
||||
import org.hibernate.testing.TestForIssue;
|
||||
import org.hibernate.testing.junit4.BaseUnitTestCase;
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.hamcrest.core.IsInstanceOf.instanceOf;
|
||||
import static org.junit.Assert.assertThat;
|
||||
|
||||
/**
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public class UUIDBasedIdInterpretationTest extends BaseUnitTestCase {
|
||||
|
||||
@Test
|
||||
@TestForIssue( jiraKey = "HHH-10564")
|
||||
public void testH2() {
|
||||
StandardServiceRegistry ssr = buildStandardServiceRegistry( H2Dialect.class );
|
||||
try {
|
||||
checkUuidTypeUsed( ssr, UUIDBinaryType.class );
|
||||
}
|
||||
finally {
|
||||
StandardServiceRegistryBuilder.destroy( ssr );
|
||||
}
|
||||
}
|
||||
|
||||
private StandardServiceRegistry buildStandardServiceRegistry(Class<? extends Dialect> dialectClass) {
|
||||
return buildStandardServiceRegistry( dialectClass, false );
|
||||
}
|
||||
|
||||
private StandardServiceRegistry buildStandardServiceRegistry(Class<? extends Dialect> dialectClass, boolean exportSchema) {
|
||||
final StandardServiceRegistryBuilder ssrb = new StandardServiceRegistryBuilder();
|
||||
ssrb.applySetting( AvailableSettings.DIALECT, dialectClass );
|
||||
if ( exportSchema ) {
|
||||
ssrb.applySetting( AvailableSettings.HBM2DDL_AUTO, Action.CREATE_DROP );
|
||||
}
|
||||
return ssrb.build();
|
||||
}
|
||||
|
||||
private void checkUuidTypeUsed(StandardServiceRegistry ssr, Class<? extends Type> uuidTypeClass) {
|
||||
final Metadata metadata = new MetadataSources( ssr )
|
||||
.addAnnotatedClass( UuidIdEntity.class )
|
||||
.buildMetadata();
|
||||
final PersistentClass entityBinding = metadata.getEntityBinding( UuidIdEntity.class.getName() );
|
||||
final Type idPropertyType = entityBinding.getIdentifier().getType();
|
||||
assertThat( idPropertyType, instanceOf( uuidTypeClass ) );
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestForIssue( jiraKey = "HHH-10564")
|
||||
public void testMySQL() {
|
||||
StandardServiceRegistry ssr = buildStandardServiceRegistry( MySQL5Dialect.class );
|
||||
try {
|
||||
checkUuidTypeUsed( ssr, UUIDBinaryType.class );
|
||||
}
|
||||
finally {
|
||||
StandardServiceRegistryBuilder.destroy( ssr );
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestForIssue( jiraKey = "HHH-10564")
|
||||
public void testPostgreSQL() {
|
||||
StandardServiceRegistry ssr = buildStandardServiceRegistry( PostgreSQL94Dialect.class );
|
||||
try {
|
||||
checkUuidTypeUsed( ssr, PostgresUUIDType.class );
|
||||
}
|
||||
finally {
|
||||
StandardServiceRegistryBuilder.destroy( ssr );
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestForIssue( jiraKey = "HHH-10564")
|
||||
@RequiresDialect(H2Dialect.class)
|
||||
public void testBinaryRuntimeUsage() {
|
||||
StandardServiceRegistry ssr = buildStandardServiceRegistry( H2Dialect.class, true );
|
||||
try {
|
||||
final Metadata metadata = new MetadataSources( ssr )
|
||||
.addAnnotatedClass( UuidIdEntity.class )
|
||||
.buildMetadata();
|
||||
final SessionFactory sf = metadata.buildSessionFactory();
|
||||
try {
|
||||
Session s = sf.openSession();
|
||||
try {
|
||||
s.beginTransaction();
|
||||
s.byId( UuidIdEntity.class ).load( UUID.randomUUID() );
|
||||
s.getTransaction().commit();
|
||||
}
|
||||
finally {
|
||||
s.close();
|
||||
}
|
||||
}
|
||||
finally {
|
||||
sf.close();
|
||||
}
|
||||
}
|
||||
finally {
|
||||
StandardServiceRegistryBuilder.destroy( ssr );
|
||||
}
|
||||
}
|
||||
|
||||
@Entity(name = "UuidIdEntity")
|
||||
@Table(name = "UUID_ID_ENTITY")
|
||||
public static class UuidIdEntity {
|
||||
@Id
|
||||
@GeneratedValue
|
||||
private UUID id;
|
||||
}
|
||||
}
|
|
@ -1,23 +0,0 @@
|
|||
<?xml version="1.0"?>
|
||||
<!--
|
||||
~ Hibernate, Relational Persistence for Idiomatic Java
|
||||
~
|
||||
~ License: GNU Lesser General Public License (LGPL), version 2.1 or later.
|
||||
~ See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
|
||||
-->
|
||||
<!DOCTYPE hibernate-mapping PUBLIC
|
||||
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
|
||||
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
|
||||
|
||||
<hibernate-mapping package="org.hibernate.test.id.uuid.sqlrep">
|
||||
|
||||
<class name="Node">
|
||||
|
||||
<id name="id" length="16">
|
||||
<generator class="uuid2"/>
|
||||
</id>
|
||||
<property name="name"/>
|
||||
<many-to-one name="parent"/>
|
||||
</class>
|
||||
|
||||
</hibernate-mapping>
|
|
@ -1,55 +0,0 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
|
||||
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
|
||||
*/
|
||||
package org.hibernate.test.id.uuid.sqlrep;
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* TODO : javadoc
|
||||
*
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public class Node {
|
||||
private UUID id;
|
||||
private String name;
|
||||
private Node parent;
|
||||
|
||||
public Node() {
|
||||
}
|
||||
|
||||
public Node(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public Node(String name, Node parent) {
|
||||
this.name = name;
|
||||
this.parent = parent;
|
||||
}
|
||||
|
||||
public UUID getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(UUID id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public Node getParent() {
|
||||
return parent;
|
||||
}
|
||||
|
||||
public void setParent(Node parent) {
|
||||
this.parent = parent;
|
||||
}
|
||||
}
|
|
@ -1,23 +0,0 @@
|
|||
<?xml version="1.0"?>
|
||||
<!--
|
||||
~ Hibernate, Relational Persistence for Idiomatic Java
|
||||
~
|
||||
~ License: GNU Lesser General Public License (LGPL), version 2.1 or later.
|
||||
~ See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
|
||||
-->
|
||||
<!DOCTYPE hibernate-mapping PUBLIC
|
||||
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
|
||||
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
|
||||
|
||||
<hibernate-mapping package="org.hibernate.test.id.uuid.sqlrep">
|
||||
|
||||
<class name="Node">
|
||||
|
||||
<id name="id" length="36">
|
||||
<generator class="uuid2"/>
|
||||
</id>
|
||||
<property name="name"/>
|
||||
<many-to-one name="parent"/>
|
||||
</class>
|
||||
|
||||
</hibernate-mapping>
|
|
@ -1,64 +0,0 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
|
||||
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
|
||||
*/
|
||||
package org.hibernate.test.id.uuid.sqlrep.sqlbinary;
|
||||
|
||||
import org.hibernate.Session;
|
||||
|
||||
import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase;
|
||||
import org.hibernate.test.id.uuid.sqlrep.Node;
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
|
||||
/**
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public class UUIDBinaryTest extends BaseCoreFunctionalTestCase {
|
||||
@Override
|
||||
public String[] getMappings() {
|
||||
return new String[] { "id/uuid/sqlrep/Node.hbm.xml" };
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUsage() {
|
||||
Session session = openSession();
|
||||
session.beginTransaction();
|
||||
Node root = new Node( "root" );
|
||||
session.save( root );
|
||||
assertNotNull( root.getId() );
|
||||
Node child = new Node( "child", root );
|
||||
session.save( child );
|
||||
assertNotNull( child.getId() );
|
||||
session.getTransaction().commit();
|
||||
session.close();
|
||||
|
||||
session = openSession();
|
||||
session.beginTransaction();
|
||||
Node node = (Node) session.get( Node.class, root.getId() );
|
||||
assertNotNull( node );
|
||||
node = (Node) session.get( Node.class, child.getId() );
|
||||
assertNotNull( node );
|
||||
session.getTransaction().commit();
|
||||
session.close();
|
||||
|
||||
session = openSession();
|
||||
session.beginTransaction();
|
||||
// test joining
|
||||
node = (Node) session.createQuery( "from Node n join fetch n.parent where n.parent is not null" ).uniqueResult();
|
||||
assertNotNull( node );
|
||||
assertNotNull( node.getParent() );
|
||||
session.getTransaction().commit();
|
||||
session.close();
|
||||
|
||||
session = openSession();
|
||||
session.beginTransaction();
|
||||
session.delete( child );
|
||||
session.delete( root );
|
||||
session.getTransaction().commit();
|
||||
session.close();
|
||||
}
|
||||
}
|
|
@ -1,34 +0,0 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
|
||||
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
|
||||
*/
|
||||
package org.hibernate.test.id.uuid.sqlrep.sqlchar;
|
||||
|
||||
import org.hibernate.cfg.Configuration;
|
||||
import org.hibernate.type.UUIDCharType;
|
||||
|
||||
import org.hibernate.test.id.uuid.sqlrep.sqlbinary.UUIDBinaryTest;
|
||||
|
||||
/**
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public class UUIDCharTest extends UUIDBinaryTest {
|
||||
@Override
|
||||
public void configure(Configuration cfg) {
|
||||
cfg.registerTypeOverride(
|
||||
new UUIDCharType() {
|
||||
@Override
|
||||
protected boolean registerUnderJavaType() {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] getMappings() {
|
||||
return new String[] { "id/uuid/sqlrep/Node2.hbm.xml" };
|
||||
}
|
||||
}
|
|
@ -1,42 +0,0 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
|
||||
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
|
||||
*/
|
||||
package org.hibernate.test.id.uuid.strategy;
|
||||
|
||||
import org.hibernate.Session;
|
||||
|
||||
import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase;
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
/**
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public class CustomStrategyTest extends BaseCoreFunctionalTestCase {
|
||||
public String[] getMappings() {
|
||||
return new String[] { "id/uuid/strategy/Node.hbm.xml" };
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUsage() {
|
||||
Session session = openSession();
|
||||
session.beginTransaction();
|
||||
Node node = new Node();
|
||||
session.save( node );
|
||||
assertNotNull( node.getId() );
|
||||
assertEquals( 2, node.getId().variant() );
|
||||
assertEquals( 1, node.getId().version() );
|
||||
session.getTransaction().commit();
|
||||
session.close();
|
||||
|
||||
session = openSession();
|
||||
session.beginTransaction();
|
||||
session.delete( node );
|
||||
session.getTransaction().commit();
|
||||
session.close();
|
||||
}
|
||||
}
|
|
@ -1,25 +0,0 @@
|
|||
<?xml version="1.0"?>
|
||||
<!--
|
||||
~ Hibernate, Relational Persistence for Idiomatic Java
|
||||
~
|
||||
~ License: GNU Lesser General Public License (LGPL), version 2.1 or later.
|
||||
~ See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
|
||||
-->
|
||||
<!DOCTYPE hibernate-mapping PUBLIC
|
||||
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
|
||||
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
|
||||
|
||||
<hibernate-mapping package="org.hibernate.test.id.uuid.strategy">
|
||||
|
||||
<class name="Node">
|
||||
|
||||
<id name="id" length="16">
|
||||
<generator class="uuid2">
|
||||
<!-- the "standard random" strategy gets tested in the other id.uuid tests -->
|
||||
<param name="uuid_gen_strategy_class">org.hibernate.id.uuid.CustomVersionOneStrategy</param>
|
||||
</generator>
|
||||
</id>
|
||||
<property name="name"/>
|
||||
</class>
|
||||
|
||||
</hibernate-mapping>
|
|
@ -1,41 +0,0 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
|
||||
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
|
||||
*/
|
||||
package org.hibernate.test.id.uuid.strategy;
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* TODO : javadoc
|
||||
*
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public class Node {
|
||||
private UUID id;
|
||||
private String name;
|
||||
|
||||
public Node() {
|
||||
}
|
||||
|
||||
public Node(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public UUID getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(UUID id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue