Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

6.2 backports #7684

Merged
merged 3 commits into from
Jan 10, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
4 changes: 2 additions & 2 deletions ci/quarkus.Jenkinsfile
Original file line number Diff line number Diff line change
Expand Up @@ -41,9 +41,9 @@ pipeline {
// Need to override the default maven configuration this way, because there is no other way to do it
sh "sed -i 's/-Xmx5g/-Xmx1920m/' ./.mvn/jvm.config"
sh "echo -e '\\n-XX:MaxMetaspaceSize=768m'>>./.mvn/jvm.config"
sh "./mvnw -Dquickly install"
sh "./mvnw -pl !docs -Dquickly install"
// Need to kill the gradle daemons started during the Maven install run
sh "pkill -f '.*GradleDaemon.*' || true"
sh "sudo pkill -f '.*GradleDaemon.*' || true"
// Need to override the default maven configuration this way, because there is no other way to do it
sh "sed -i 's/-Xmx1920m/-Xmx1372m/' ./.mvn/jvm.config"
sh "sed -i 's/MaxMetaspaceSize=768m/MaxMetaspaceSize=512m/' ./.mvn/jvm.config"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -149,9 +149,9 @@ public static <E extends Enum<E>> EnumeratedValueResolution<E,?> fromName(
}
else if ( style == EnumType.STRING ) {
jdbcType = jdbcTypeRegistry.getDescriptor( jdbcTypeIndicators.getColumnLength() == 1 ? CHAR : VARCHAR );
final JavaType<String> jdbcJavaType = jdbcType.getJdbcRecommendedJavaTypeMapping(
jdbcTypeIndicators.getColumnPrecision(),
jdbcTypeIndicators.getColumnScale(),
final JavaType<Object> jdbcJavaType = jdbcType.getJdbcRecommendedJavaTypeMapping(
(int) jdbcTypeIndicators.getColumnLength(),
null,
typeConfiguration
);
converter = new NamedEnumValueConverter<>( enumJavaType, jdbcType, jdbcJavaType );
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -334,7 +334,7 @@ public static <E extends Enum<E>, R> EnumeratedValueResolution<E,R> fromEnum(

if ( enumStyle == EnumType.STRING ) {
//noinspection unchecked
return (EnumeratedValueResolution<E, R>) stringEnumValueResolution(
return (EnumeratedValueResolution<E, R>) namedEnumValueResolution(
enumJavaType,
explicitJavaType,
explicitJdbcType,
Expand Down Expand Up @@ -418,7 +418,7 @@ private static <N extends Number> JavaType<N> ordinalJavaType(
}
}

private static <E extends Enum<E>> EnumeratedValueResolution<E,String> stringEnumValueResolution(
private static <E extends Enum<E>> EnumeratedValueResolution<E, Object> namedEnumValueResolution(
EnumJavaType<E> enumJavaType,
BasicJavaType<?> explicitJavaType,
JdbcType explicitJdbcType,
Expand All @@ -427,7 +427,7 @@ private static <E extends Enum<E>> EnumeratedValueResolution<E,String> stringEnu
final JdbcType jdbcType = explicitJdbcType == null
? enumJavaType.getRecommendedJdbcType( stdIndicators )
: explicitJdbcType;
final JavaType<String> relationalJtd = stringJavaType( explicitJavaType, stdIndicators, context );
final JavaType<Object> relationalJtd = namedJavaType( explicitJavaType, stdIndicators, context );

return new EnumeratedValueResolution<>(
jdbcType,
Expand All @@ -442,7 +442,7 @@ private static JdbcType stringJdbcType(JdbcType explicitJdbcType, JdbcTypeIndica
: relationalJtd.getRecommendedJdbcType( stdIndicators );
}

private static JavaType<String> stringJavaType(
private static JavaType<Object> namedJavaType(
BasicJavaType<?> explicitJavaType,
JdbcTypeIndicators stdIndicators,
MetadataBuildingContext context) {
Expand All @@ -454,7 +454,7 @@ private static JavaType<String> stringJavaType(
" should handle `java.lang.String` as its relational type descriptor"
);
}
return (JavaType<String>) explicitJavaType;
return (JavaType<Object>) explicitJavaType;
}
else {
return context.getMetadataCollector().getTypeConfiguration().getJavaTypeRegistry()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
import org.hibernate.metamodel.mapping.BasicValuedModelPart;
import org.hibernate.metamodel.mapping.EmbeddableValuedModelPart;
import org.hibernate.metamodel.mapping.EntityValuedModelPart;
import org.hibernate.metamodel.mapping.ForeignKeyDescriptor;
import org.hibernate.metamodel.mapping.ModelPart;
import org.hibernate.metamodel.mapping.SelectableMapping;
import org.hibernate.metamodel.mapping.ordering.ast.DomainPath;
Expand Down Expand Up @@ -161,19 +162,8 @@ else if ( referenceModelPart instanceof EntityValuedModelPart ) {
subPart = ( (EntityValuedModelPart) referenceModelPart ).getEntityMappingType().getIdentifierMapping();
}
else {
subPart = ( (EntityValuedModelPart) referenceModelPart ).findSubPart( modelPartName );
if ( subPart == null && referenceModelPart instanceof ToOneAttributeMapping ) {
// this is the case of sort by to-one attribute inside an embedded item,
// at this stage the foreign key descriptor should have been set on the attribute mapping,
// so we can generate a sub part valid for the order-by generation
ToOneAttributeMapping toOneAttribute = (ToOneAttributeMapping) referenceModelPart;
String foreignKeyModelPart = toOneAttribute.getAttributeName() + "."
+ toOneAttribute.getTargetKeyPropertyName();

if ( modelPartName.equals( foreignKeyModelPart ) ) {
subPart = toOneAttribute.findSubPart( toOneAttribute.getTargetKeyPropertyName() );
}
}
// Default to using the foreign key of an entity valued model part
subPart = ( (EntityValuedModelPart) referenceModelPart ).findSubPart( ForeignKeyDescriptor.PART_NAME );
}
apply(
subPart,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,15 +21,18 @@ public class FkDomainPathContinuation extends DomainPathContinuation {
private final Set<String> possiblePaths;

public FkDomainPathContinuation(
NavigablePath navigablePath, DomainPath lhs,
NavigablePath navigablePath,
DomainPath lhs,
ToOneAttributeMapping referencedModelPart) {
super( navigablePath, lhs, referencedModelPart );
this.possiblePaths = referencedModelPart.getTargetKeyPropertyNames();
}

public FkDomainPathContinuation(
NavigablePath navigablePath, DomainPath lhs,
ModelPart referencedModelPart, Set<String> possiblePaths) {
NavigablePath navigablePath,
DomainPath lhs,
ModelPart referencedModelPart,
Set<String> possiblePaths) {
super( navigablePath, lhs, referencedModelPart );
this.possiblePaths = possiblePaths;
}
Expand All @@ -40,25 +43,17 @@ public SequencePart resolvePathPart(
String identifier,
boolean isTerminal,
TranslationContext translationContext) {
HashSet<String> furtherPaths = new LinkedHashSet<>( possiblePaths.size() );
for ( String path : possiblePaths ) {
if ( !path.startsWith( name ) ) {
return new DomainPathContinuation(
navigablePath.append( name ),
this,
// unfortunately at this stage the foreign key descriptor could not be set
// on the attribute mapping yet, so we need to defer the sub part extraction later
referencedModelPart
);
}

furtherPaths.add( path.substring( name.length() + 1 ) );
}

if ( furtherPaths.isEmpty() ) {
if ( !possiblePaths.contains( name ) ) {
throw new PathResolutionException( "Domain path of type `" + referencedModelPart.getPartMappingType() + "` -> `" + name + "`" );
}

final HashSet<String> furtherPaths = new HashSet<>();
for ( String possiblePath : possiblePaths ) {
if ( possiblePath.startsWith( name ) && possiblePath.length() > name.length()
&& possiblePath.charAt( name.length() ) == '.' ) {
furtherPaths.add( possiblePath.substring( name.length() + 2 ) );
}
}
return new FkDomainPathContinuation(
navigablePath.append( name ),
this,
Expand Down
20 changes: 12 additions & 8 deletions hibernate-core/src/main/java/org/hibernate/type/EnumType.java
Original file line number Diff line number Diff line change
Expand Up @@ -273,19 +273,22 @@ private EnumValueConverter<T,?> interpretParameters(Properties parameters) {
);
}

private JavaType<String> getStringType() {
return typeConfiguration.getJavaTypeRegistry().getDescriptor(String.class);
private JavaType<Object> namedJavaType(JdbcTypeIndicators stdIndicators) {
return typeConfiguration.getJavaTypeRegistry().getDescriptor(
stdIndicators.getColumnLength() == 1 ? Character.class : String.class
);
}

private EnumValueConverter<T,?> getConverter(
EnumJavaType<T> enumJavaType,
EnumType<T>.LocalJdbcTypeIndicators localIndicators,
boolean useNamed) {
if (useNamed) {
if ( useNamed ) {
final JavaType<Object> relationalJavaType = namedJavaType( localIndicators );
return new NamedEnumValueConverter<>(
enumJavaType,
getStringType().getRecommendedJdbcType( localIndicators ),
getStringType()
relationalJavaType.getRecommendedJdbcType( localIndicators ),
relationalJavaType
);
}
else {
Expand All @@ -310,11 +313,12 @@ private EnumValueConverter<T,?> getConverterForType(
relationalJavaType
);
}
else if ( isCharacterType(type) ) {
else if ( isCharacterType( type ) ) {
final JavaType<Object> relationalJavaType = namedJavaType( localIndicators );
return new NamedEnumValueConverter<>(
enumJavaType,
getStringType().getRecommendedJdbcType( localIndicators ),
getStringType()
relationalJavaType.getRecommendedJdbcType( localIndicators ),
relationalJavaType
);
}
else {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,18 +24,19 @@
*
* @author Steve Ebersole
*/
public class NamedEnumValueConverter<E extends Enum<E>> implements EnumValueConverter<E,String>, Serializable {
public class NamedEnumValueConverter<E extends Enum<E>> implements EnumValueConverter<E, Object>, Serializable {
private final EnumJavaType<E> domainTypeDescriptor;
private final JdbcType jdbcType;
private final JavaType<String> relationalTypeDescriptor;
private final JavaType<Object> relationalTypeDescriptor;

public NamedEnumValueConverter(
EnumJavaType<E> domainTypeDescriptor,
JdbcType jdbcType,
JavaType<String> relationalTypeDescriptor) {
JavaType<?> relationalTypeDescriptor) {
this.domainTypeDescriptor = domainTypeDescriptor;
this.jdbcType = jdbcType;
this.relationalTypeDescriptor = relationalTypeDescriptor;
//noinspection unchecked
this.relationalTypeDescriptor = (JavaType<Object>) relationalTypeDescriptor;
}

@Override
Expand All @@ -44,18 +45,21 @@ public EnumJavaType<E> getDomainJavaType() {
}

@Override
public JavaType<String> getRelationalJavaType() {
public JavaType<Object> getRelationalJavaType() {
return relationalTypeDescriptor;
}

@Override
public E toDomainValue(String relationalForm) {
return domainTypeDescriptor.fromName( relationalForm );
public E toDomainValue(Object relationalForm) {
return relationalForm == null
? null
: domainTypeDescriptor.fromName( relationalTypeDescriptor.toString( relationalForm ) );
}

@Override
public String toRelationalValue(E domainForm) {
return domainTypeDescriptor.toName( domainForm );
public Object toRelationalValue(E domainForm) {
final String name = domainTypeDescriptor.toName( domainForm );
return name == null ? null : relationalTypeDescriptor.fromString( name );
}

@Override
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
/*
* 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.mapping.basic;

import java.util.List;

import org.hibernate.testing.orm.junit.DomainModel;
import org.hibernate.testing.orm.junit.JiraKey;
import org.hibernate.testing.orm.junit.SessionFactory;
import org.hibernate.testing.orm.junit.SessionFactoryScope;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;

import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.EnumType;
import jakarta.persistence.Enumerated;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.Id;

import static org.junit.jupiter.api.Assertions.assertEquals;

@SessionFactory
@DomainModel(annotatedClasses = EnumSingleCharTest.Person.class)
@JiraKey("HHH-17106")
public class EnumSingleCharTest {
@BeforeAll
public void setUp(SessionFactoryScope scope) {
scope.inTransaction( session -> {
session.persist( new Person( 1L, SinglecharEnum.B ) );
session.persist( new Person( 2L, SinglecharEnum.R ) );
} );
}

@AfterAll
public void tearDown(SessionFactoryScope scope) {
scope.inTransaction( session -> session.createMutationQuery( "delete from Person" ).executeUpdate() );
}

@Test
public void testUpdate(SessionFactoryScope scope) {
scope.inTransaction( session -> {
List<Person> resultList = session.createQuery( "from Person order by id", Person.class ).getResultList();
assertEquals( 2, resultList.size() );
assertEquals( SinglecharEnum.B, resultList.get( 0 ).getSingleChar() );
assertEquals( SinglecharEnum.R, resultList.get( 1 ).getSingleChar() );
} );
}

public enum SinglecharEnum {
B("first"),
R("second"),
O("third"),
K("fourth"),
E("fifth"),
N("sixth");

private final String item;

SinglecharEnum(String item) {
this.item = item;
}

public String getItem() {
return item;
}
}

@Entity(name = "Person")
public static class Person {
@Id
private Long id;

@Column(name="SINGLE_CHAR", length = 1)
@Enumerated(EnumType.STRING)
private SinglecharEnum singleChar;

public Person() {
}

public Person(Long id, SinglecharEnum singleChar) {
this.id = id;
this.singleChar = singleChar;
}

public SinglecharEnum getSingleChar() {
return singleChar;
}
}
}