From 20d22941c0e07b37295704d5300a7071e48e640d Mon Sep 17 00:00:00 2001 From: Emmanuel Bernard Date: Tue, 21 Jul 2009 02:07:50 +0000 Subject: [PATCH] ANN-856 implement @MapKeyColumn git-svn-id: https://svn.jboss.org/repos/hibernate/core/trunk@17173 1b8cb986-b30d-0410-93ca-fae66ebed9b2 --- .../org/hibernate/cfg/AnnotationBinder.java | 21 +++++-- .../cfg/annotations/CollectionBinder.java | 7 ++- .../cfg/annotations/CustomizableColumns.java | 27 ++++++++ .../hibernate/cfg/annotations/MapBinder.java | 9 +-- .../annotations/MapKeyColumnDelegator.java | 61 +++++++++++++++++++ .../test/annotations/any/PropertyMap.java | 2 +- .../collectionelement/LocalizedString.java | 3 +- .../annotations/indexcoll/Atmosphere.java | 3 +- .../test/annotations/target/Brand.java | 3 +- .../test/annotations/target/OwnerImpl.java | 4 -- 10 files changed, 120 insertions(+), 20 deletions(-) create mode 100644 annotations/src/main/java/org/hibernate/cfg/annotations/CustomizableColumns.java create mode 100644 annotations/src/main/java/org/hibernate/cfg/annotations/MapKeyColumnDelegator.java diff --git a/annotations/src/main/java/org/hibernate/cfg/AnnotationBinder.java b/annotations/src/main/java/org/hibernate/cfg/AnnotationBinder.java index fda6b4b5ff..edb91c57f9 100644 --- a/annotations/src/main/java/org/hibernate/cfg/AnnotationBinder.java +++ b/annotations/src/main/java/org/hibernate/cfg/AnnotationBinder.java @@ -73,6 +73,7 @@ import javax.persistence.Version; import javax.persistence.ElementCollection; import javax.persistence.CollectionTable; import javax.persistence.UniqueConstraint; +import javax.persistence.MapKeyColumn; import org.hibernate.AnnotationException; import org.hibernate.AssertionFailure; @@ -132,6 +133,8 @@ import org.hibernate.cfg.annotations.PropertyBinder; import org.hibernate.cfg.annotations.QueryBinder; import org.hibernate.cfg.annotations.SimpleValueBinder; import org.hibernate.cfg.annotations.TableBinder; +import org.hibernate.cfg.annotations.MapKeyColumnDelegator; +import org.hibernate.cfg.annotations.CustomizableColumns; import org.hibernate.engine.FilterDefinition; import org.hibernate.engine.Versioning; import org.hibernate.id.MultipleHiLoPerTableGenerator; @@ -1538,14 +1541,20 @@ public final class AnnotationBinder { ); } - org.hibernate.annotations.MapKey hibMapKeyAnn = property.getAnnotation( - org.hibernate.annotations.MapKey.class - ); + Column[] keyColumns = null; + //JPA 2 has priority + if ( property.isAnnotationPresent( MapKeyColumn.class ) ) { + keyColumns = new Column[] { new MapKeyColumnDelegator( property.getAnnotation( MapKeyColumn.class ) ) }; + } + else if ( property.isAnnotationPresent( org.hibernate.annotations.MapKey.class ) ) { + keyColumns = property.getAnnotation( org.hibernate.annotations.MapKey.class ).columns(); + } + //nullify empty array + keyColumns = keyColumns != null && keyColumns.length > 0 ? keyColumns : null; + PropertyData mapKeyVirtualProperty = new WrappedInferredData( inferredData, "mapkey" ); Ejb3Column[] mapColumns = Ejb3Column.buildColumnFromAnnotation( - hibMapKeyAnn != null && hibMapKeyAnn.columns().length > 0 ? - hibMapKeyAnn.columns() : - null, + keyColumns, null, Nullability.FORCED_NOT_NULL, propertyHolder, diff --git a/annotations/src/main/java/org/hibernate/cfg/annotations/CollectionBinder.java b/annotations/src/main/java/org/hibernate/cfg/annotations/CollectionBinder.java index d8a1a5c19b..8ea932a05c 100644 --- a/annotations/src/main/java/org/hibernate/cfg/annotations/CollectionBinder.java +++ b/annotations/src/main/java/org/hibernate/cfg/annotations/CollectionBinder.java @@ -39,6 +39,7 @@ import javax.persistence.ManyToMany; import javax.persistence.MapKey; import javax.persistence.OneToMany; import javax.persistence.ElementCollection; +import javax.persistence.MapKeyColumn; import org.hibernate.AnnotationException; import org.hibernate.AssertionFailure; @@ -337,9 +338,11 @@ public abstract class CollectionBinder { collection.setRole( StringHelper.qualify( propertyHolder.getPath(), propertyName ) ); collection.setNodeName( propertyName ); - if ( property.isAnnotationPresent( org.hibernate.annotations.MapKey.class ) && mapKeyPropertyName != null ) { + if ( (property.isAnnotationPresent( org.hibernate.annotations.MapKey.class ) + || property.isAnnotationPresent( MapKeyColumn.class ) ) + && mapKeyPropertyName != null ) { throw new AnnotationException( - "Cannot mix @javax.persistence.MapKey and @org.hibernate.annotations.MapKey " + "Cannot mix @javax.persistence.MapKey and @MapKeyColumn or @org.hibernate.annotations.MapKey " + "on the same collection: " + StringHelper.qualify( propertyHolder.getPath(), propertyName ) diff --git a/annotations/src/main/java/org/hibernate/cfg/annotations/CustomizableColumns.java b/annotations/src/main/java/org/hibernate/cfg/annotations/CustomizableColumns.java new file mode 100644 index 0000000000..3763e98a1a --- /dev/null +++ b/annotations/src/main/java/org/hibernate/cfg/annotations/CustomizableColumns.java @@ -0,0 +1,27 @@ +package org.hibernate.cfg.annotations; + +import java.lang.annotation.Annotation; +import java.util.ArrayList; +import javax.persistence.Column; + +import org.hibernate.annotations.Columns; + +/** + * @author Emmanuel Bernard + */ +@SuppressWarnings({ "ClassExplicitlyAnnotation" }) +public class CustomizableColumns implements Columns { + private final Column[] columns; + + public CustomizableColumns(Column[] columns) { + this.columns = columns; + } + + public Column[] columns() { + return columns; + } + + public Class annotationType() { + return Columns.class; + } +} diff --git a/annotations/src/main/java/org/hibernate/cfg/annotations/MapBinder.java b/annotations/src/main/java/org/hibernate/cfg/annotations/MapBinder.java index 367112c189..c310249abe 100644 --- a/annotations/src/main/java/org/hibernate/cfg/annotations/MapBinder.java +++ b/annotations/src/main/java/org/hibernate/cfg/annotations/MapBinder.java @@ -138,13 +138,14 @@ public class MapBinder extends CollectionBinder { Class target = void.class; /* * target has priority over reflection for the map key type + * JPA 2 has priority */ - if ( property.isAnnotationPresent( org.hibernate.annotations.MapKey.class ) ) { - target = property.getAnnotation( org.hibernate.annotations.MapKey.class ).targetElement(); - } - else if ( property.isAnnotationPresent( MapKeyClass.class ) ) { + if ( property.isAnnotationPresent( MapKeyClass.class ) ) { target = property.getAnnotation( MapKeyClass.class ).value(); } + else if ( property.isAnnotationPresent( org.hibernate.annotations.MapKey.class ) ) { + target = property.getAnnotation( org.hibernate.annotations.MapKey.class ).targetElement(); + } else if ( property.isAnnotationPresent( MapKeyManyToMany.class ) ) { target = property.getAnnotation( MapKeyManyToMany.class ).targetEntity(); } diff --git a/annotations/src/main/java/org/hibernate/cfg/annotations/MapKeyColumnDelegator.java b/annotations/src/main/java/org/hibernate/cfg/annotations/MapKeyColumnDelegator.java new file mode 100644 index 0000000000..5fd47f0d07 --- /dev/null +++ b/annotations/src/main/java/org/hibernate/cfg/annotations/MapKeyColumnDelegator.java @@ -0,0 +1,61 @@ +package org.hibernate.cfg.annotations; + +import java.lang.annotation.Annotation; +import javax.persistence.Column; +import javax.persistence.MapKeyColumn; + +/** + * @author Emmanuel Bernard + */ +@SuppressWarnings({ "ClassExplicitlyAnnotation" }) +public class MapKeyColumnDelegator implements Column { + private final MapKeyColumn column; + + public MapKeyColumnDelegator(MapKeyColumn column) { + this.column = column; + } + + public String name() { + return column.name(); + } + + public boolean unique() { + return column.unique(); + } + + public boolean nullable() { + return column.nullable(); + } + + public boolean insertable() { + return column.insertable(); + } + + public boolean updatable() { + return column.updatable(); + } + + public String columnDefinition() { + return column.columnDefinition(); + } + + public String table() { + return column.table(); + } + + public int length() { + return column.length(); + } + + public int precision() { + return column.precision(); + } + + public int scale() { + return column.scale(); + } + + public Class annotationType() { + return Column.class; + } +} diff --git a/annotations/src/test/java/org/hibernate/test/annotations/any/PropertyMap.java b/annotations/src/test/java/org/hibernate/test/annotations/any/PropertyMap.java index e52d238e2f..c1993862eb 100644 --- a/annotations/src/test/java/org/hibernate/test/annotations/any/PropertyMap.java +++ b/annotations/src/test/java/org/hibernate/test/annotations/any/PropertyMap.java @@ -61,7 +61,7 @@ public class PropertyMap { name = "map_properties", joinColumns = @JoinColumn( name = "map_id" ), inverseJoinColumns = @JoinColumn( name = "property_id" ) ) - @MapKey( columns = { @Column( name = "map_key" ) } ) + @MapKey( columns = { @Column( name = "map_key" ) } ) //keep for legacy test public Map getProperties() { return properties; } diff --git a/annotations/src/test/java/org/hibernate/test/annotations/collectionelement/LocalizedString.java b/annotations/src/test/java/org/hibernate/test/annotations/collectionelement/LocalizedString.java index 5749475d98..10bca96c5d 100644 --- a/annotations/src/test/java/org/hibernate/test/annotations/collectionelement/LocalizedString.java +++ b/annotations/src/test/java/org/hibernate/test/annotations/collectionelement/LocalizedString.java @@ -8,6 +8,7 @@ import java.util.Map; import javax.persistence.Column; import javax.persistence.ElementCollection; import javax.persistence.Embeddable; +import javax.persistence.MapKeyColumn; import org.hibernate.annotations.Fetch; import org.hibernate.annotations.FetchMode; @@ -33,7 +34,7 @@ public class LocalizedString implements Serializable { new HashMap( 1 ); @ElementCollection - @MapKey( columns = @Column( name = "language_code" ) ) + @MapKeyColumn(name = "language_code" ) @Fetch( FetchMode.JOIN ) @Filter( name = "selectedLocale", condition = " language_code = :param " ) diff --git a/annotations/src/test/java/org/hibernate/test/annotations/indexcoll/Atmosphere.java b/annotations/src/test/java/org/hibernate/test/annotations/indexcoll/Atmosphere.java index 203a889519..b62d995150 100644 --- a/annotations/src/test/java/org/hibernate/test/annotations/indexcoll/Atmosphere.java +++ b/annotations/src/test/java/org/hibernate/test/annotations/indexcoll/Atmosphere.java @@ -11,6 +11,7 @@ import javax.persistence.ManyToMany; import javax.persistence.Column; import javax.persistence.JoinTable; import javax.persistence.JoinColumn; +import javax.persistence.MapKeyColumn; import org.hibernate.annotations.MapKey; import org.hibernate.annotations.CollectionOfElements; @@ -26,7 +27,7 @@ public class Atmosphere { public Integer id; @ManyToMany(cascade = CascadeType.ALL) - @MapKey(columns = {@Column(name="gas_name")}) + @MapKeyColumn(name="gas_name") public Map gases = new HashMap(); @ManyToMany(cascade = CascadeType.ALL) diff --git a/annotations/src/test/java/org/hibernate/test/annotations/target/Brand.java b/annotations/src/test/java/org/hibernate/test/annotations/target/Brand.java index c45904bc8d..a61cd08a79 100644 --- a/annotations/src/test/java/org/hibernate/test/annotations/target/Brand.java +++ b/annotations/src/test/java/org/hibernate/test/annotations/target/Brand.java @@ -8,6 +8,7 @@ import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.Id; import javax.persistence.ManyToMany; +import javax.persistence.MapKeyClass; import org.hibernate.annotations.MapKey; import org.hibernate.annotations.MapKeyManyToMany; @@ -22,7 +23,7 @@ public class Brand { private Long id; @ManyToMany(targetEntity = LuggageImpl.class) - @MapKey(targetElement = SizeImpl.class) + @MapKeyClass(SizeImpl.class) private Map luggagesBySize = new HashMap(); @ElementCollection(targetClass = SizeImpl.class) diff --git a/annotations/src/test/java/org/hibernate/test/annotations/target/OwnerImpl.java b/annotations/src/test/java/org/hibernate/test/annotations/target/OwnerImpl.java index d89525e480..1917684e23 100644 --- a/annotations/src/test/java/org/hibernate/test/annotations/target/OwnerImpl.java +++ b/annotations/src/test/java/org/hibernate/test/annotations/target/OwnerImpl.java @@ -1,11 +1,7 @@ //$Id$ package org.hibernate.test.annotations.target; -import java.util.Map; -import java.util.HashMap; import javax.persistence.Embeddable; -import org.hibernate.annotations.MapKey; -import javax.persistence.ManyToMany; /** * @author Emmanuel Bernard