HHH-16829 add @Collate annotation
This commit is contained in:
parent
f32f6b5515
commit
ae1215ca35
|
@ -0,0 +1,36 @@
|
|||
/*
|
||||
* 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.annotations;
|
||||
|
||||
import org.hibernate.Incubating;
|
||||
import org.hibernate.binder.internal.CollateBinder;
|
||||
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
import static java.lang.annotation.ElementType.FIELD;
|
||||
import static java.lang.annotation.ElementType.METHOD;
|
||||
import static java.lang.annotation.RetentionPolicy.RUNTIME;
|
||||
|
||||
/**
|
||||
* Specifies a collation to use when generating DDL for
|
||||
* the column mapped by the annotated field or property.
|
||||
*
|
||||
* @author Gavin King
|
||||
*
|
||||
* @since 6.3
|
||||
*/
|
||||
@Incubating
|
||||
@AttributeBinderType(binder = CollateBinder.class)
|
||||
@Target({METHOD, FIELD})
|
||||
@Retention(RUNTIME)
|
||||
public @interface Collate {
|
||||
/**
|
||||
* The name of the collation.
|
||||
*/
|
||||
String value();
|
||||
}
|
|
@ -0,0 +1,44 @@
|
|||
/*
|
||||
* 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.binder.internal;
|
||||
|
||||
import org.hibernate.AnnotationException;
|
||||
import org.hibernate.annotations.Collate;
|
||||
import org.hibernate.binder.AttributeBinder;
|
||||
import org.hibernate.boot.spi.MetadataBuildingContext;
|
||||
import org.hibernate.mapping.Collection;
|
||||
import org.hibernate.mapping.Column;
|
||||
import org.hibernate.mapping.OneToMany;
|
||||
import org.hibernate.mapping.PersistentClass;
|
||||
import org.hibernate.mapping.Property;
|
||||
import org.hibernate.mapping.Value;
|
||||
|
||||
/**
|
||||
* Handles {@link Collate} annotations.
|
||||
*
|
||||
* @author Gavin King
|
||||
*/
|
||||
public class CollateBinder implements AttributeBinder<Collate> {
|
||||
@Override
|
||||
public void bind(Collate collate, MetadataBuildingContext context, PersistentClass entity, Property property) {
|
||||
Value value = property.getValue();
|
||||
if ( value instanceof OneToMany ) {
|
||||
throw new AnnotationException( "One to many association '" + property.getName()
|
||||
+ "' was annotated '@Collate'");
|
||||
}
|
||||
else if ( value instanceof Collection ) {
|
||||
throw new AnnotationException( "Collection '" + property.getName()
|
||||
+ "' was annotated '@Collate'");
|
||||
|
||||
}
|
||||
else {
|
||||
for ( Column column : value.getColumns() ) {
|
||||
column.setCollation( collate.value() );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -3413,6 +3413,13 @@ public abstract class Dialect implements ConversionContext, TypeContributor, Fun
|
|||
return getNullColumnString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Quote the given collation name if necessary.
|
||||
*/
|
||||
public String quoteCollation(String collation) {
|
||||
return collation;
|
||||
}
|
||||
|
||||
/**
|
||||
* Does this dialect support commenting on tables and columns?
|
||||
*
|
||||
|
|
|
@ -660,4 +660,9 @@ public class HSQLDialect extends Dialect {
|
|||
public UniqueDelegate getUniqueDelegate() {
|
||||
return uniqueDelegate;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String quoteCollation(String collation) {
|
||||
return '\"' + collation + '\"';
|
||||
}
|
||||
}
|
||||
|
|
|
@ -861,6 +861,11 @@ public class PostgreSQLDialect extends Dialect {
|
|||
return "null::" + typeConfiguration.getDdlTypeRegistry().getDescriptor( sqlType ).getRawTypeName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String quoteCollation(String collation) {
|
||||
return '\"' + collation + '\"';
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supportsCommentOn() {
|
||||
return true;
|
||||
|
|
|
@ -36,6 +36,7 @@ public class AggregateColumn extends Column {
|
|||
addCheckConstraint( constraint );
|
||||
}
|
||||
setComment( column.getComment() );
|
||||
setCollation( column.getCollation() );
|
||||
setDefaultValue( column.getDefaultValue() );
|
||||
setGeneratedAs( column.getGeneratedAs() );
|
||||
setAssignmentExpression( column.getAssignmentExpression() );
|
||||
|
|
|
@ -65,7 +65,7 @@ public class Column implements Selectable, Serializable, Cloneable, ColumnTypeIn
|
|||
private String customWrite;
|
||||
private String customRead;
|
||||
private Size columnSize;
|
||||
// private String specializedTypeDeclaration;
|
||||
private String collation;
|
||||
private java.util.List<CheckConstraint> checkConstraints = new ArrayList<>();
|
||||
|
||||
public Column() {
|
||||
|
@ -614,6 +614,14 @@ public class Column implements Selectable, Serializable, Cloneable, ColumnTypeIn
|
|||
this.comment = comment;
|
||||
}
|
||||
|
||||
public String getCollation() {
|
||||
return collation;
|
||||
}
|
||||
|
||||
public void setCollation(String collation) {
|
||||
this.collation = collation;
|
||||
}
|
||||
|
||||
public String getDefaultValue() {
|
||||
return defaultValue;
|
||||
}
|
||||
|
|
|
@ -183,6 +183,11 @@ class ColumnDefinitions {
|
|||
definition.append( ' ' ).append( columnType );
|
||||
}
|
||||
|
||||
String collation = column.getCollation();
|
||||
if ( collation != null ) {
|
||||
definition.append(" collate ").append( dialect.quoteCollation( collation ) );
|
||||
}
|
||||
|
||||
final String defaultValue = column.getDefaultValue();
|
||||
if ( defaultValue != null ) {
|
||||
definition.append( " default " ).append( defaultValue );
|
||||
|
@ -205,7 +210,7 @@ class ColumnDefinitions {
|
|||
private static boolean isIdentityColumn(Column column, Table table, Metadata metadata, Dialect dialect) {
|
||||
// Try to find out the name of the primary key in case the dialect needs it to create an identity
|
||||
return isPrimaryKeyIdentity( table, metadata, dialect )
|
||||
&& column.getQuotedName( dialect ).equals( getPrimaryKeyColumnName( table, dialect ) );
|
||||
&& column.getQuotedName( dialect ).equals( getPrimaryKeyColumnName( table, dialect ) );
|
||||
}
|
||||
|
||||
private static String getPrimaryKeyColumnName(Table table, Dialect dialect) {
|
||||
|
@ -221,13 +226,13 @@ class ColumnDefinitions {
|
|||
// && table.getPrimaryKey().getColumn( 0 ).isIdentity();
|
||||
MetadataImplementor metadataImplementor = (MetadataImplementor) metadata;
|
||||
return table.hasPrimaryKey()
|
||||
&& table.getIdentifierValue() != null
|
||||
&& table.getIdentifierValue()
|
||||
.isIdentityColumn(
|
||||
metadataImplementor.getMetadataBuildingOptions()
|
||||
.getIdentifierGeneratorFactory(),
|
||||
dialect
|
||||
);
|
||||
&& table.getIdentifierValue() != null
|
||||
&& table.getIdentifierValue()
|
||||
.isIdentityColumn(
|
||||
metadataImplementor.getMetadataBuildingOptions()
|
||||
.getIdentifierGeneratorFactory(),
|
||||
dialect
|
||||
);
|
||||
}
|
||||
|
||||
private static String stripArgs(String string) {
|
||||
|
|
|
@ -0,0 +1,38 @@
|
|||
package org.hibernate.orm.test.annotations.collate;
|
||||
|
||||
import jakarta.persistence.Basic;
|
||||
import jakarta.persistence.Column;
|
||||
import jakarta.persistence.Entity;
|
||||
import jakarta.persistence.GeneratedValue;
|
||||
import jakarta.persistence.Id;
|
||||
import org.hibernate.annotations.Collate;
|
||||
import org.hibernate.dialect.MySQLDialect;
|
||||
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.Test;
|
||||
|
||||
@SessionFactory
|
||||
@DomainModel(annotatedClasses = MySQLCollateTest.Message.class)
|
||||
@RequiresDialect(MySQLDialect.class)
|
||||
public class MySQLCollateTest {
|
||||
|
||||
@Test void test(SessionFactoryScope scope) {
|
||||
scope.inTransaction(session -> session.persist(new Message("Hello, world!")));
|
||||
}
|
||||
|
||||
@Entity(name = "msgs")
|
||||
static class Message {
|
||||
@Id @GeneratedValue
|
||||
Long id;
|
||||
@Basic(optional = false)
|
||||
@Collate("utf8mb4_spanish2_ci")
|
||||
@Column(length = 200)
|
||||
String text;
|
||||
|
||||
public Message(String text) {
|
||||
this.text = text;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,38 @@
|
|||
package org.hibernate.orm.test.annotations.collate;
|
||||
|
||||
import jakarta.persistence.Basic;
|
||||
import jakarta.persistence.Column;
|
||||
import jakarta.persistence.Entity;
|
||||
import jakarta.persistence.GeneratedValue;
|
||||
import jakarta.persistence.Id;
|
||||
import org.hibernate.annotations.Collate;
|
||||
import org.hibernate.dialect.PostgreSQLDialect;
|
||||
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.Test;
|
||||
|
||||
@SessionFactory
|
||||
@DomainModel(annotatedClasses = PostgresCollateTest.Message.class)
|
||||
@RequiresDialect(PostgreSQLDialect.class)
|
||||
public class PostgresCollateTest {
|
||||
|
||||
@Test void test(SessionFactoryScope scope) {
|
||||
scope.inTransaction(session -> session.persist(new Message("Hello, world!")));
|
||||
}
|
||||
|
||||
@Entity(name = "msgs")
|
||||
static class Message {
|
||||
@Id @GeneratedValue
|
||||
Long id;
|
||||
@Basic(optional = false)
|
||||
@Collate("es_ES")
|
||||
@Column(length = 200)
|
||||
String text;
|
||||
|
||||
public Message(String text) {
|
||||
this.text = text;
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue