HHH-18516 - Ignore @AttributeOverride for map key when checking type of map value
This commit is contained in:
parent
d39ba13ee4
commit
ad6f326090
|
@ -2356,8 +2356,7 @@ public abstract class CollectionBinder {
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
//force in case of attribute override
|
//force in case of attribute override
|
||||||
final boolean attributeOverride = property.hasDirectAnnotationUsage( AttributeOverride.class )
|
final boolean attributeOverride = mappingDefinedAttributeOverrideOnElement(property);
|
||||||
|| property.hasDirectAnnotationUsage( AttributeOverrides.class );
|
|
||||||
// todo : force in the case of Convert annotation(s) with embedded paths (beyond key/value prefixes)?
|
// todo : force in the case of Convert annotation(s) with embedded paths (beyond key/value prefixes)?
|
||||||
return isEmbedded || attributeOverride
|
return isEmbedded || attributeOverride
|
||||||
? EMBEDDABLE
|
? 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(
|
static AnnotatedColumns createElementColumnsIfNecessary(
|
||||||
Collection collection,
|
Collection collection,
|
||||||
AnnotatedColumns elementColumns,
|
AnnotatedColumns elementColumns,
|
||||||
|
|
|
@ -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) {
|
private void makeOneToManyMapKeyColumnNullableIfNotInProperty(MemberDetails property) {
|
||||||
final Map map = (Map) this.collection;
|
final Map map = (Map) this.collection;
|
||||||
if ( map.isOneToMany() && property.hasDirectAnnotationUsage( MapKeyColumn.class ) ) {
|
if ( map.isOneToMany() && property.hasDirectAnnotationUsage( MapKeyColumn.class ) ) {
|
||||||
|
|
|
@ -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();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue