Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ public static <T> BasicValue.Resolution<T> from(
final var typeConfiguration = bootstrapContext.getTypeConfiguration();
final var basicTypeRegistry = typeConfiguration.getBasicTypeRegistry();

final var reflectedJtd = reflectedJtdResolver.get();
final JavaType<T> reflectedJtd;

// NOTE: the distinction that is made below wrt `explicitJavaType` and `reflectedJtd`
// is needed temporarily to trigger "legacy resolution" versus "ORM6 resolution.
Expand Down Expand Up @@ -110,7 +110,7 @@ else if ( explicitJdbcType != null ) {
}
}
}
else if ( reflectedJtd != null ) {
else if ( ( reflectedJtd = reflectedJtdResolver.get() ) != null ) {
// we were able to determine the "reflected java-type"
// Use JTD if we know it to apply any specialized resolutions
if ( reflectedJtd instanceof EnumJavaType enumJavaType ) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,16 +25,16 @@ default <X> BasicType<X> resolveIndicatedType(JdbcTypeIndicators indicators, Jav
indicators,
domainJtd
);
if ( resolvedJdbcType != jdbcType ) {
if ( getJavaTypeDescriptor() != domainJtd || resolvedJdbcType != jdbcType ) {
return indicators.getTypeConfiguration().getBasicTypeRegistry()
.resolve( domainJtd, resolvedJdbcType, getName() );
.resolve( domainJtd, resolvedJdbcType );
}
}
else {
final int resolvedJdbcTypeCode = indicators.resolveJdbcTypeCode( jdbcType.getDefaultSqlTypeCode() );
if ( resolvedJdbcTypeCode != jdbcType.getDefaultSqlTypeCode() ) {
if ( getJavaTypeDescriptor() != domainJtd || resolvedJdbcTypeCode != jdbcType.getDefaultSqlTypeCode() ) {
return indicators.getTypeConfiguration().getBasicTypeRegistry()
.resolve( domainJtd, indicators.getJdbcType( resolvedJdbcTypeCode ), getName() );
.resolve( domainJtd, indicators.getJdbcType( resolvedJdbcTypeCode ) );
}
}
return (BasicType<X>) this;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
package org.hibernate.type;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.Supplier;
Expand Down Expand Up @@ -49,6 +51,7 @@ public class BasicTypeRegistry implements Serializable {

private final Map<String, BasicType<?>> typesByName = new ConcurrentHashMap<>();
private final Map<String, BasicTypeReference<?>> typeReferencesByName = new ConcurrentHashMap<>();
private final Map<String, List<BasicTypeReference<?>>> typeReferencesByJavaTypeName = new ConcurrentHashMap<>();

public BasicTypeRegistry(TypeConfiguration typeConfiguration){
this.typeConfiguration = typeConfiguration;
Expand Down Expand Up @@ -256,11 +259,25 @@ private <J> BasicType<J> createIfUnregistered(
if ( registeredTypeMatches( javaType, jdbcType, registeredType ) ) {
return castNonNull( registeredType );
}
else {
final var createdType = creator.get();
register( javaType, jdbcType, createdType );
return createdType;
// Create an ad-hoc type since the java type doesn't come from the registry and is probably explicitly defined
else if ( typeConfiguration.getJavaTypeRegistry().resolveDescriptor( javaType.getJavaType() ) == javaType ) {
final var basicTypeReferences = typeReferencesByJavaTypeName.get( javaType.getTypeName() );
if ( basicTypeReferences != null && !basicTypeReferences.isEmpty() ) {
final var jdbcTypeRegistry = typeConfiguration.getJdbcTypeRegistry();
for ( var typeReference : basicTypeReferences ) {
if ( jdbcTypeRegistry.getDescriptor( typeReference.getSqlTypeCode() ) == jdbcType ) {
final var basicType = typesByName.get( typeReference.getName() );
//noinspection unchecked
return basicType != null
? (BasicType<J>) basicType
: (BasicType<J>) createBasicType( typeReference.getName(), typeReference );
}
}
}
}
final var createdType = creator.get();
register( javaType, jdbcType, createdType );
return createdType;
}

private static <J> boolean registeredTypeMatches(JavaType<J> javaType, JdbcType jdbcType, BasicType<J> registeredType) {
Expand Down Expand Up @@ -334,7 +351,7 @@ public void addTypeReferenceRegistrationKey(String typeReferenceKey, String... a
throw new IllegalArgumentException( "Couldn't find type reference with name: " + typeReferenceKey );
}
for ( String additionalTypeReferenceKey : additionalTypeReferenceKeys ) {
typeReferencesByName.put( additionalTypeReferenceKey, basicTypeReference );
addTypeReference( additionalTypeReferenceKey, basicTypeReference );
}
}

Expand Down Expand Up @@ -384,7 +401,7 @@ public void addPrimeEntry(BasicTypeReference<?> type, String legacyTypeClassName

// Legacy name registration
if ( isNotEmpty( legacyTypeClassName ) ) {
typeReferencesByName.put( legacyTypeClassName, type );
addTypeReference( legacyTypeClassName, type );
}

// explicit registration keys
Expand Down Expand Up @@ -429,19 +446,31 @@ private void applyRegistrationKeys(BasicTypeReference<?> type, String[] keys) {
// Incidentally, this might also help with map lookup efficiency.
key = key.intern();

// Incredibly verbose logging disabled
// LOG.tracef( "Adding type registration %s -> %s", key, type );
addTypeReference( key, type );
}
}
}

private void addTypeReference(String name, BasicTypeReference<?> typeReference) {
// Incredibly verbose logging disabled
// LOG.tracef( "Adding type registration %s -> %s", key, type );

// final BasicTypeReference<?> old =
typeReferencesByName.put( key, type );
// if ( old != null && old != type ) {
// LOG.tracef(
// "Type registration key [%s] overrode previous entry : `%s`",
// key,
// old
// );
// }
}
typeReferencesByName.put( name, typeReference );
// if ( old != null && old != type ) {
// LOG.tracef(
// "Type registration key [%s] overrode previous entry : `%s`",
// key,
// old
// );
// }

final var basicTypeReferences = typeReferencesByJavaTypeName.computeIfAbsent(
typeReference.getJavaType().getTypeName(),
s -> new ArrayList<>()
);
if ( !basicTypeReferences.contains( typeReference ) ) {
basicTypeReferences.add( typeReference );
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
/*
* SPDX-License-Identifier: Apache-2.0
* Copyright Red Hat Inc. and Hibernate Authors
*/
package org.hibernate.orm.test.envers.integration.basic;

import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.Id;
import org.hibernate.annotations.Nationalized;
import org.hibernate.community.dialect.DerbyDialect;
import org.hibernate.dialect.DB2Dialect;
import org.hibernate.dialect.HANADialect;
import org.hibernate.dialect.OracleDialect;
import org.hibernate.dialect.PostgreSQLDialect;
import org.hibernate.dialect.SybaseDialect;
import org.hibernate.envers.Audited;
import org.hibernate.mapping.Table;
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.SessionFactory;
import org.hibernate.testing.orm.junit.SkipForDialect;
import org.hibernate.type.StandardBasicTypes;
import org.junit.jupiter.api.Test;
import org.opentest4j.AssertionFailedError;

import static org.hibernate.boot.model.naming.Identifier.toIdentifier;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertThrows;

@JiraKey(value = "HHH-19976")
@DomainModel(annotatedClasses = {NationalizedTest.NationalizedEntity.class})
@SessionFactory
@SkipForDialect(dialectClass = OracleDialect.class)
@SkipForDialect(dialectClass = PostgreSQLDialect.class, matchSubTypes = true, reason = "@Lob field in HQL predicate fails with error about text = bigint")
@SkipForDialect(dialectClass = HANADialect.class, matchSubTypes = true, reason = "HANA doesn't support comparing LOBs with the = operator")
@SkipForDialect(dialectClass = SybaseDialect.class, matchSubTypes = true, reason = "Sybase doesn't support comparing LOBs with the = operator")
@SkipForDialect(dialectClass = DB2Dialect.class, matchSubTypes = true, reason = "DB2 jdbc driver doesn't support setNString")
@SkipForDialect(dialectClass = DerbyDialect.class, matchSubTypes = true, reason = "Derby jdbc driver doesn't support setNString")
public class NationalizedTest {

@Test
public void testMetadataBindings(DomainModelScope scope) {
final var domainModel = scope.getDomainModel();

assertThrows( AssertionFailedError.class, () -> {
final Table auditTable = domainModel.getEntityBinding( NationalizedEntity.class.getName() + "_AUD" )
.getTable();

final org.hibernate.mapping.Column colDef = auditTable.getColumn( toIdentifier( "nationalizedString" ) );
assertEquals( StandardBasicTypes.NSTRING.getName(), colDef.getTypeName() );
} );
}

@Entity(name = "NationalizedEntity")
@Audited
public static class NationalizedEntity {
@Id
@GeneratedValue
private Integer id;
@Nationalized
private String nationalizedString;
}
}
Loading