HHH-18516 - Ignore @AttributeOverride for map key when checking type of map value

This commit is contained in:
Kyrylo Merzlikin 2024-08-24 19:07:54 +03:00 committed by Marco Belladelli
parent d39ba13ee4
commit ad6f326090
5 changed files with 121 additions and 2 deletions

View File

@ -2356,8 +2356,7 @@ public abstract class CollectionBinder {
}
else {
//force in case of attribute override
final boolean attributeOverride = property.hasDirectAnnotationUsage( AttributeOverride.class )
|| property.hasDirectAnnotationUsage( AttributeOverrides.class );
final boolean attributeOverride = mappingDefinedAttributeOverrideOnElement(property);
// todo : force in the case of Convert annotation(s) with embedded paths (beyond key/value prefixes)?
return isEmbedded || attributeOverride
? EMBEDDABLE
@ -2365,6 +2364,11 @@ public abstract class CollectionBinder {
}
}
protected boolean mappingDefinedAttributeOverrideOnElement(MemberDetails property) {
return property.hasDirectAnnotationUsage( AttributeOverride.class )
|| property.hasDirectAnnotationUsage( AttributeOverrides.class );
}
static AnnotatedColumns createElementColumnsIfNecessary(
Collection collection,
AnnotatedColumns elementColumns,

View File

@ -109,6 +109,26 @@ public class MapBinder extends CollectionBinder {
};
}
@Override
protected boolean mappingDefinedAttributeOverrideOnElement(MemberDetails property) {
if ( property.hasDirectAnnotationUsage( AttributeOverride.class ) ) {
return namedMapValue( property.getDirectAnnotationUsage( AttributeOverride.class ) );
}
if ( property.hasDirectAnnotationUsage( AttributeOverrides.class ) ) {
final AttributeOverrides annotations = property.getDirectAnnotationUsage( AttributeOverrides.class );
for ( AttributeOverride attributeOverride : annotations.value() ) {
if ( namedMapValue( attributeOverride ) ) {
return true;
}
}
}
return false;
}
private boolean namedMapValue(AttributeOverride annotation) {
return annotation.name().startsWith( "value." );
}
private void makeOneToManyMapKeyColumnNullableIfNotInProperty(MemberDetails property) {
final Map map = (Map) this.collection;
if ( map.isOneToMany() && property.hasDirectAnnotationUsage( MapKeyColumn.class ) ) {

View File

@ -0,0 +1,45 @@
package org.hibernate.orm.test.annotations.attributeoverride;
import java.time.LocalTime;
import java.util.Map;
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.Test;
import jakarta.persistence.metamodel.EntityType;
import jakarta.persistence.metamodel.MapAttribute;
import static jakarta.persistence.metamodel.Type.PersistenceType.BASIC;
import static jakarta.persistence.metamodel.Type.PersistenceType.EMBEDDABLE;
import static org.assertj.core.api.Assertions.assertThat;
@DomainModel(
annotatedClasses = {
Schedule.class,
Route.class
}
)
@SessionFactory
class MapAttributeOverrideTest {
@Test
@JiraKey("HHH-18516")
void testMapOfEmbeddableKeysWithAttributeOverridesAndBasicValues(SessionFactoryScope sessionFactoryScope) {
sessionFactoryScope.inTransaction(session -> {
EntityType<Schedule> scheduleType = session.getMetamodel().entity(Schedule.class);
MapAttribute<? super Schedule, ?, ?> departuresMapAttribute = scheduleType.getMap("departures");
// Presence of @AttributeOverride-s for the key should only affect the type of the key, but not the type of the value
assertThat(departuresMapAttribute.getKeyType().getPersistenceType()).isEqualTo(EMBEDDABLE);
assertThat(departuresMapAttribute.getElementType().getPersistenceType()).isEqualTo(BASIC);
session.persist(new Schedule(Map.of(
new Route("Hamburg", "Vienna"), LocalTime.NOON,
new Route("Warsaw", "Barcelona"), LocalTime.MIDNIGHT
)));
assertThat(session.createQuery("FROM Schedule s", Schedule.class).getResultCount()).isOne();
});
}
}

View File

@ -0,0 +1,18 @@
package org.hibernate.orm.test.annotations.attributeoverride;
import jakarta.persistence.Embeddable;
@Embeddable
public class Route {
private String origin;
private String destination;
public Route() {
}
public Route(String origin, String destination) {
this.origin = origin;
this.destination = destination;
}
}

View File

@ -0,0 +1,32 @@
package org.hibernate.orm.test.annotations.attributeoverride;
import java.time.LocalTime;
import java.util.Map;
import jakarta.persistence.AttributeOverride;
import jakarta.persistence.Column;
import jakarta.persistence.ElementCollection;
import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.Id;
@Entity
public class Schedule {
@Id
@GeneratedValue
private Long id;
@ElementCollection
@Column(name = "time")
@AttributeOverride(name = "key.origin", column = @Column(name = "orig"))
@AttributeOverride(name = "key.destination", column = @Column(name = "dest"))
private Map<Route, LocalTime> departures;
public Schedule() {
}
public Schedule(Map<Route, LocalTime> departures) {
this.departures = departures;
}
}