HHH-12357 - NamingHelper uses system default encoding
Fix issue by allowing an explicit charset to be used
This commit is contained in:
parent
1ae38f27a7
commit
a2a52c32e5
|
@ -622,6 +622,8 @@ public class MetadataBuilderImpl implements MetadataBuilderImplementor, TypeCont
|
||||||
|
|
||||||
private boolean autoQuoteKeywords;
|
private boolean autoQuoteKeywords;
|
||||||
|
|
||||||
|
private String schemaCharset;
|
||||||
|
|
||||||
// private PersistentAttributeMemberResolver persistentAttributeMemberResolver =
|
// private PersistentAttributeMemberResolver persistentAttributeMemberResolver =
|
||||||
// StandardPersistentAttributeMemberResolver.INSTANCE;
|
// StandardPersistentAttributeMemberResolver.INSTANCE;
|
||||||
|
|
||||||
|
@ -765,6 +767,12 @@ public class MetadataBuilderImpl implements MetadataBuilderImplementor, TypeCont
|
||||||
);
|
);
|
||||||
|
|
||||||
this.reflectionManager = generateDefaultReflectionManager();
|
this.reflectionManager = generateDefaultReflectionManager();
|
||||||
|
|
||||||
|
this.schemaCharset = configService.getSetting(
|
||||||
|
AvailableSettings.HBM2DDL_CHARSET_NAME,
|
||||||
|
String.class,
|
||||||
|
null
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
private ArrayList<MetadataSourceType> resolveInitialSourceProcessOrdering(ConfigurationService configService) {
|
private ArrayList<MetadataSourceType> resolveInitialSourceProcessOrdering(ConfigurationService configService) {
|
||||||
|
@ -949,6 +957,10 @@ public class MetadataBuilderImpl implements MetadataBuilderImplementor, TypeCont
|
||||||
: Collections.emptyList();
|
: Collections.emptyList();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String getSchemaCharset() {
|
||||||
|
return schemaCharset;
|
||||||
|
}
|
||||||
|
|
||||||
void addAttributeConverterInfo(AttributeConverterInfo info) {
|
void addAttributeConverterInfo(AttributeConverterInfo info) {
|
||||||
if ( this.attributeConverterInfoMap == null ) {
|
if ( this.attributeConverterInfoMap == null ) {
|
||||||
this.attributeConverterInfoMap = new HashMap<>();
|
this.attributeConverterInfoMap = new HashMap<>();
|
||||||
|
|
|
@ -199,8 +199,9 @@ public class ImplicitNamingStrategyJpaCompliantImpl implements ImplicitNamingStr
|
||||||
@Override
|
@Override
|
||||||
public Identifier determineForeignKeyName(ImplicitForeignKeyNameSource source) {
|
public Identifier determineForeignKeyName(ImplicitForeignKeyNameSource source) {
|
||||||
Identifier userProvidedIdentifier = source.getUserProvidedIdentifier();
|
Identifier userProvidedIdentifier = source.getUserProvidedIdentifier();
|
||||||
|
source.getBuildingContext().getBuildingOptions().getSchemaCharset();
|
||||||
return userProvidedIdentifier != null ? userProvidedIdentifier : toIdentifier(
|
return userProvidedIdentifier != null ? userProvidedIdentifier : toIdentifier(
|
||||||
NamingHelper.INSTANCE.generateHashedFkName(
|
NamingHelper.withCharset( source.getBuildingContext().getBuildingOptions().getSchemaCharset() ).generateHashedFkName(
|
||||||
"FK",
|
"FK",
|
||||||
source.getTableName(),
|
source.getTableName(),
|
||||||
source.getReferencedTableName(),
|
source.getReferencedTableName(),
|
||||||
|
@ -214,7 +215,7 @@ public class ImplicitNamingStrategyJpaCompliantImpl implements ImplicitNamingStr
|
||||||
public Identifier determineUniqueKeyName(ImplicitUniqueKeyNameSource source) {
|
public Identifier determineUniqueKeyName(ImplicitUniqueKeyNameSource source) {
|
||||||
Identifier userProvidedIdentifier = source.getUserProvidedIdentifier();
|
Identifier userProvidedIdentifier = source.getUserProvidedIdentifier();
|
||||||
return userProvidedIdentifier != null ? userProvidedIdentifier : toIdentifier(
|
return userProvidedIdentifier != null ? userProvidedIdentifier : toIdentifier(
|
||||||
NamingHelper.INSTANCE.generateHashedConstraintName(
|
NamingHelper.withCharset( source.getBuildingContext().getBuildingOptions().getSchemaCharset() ).generateHashedConstraintName(
|
||||||
"UK",
|
"UK",
|
||||||
source.getTableName(),
|
source.getTableName(),
|
||||||
source.getColumnNames()
|
source.getColumnNames()
|
||||||
|
@ -227,7 +228,7 @@ public class ImplicitNamingStrategyJpaCompliantImpl implements ImplicitNamingStr
|
||||||
public Identifier determineIndexName(ImplicitIndexNameSource source) {
|
public Identifier determineIndexName(ImplicitIndexNameSource source) {
|
||||||
Identifier userProvidedIdentifier = source.getUserProvidedIdentifier();
|
Identifier userProvidedIdentifier = source.getUserProvidedIdentifier();
|
||||||
return userProvidedIdentifier != null ? userProvidedIdentifier : toIdentifier(
|
return userProvidedIdentifier != null ? userProvidedIdentifier : toIdentifier(
|
||||||
NamingHelper.INSTANCE.generateHashedConstraintName(
|
NamingHelper.withCharset( source.getBuildingContext().getBuildingOptions().getSchemaCharset() ).generateHashedConstraintName(
|
||||||
"IDX",
|
"IDX",
|
||||||
source.getTableName(),
|
source.getTableName(),
|
||||||
source.getColumnNames()
|
source.getColumnNames()
|
||||||
|
|
|
@ -6,7 +6,9 @@
|
||||||
*/
|
*/
|
||||||
package org.hibernate.boot.model.naming;
|
package org.hibernate.boot.model.naming;
|
||||||
|
|
||||||
|
import java.io.UnsupportedEncodingException;
|
||||||
import java.math.BigInteger;
|
import java.math.BigInteger;
|
||||||
|
import java.nio.charset.Charset;
|
||||||
import java.security.MessageDigest;
|
import java.security.MessageDigest;
|
||||||
import java.security.NoSuchAlgorithmException;
|
import java.security.NoSuchAlgorithmException;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
@ -24,6 +26,20 @@ public class NamingHelper {
|
||||||
*/
|
*/
|
||||||
public static final NamingHelper INSTANCE = new NamingHelper();
|
public static final NamingHelper INSTANCE = new NamingHelper();
|
||||||
|
|
||||||
|
public static NamingHelper withCharset(String charset) {
|
||||||
|
return new NamingHelper(charset);
|
||||||
|
}
|
||||||
|
|
||||||
|
private final String charset;
|
||||||
|
|
||||||
|
public NamingHelper() {
|
||||||
|
this(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
private NamingHelper(String charset) {
|
||||||
|
this.charset = charset;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* If a foreign-key is not explicitly named, this is called to generate
|
* If a foreign-key is not explicitly named, this is called to generate
|
||||||
* a unique hash using the table and column names.
|
* a unique hash using the table and column names.
|
||||||
|
@ -146,7 +162,7 @@ public class NamingHelper {
|
||||||
try {
|
try {
|
||||||
MessageDigest md = MessageDigest.getInstance( "MD5" );
|
MessageDigest md = MessageDigest.getInstance( "MD5" );
|
||||||
md.reset();
|
md.reset();
|
||||||
md.update( s.getBytes() );
|
md.update( charset != null ? s.getBytes( charset ) : s.getBytes() );
|
||||||
byte[] digest = md.digest();
|
byte[] digest = md.digest();
|
||||||
BigInteger bigInt = new BigInteger( 1, digest );
|
BigInteger bigInt = new BigInteger( 1, digest );
|
||||||
// By converting to base 35 (full alphanumeric), we guarantee
|
// By converting to base 35 (full alphanumeric), we guarantee
|
||||||
|
@ -154,7 +170,7 @@ public class NamingHelper {
|
||||||
// character identifier restriction enforced by a few dialects.
|
// character identifier restriction enforced by a few dialects.
|
||||||
return bigInt.toString( 35 );
|
return bigInt.toString( 35 );
|
||||||
}
|
}
|
||||||
catch ( NoSuchAlgorithmException e ) {
|
catch ( NoSuchAlgorithmException|UnsupportedEncodingException e ) {
|
||||||
throw new HibernateException( "Unable to generate a hashed name!", e );
|
throw new HibernateException( "Unable to generate a hashed name!", e );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -224,6 +224,10 @@ public interface MetadataBuildingOptions {
|
||||||
|
|
||||||
List<AttributeConverterInfo> getAttributeConverters();
|
List<AttributeConverterInfo> getAttributeConverters();
|
||||||
|
|
||||||
|
default String getSchemaCharset() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
// /**
|
// /**
|
||||||
// * Obtain the selected strategy for resolving members identifying persistent attributes
|
// * Obtain the selected strategy for resolving members identifying persistent attributes
|
||||||
// *
|
// *
|
||||||
|
|
|
@ -43,6 +43,26 @@ public class NamingHelperTest extends BaseUnitTestCase {
|
||||||
assertEquals( "FKdgopp1hqnm8c1o6sfbb3tbeh", fkNameUtf8 );
|
assertEquals( "FKdgopp1hqnm8c1o6sfbb3tbeh", fkNameUtf8 );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestForIssue(jiraKey = "HHH-12357")
|
||||||
|
public void generateHashedFkNameUSingUtf8() {
|
||||||
|
Identifier booksDe = new Identifier( "Bücher", false );
|
||||||
|
Identifier authorsDe = new Identifier( "Autoren", false );
|
||||||
|
Identifier authorId = new Identifier( "autor_id", false );
|
||||||
|
|
||||||
|
defaultCharset.set( StandardCharsets.ISO_8859_1 );
|
||||||
|
|
||||||
|
String fkNameLatin1 = NamingHelper.withCharset( "UTF8" ).generateHashedFkName( "FK", booksDe, authorsDe, authorId );
|
||||||
|
|
||||||
|
assertEquals( "FKdgopp1hqnm8c1o6sfbb3tbeh", fkNameLatin1 );
|
||||||
|
|
||||||
|
defaultCharset.set( StandardCharsets.UTF_8 );
|
||||||
|
|
||||||
|
String fkNameUtf8 = NamingHelper.withCharset( "UTF8" ).generateHashedFkName( "FK", booksDe, authorsDe, authorId );
|
||||||
|
|
||||||
|
assertEquals( "FKdgopp1hqnm8c1o6sfbb3tbeh", fkNameUtf8 );
|
||||||
|
}
|
||||||
|
|
||||||
public static class DefaultCharset extends ExternalResource {
|
public static class DefaultCharset extends ExternalResource {
|
||||||
|
|
||||||
private Charset prev;
|
private Charset prev;
|
||||||
|
|
|
@ -0,0 +1,120 @@
|
||||||
|
/*
|
||||||
|
* 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>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
// $Id$
|
||||||
|
package org.hibernate.test.annotations.namingstrategy.charset;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
import javax.persistence.Entity;
|
||||||
|
import javax.persistence.Id;
|
||||||
|
import javax.persistence.Index;
|
||||||
|
import javax.persistence.ManyToOne;
|
||||||
|
import javax.persistence.Table;
|
||||||
|
import javax.persistence.UniqueConstraint;
|
||||||
|
|
||||||
|
import org.hibernate.boot.Metadata;
|
||||||
|
import org.hibernate.boot.MetadataSources;
|
||||||
|
import org.hibernate.cfg.AvailableSettings;
|
||||||
|
import org.hibernate.cfg.Environment;
|
||||||
|
import org.hibernate.mapping.UniqueKey;
|
||||||
|
import org.hibernate.service.ServiceRegistry;
|
||||||
|
|
||||||
|
import org.hibernate.testing.ServiceRegistryBuilder;
|
||||||
|
import org.hibernate.testing.TestForIssue;
|
||||||
|
import org.hibernate.testing.junit4.BaseUnitTestCase;
|
||||||
|
import org.hibernate.test.annotations.namingstrategy.LongIdentifierNamingStrategy;
|
||||||
|
import org.junit.After;
|
||||||
|
import org.junit.Before;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import static org.junit.Assert.assertEquals;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Vlad Mihalcea
|
||||||
|
*/
|
||||||
|
@TestForIssue( jiraKey = "HHH-12357" )
|
||||||
|
public abstract class AbstractCharsetNamingStrategyTest extends BaseUnitTestCase {
|
||||||
|
|
||||||
|
private ServiceRegistry serviceRegistry;
|
||||||
|
|
||||||
|
@Before
|
||||||
|
public void setUp() {
|
||||||
|
Map properties = new HashMap( Environment.getProperties() );
|
||||||
|
properties.put( AvailableSettings.HBM2DDL_CHARSET_NAME, charsetName() );
|
||||||
|
serviceRegistry = ServiceRegistryBuilder.buildServiceRegistry( properties );
|
||||||
|
}
|
||||||
|
|
||||||
|
protected abstract String charsetName();
|
||||||
|
|
||||||
|
@After
|
||||||
|
public void tearDown() {
|
||||||
|
if ( serviceRegistry != null ) {
|
||||||
|
ServiceRegistryBuilder.destroy( serviceRegistry );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@Test
|
||||||
|
public void testWithCustomNamingStrategy() throws Exception {
|
||||||
|
Metadata metadata = new MetadataSources( serviceRegistry )
|
||||||
|
.addAnnotatedClass(Address.class)
|
||||||
|
.addAnnotatedClass(Person.class)
|
||||||
|
.getMetadataBuilder()
|
||||||
|
.applyImplicitNamingStrategy( new LongIdentifierNamingStrategy() )
|
||||||
|
.build();
|
||||||
|
|
||||||
|
UniqueKey uniqueKey = metadata.getEntityBinding( Address.class.getName()).getTable().getUniqueKeyIterator().next();
|
||||||
|
assertEquals( expectedUniqueKeyName(), uniqueKey.getName() );
|
||||||
|
|
||||||
|
org.hibernate.mapping.ForeignKey foreignKey =
|
||||||
|
(org.hibernate.mapping.ForeignKey) metadata.getEntityBinding( Address.class.getName()).getTable().getForeignKeyIterator().next();
|
||||||
|
assertEquals( expectedForeignKeyName(), foreignKey.getName() );
|
||||||
|
|
||||||
|
org.hibernate.mapping.Index index = metadata.getEntityBinding( Address.class.getName()).getTable().getIndexIterator().next();
|
||||||
|
assertEquals( expectedIndexName(), index.getName() );
|
||||||
|
}
|
||||||
|
|
||||||
|
protected abstract String expectedUniqueKeyName();
|
||||||
|
|
||||||
|
protected abstract String expectedForeignKeyName();
|
||||||
|
|
||||||
|
protected abstract String expectedIndexName();
|
||||||
|
|
||||||
|
@Entity(name = "Address")
|
||||||
|
@Table(uniqueConstraints = @UniqueConstraint(
|
||||||
|
columnNames = {
|
||||||
|
"city", "stradă"
|
||||||
|
}),
|
||||||
|
indexes = @Index( columnList = "city, stradă")
|
||||||
|
)
|
||||||
|
public class Address {
|
||||||
|
|
||||||
|
@Id
|
||||||
|
private Long id;
|
||||||
|
|
||||||
|
private String city;
|
||||||
|
|
||||||
|
private String stradă;
|
||||||
|
|
||||||
|
@ManyToOne
|
||||||
|
private Person personă;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Entity(name = "Person")
|
||||||
|
public class Person {
|
||||||
|
|
||||||
|
@Id
|
||||||
|
private long id;
|
||||||
|
|
||||||
|
public long getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setId(long id) {
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,35 @@
|
||||||
|
/*
|
||||||
|
* 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>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
// $Id$
|
||||||
|
package org.hibernate.test.annotations.namingstrategy.charset;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Vlad Mihalcea
|
||||||
|
*/
|
||||||
|
public class Iso88591CharsetNamingStrategyTest extends AbstractCharsetNamingStrategyTest {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected String charsetName() {
|
||||||
|
return "ISO-8859-1";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected String expectedUniqueKeyName() {
|
||||||
|
return "UKq2jxex2hrvg4139p85npyj71g";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected String expectedForeignKeyName() {
|
||||||
|
return "FKdeqq4y6cesc2yfgi97u2hp61g";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected String expectedIndexName() {
|
||||||
|
return "IDXq2jxex2hrvg4139p85npyj71g";
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,37 @@
|
||||||
|
/*
|
||||||
|
* 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>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
// $Id$
|
||||||
|
package org.hibernate.test.annotations.namingstrategy.charset;
|
||||||
|
|
||||||
|
import org.hibernate.testing.TestForIssue;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Vlad Mihalcea
|
||||||
|
*/
|
||||||
|
public class Utf8CharsetNamingStrategyTest extends AbstractCharsetNamingStrategyTest {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected String charsetName() {
|
||||||
|
return "UTF8";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected String expectedUniqueKeyName() {
|
||||||
|
return "UKpm66tdjkgtsca5x2uwux487t5";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected String expectedForeignKeyName() {
|
||||||
|
return "FKgvrnki5fwp3qo0hfp1bu1jj0q";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected String expectedIndexName() {
|
||||||
|
return "IDXpm66tdjkgtsca5x2uwux487t5";
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue