HHH-4352 support for key. and value. for Map and @AttributeOverride. Managed to keep support for legacy names as well.

git-svn-id: https://svn.jboss.org/repos/hibernate/core/trunk@18393 1b8cb986-b30d-0410-93ca-fae66ebed9b2
This commit is contained in:
Emmanuel Bernard 2010-01-04 16:47:08 +00:00
parent 41b12a6479
commit ef1cb9f066
8 changed files with 147 additions and 7 deletions

View File

@ -98,8 +98,48 @@ public abstract class AbstractPropertyHolder implements PropertyHolder {
/**
* Get column overriding, property first, then parent, then holder
* replace
* - "index" by "key" if present
* - "element" by "value" if present
* These rules are here to support both JPA 2 and legacy overriding rules.
*
* WARNING: this can conflict with user's expectations if:
* - the property uses some restricted values
* - the user has overridden the column
* But this is unlikely and avoid the need for a "legacy" flag
*/
public Column[] getOverriddenColumn(String propertyName) {
Column[] result = getExactOverriddenColumn( propertyName );
if (result == null) {
if ( propertyName.contains( ".key." ) ) {
//TODO cache the underlying regexp
result = getExactOverriddenColumn( propertyName.replace( ".key.", ".index." ) );
}
if ( result == null && propertyName.endsWith( ".key" ) ) {
//TODO cache the underlying regexp
result = getExactOverriddenColumn(
propertyName.substring( 0, propertyName.length() - ".key".length() ) + ".index"
);
}
if ( result == null && propertyName.contains( ".value." ) ) {
//TODO cache the underlying regexp
result = getExactOverriddenColumn( propertyName.replace( ".value.", ".element." ) );
}
if ( result == null && propertyName.endsWith( ".value" ) ) {
//TODO cache the underlying regexp
result = getExactOverriddenColumn(
propertyName.substring( 0, propertyName.length() - ".value".length() ) + ".element"
);
}
}
return result;
}
/**
* Get column overriding, property first, then parent, then holder
* find the overridden rules from the exact property name.
*/
private Column[] getExactOverriddenColumn(String propertyName) {
Column[] override = null;
if ( parent != null ) {
override = parent.getOverriddenColumn( propertyName );

View File

@ -1672,6 +1672,7 @@ public final class AnnotationBinder {
//nullify empty array
keyColumns = keyColumns != null && keyColumns.length > 0 ? keyColumns : null;
//"mapkey" is the legacy column name of the key column pre JPA 2
PropertyData mapKeyVirtualProperty = new WrappedInferredData( inferredData, "mapkey" );
Ejb3Column[] mapColumns = Ejb3Column.buildColumnFromAnnotation(
keyColumns,

View File

@ -1295,7 +1295,8 @@ public abstract class CollectionBinder {
throw new AssertionFailure( "Unable to guess collection property accessor name" );
}
PropertyData inferredData = new PropertyPreloadedData( AccessType.PROPERTY, "element", elementClass );
//"value" is the JPA 2 prefix for map values (used to be "element")
PropertyData inferredData = new PropertyPreloadedData( AccessType.PROPERTY, "value", elementClass );
//TODO be smart with isNullable
Component component = AnnotationBinder.fillComponent(
holder, inferredData, isPropertyAnnotated ? AccessType.PROPERTY : AccessType.FIELD, true,

View File

@ -174,10 +174,6 @@ public class MapBinder extends CollectionBinder {
else {
XClass elementClass;
AnnotatedClassType classType;
// Map<String, javax.persistence.Column[]> columnOverrides = PropertyHolderBuilder.buildColumnOverride(
// property, StringHelper.qualify( collValue.getRole(), "element" )
// );
//FIXME the "element" is lost
PropertyHolder holder = null;
if ( BinderHelper.PRIMITIVE_NAMES.contains( mapKeyType ) ) {
classType = AnnotatedClassType.NONE;
@ -227,8 +223,8 @@ public class MapBinder extends CollectionBinder {
}
//boolean propertyAccess = embeddable == null || AccessType.PROPERTY.equals( embeddable.access() );
//FIXME "index" is it right?
PropertyData inferredData = new PropertyPreloadedData( AccessType.PROPERTY, "index", elementClass );
//"key" is the JPA 2 prefix for map keys
PropertyData inferredData = new PropertyPreloadedData( AccessType.PROPERTY, "key", elementClass );
//TODO be smart with isNullable
Component component = AnnotationBinder.fillComponent(
holder, inferredData, isPropertyAnnotated ? AccessType.PROPERTY : AccessType.FIELD, true,

View File

@ -0,0 +1,14 @@
package org.hibernate.test.annotations.override;
import javax.persistence.Embedded;
import javax.persistence.Embeddable;
/**
* @author Emmanuel Bernard
*/
@Embeddable
public class Address {
public String street;
public String city;
public String state;
}

View File

@ -0,0 +1,46 @@
package org.hibernate.test.annotations.override;
import java.util.Iterator;
import org.hibernate.test.annotations.TestCase;
import org.hibernate.metadata.CollectionMetadata;
import org.hibernate.engine.SessionFactoryImplementor;
import org.hibernate.persister.collection.CollectionPersister;
import org.hibernate.mapping.Table;
import org.hibernate.mapping.Column;
/**
* @author Emmanuel Bernard
*/
public class AttributeOverrideTest extends TestCase {
public void testMapKeyValue() throws Exception {
assertTrue( isColumnPresent( "PropertyRecord_parcels", "ASSESSMENT") );
assertTrue( isColumnPresent( "PropertyRecord_parcels", "SQUARE_FEET") );
assertTrue( isColumnPresent( "PropertyRecord_parcels", "STREET_NAME") );
}
public boolean isColumnPresent(String tableName, String columnName) {
final Iterator<Table> tables = ( Iterator<Table> ) getCfg().getTableMappings();
while (tables.hasNext()) {
Table table = tables.next();
if (tableName.equals( table.getName() ) ) {
Iterator<Column> columns = (Iterator<Column>) table.getColumnIterator();
while ( columns.hasNext() ) {
Column column = columns.next();
if ( columnName.equals( column.getName() ) ) {
return true;
}
}
}
}
return false;
}
protected Class<?>[] getMappings() {
return new Class<?>[] {
PropertyInfo.class,
PropertyRecord.class,
Address.class
};
}
}

View File

@ -0,0 +1,14 @@
package org.hibernate.test.annotations.override;
import java.math.BigDecimal;
import javax.persistence.Embeddable;
/**
* @author Emmanuel Bernard
*/
@Embeddable
public class PropertyInfo {
public Integer parcelNumber;
public Integer size;
public BigDecimal tax;
}

View File

@ -0,0 +1,28 @@
package org.hibernate.test.annotations.override;
import java.util.Map;
import javax.persistence.AttributeOverride;
import javax.persistence.AttributeOverrides;
import javax.persistence.Column;
import javax.persistence.ElementCollection;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
/**
* @author Emmanuel Bernard
*/
@Entity
public class PropertyRecord {
@Id
@GeneratedValue
public Long id;
@AttributeOverrides({
@AttributeOverride(name = "key.street", column = @Column(name = "STREET_NAME")),
@AttributeOverride(name = "value.size", column = @Column(name = "SQUARE_FEET")),
@AttributeOverride(name = "value.tax", column = @Column(name = "ASSESSMENT"))
})
@ElementCollection
public Map<Address, PropertyInfo> parcels;
}