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:
parent
41b12a6479
commit
ef1cb9f066
|
@ -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 );
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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;
|
||||
}
|
|
@ -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
|
||||
};
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
Loading…
Reference in New Issue