From: <hib...@li...> - 2006-05-05 18:01:45
|
Author: epbernard Date: 2006-05-05 14:01:32 -0400 (Fri, 05 May 2006) New Revision: 9894 Modified: trunk/HibernateExt/metadata/src/java/org/hibernate/cfg/annotations/MapBinder.java trunk/HibernateExt/metadata/src/test/org/hibernate/test/annotations/entity/BasicHibernateAnnotationsTest.java trunk/HibernateExt/metadata/src/test/org/hibernate/test/annotations/inheritance/singletable/SingleTableTest.java trunk/HibernateExt/metadata/src/test/org/hibernate/test/annotations/onetomany/City.java Log: ANN-120 support association table MapKey through formula Modified: trunk/HibernateExt/metadata/src/java/org/hibernate/cfg/annotations/MapBinder.java =================================================================== --- trunk/HibernateExt/metadata/src/java/org/hibernate/cfg/annotations/MapBinder.java 2006-05-05 16:58:38 UTC (rev 9893) +++ trunk/HibernateExt/metadata/src/java/org/hibernate/cfg/annotations/MapBinder.java 2006-05-05 18:01:32 UTC (rev 9894) @@ -4,6 +4,7 @@ import java.util.HashMap; import java.util.Iterator; import java.util.Map; +import java.util.Random; import javax.persistence.AttributeOverride; import javax.persistence.AttributeOverrides; import javax.persistence.Embeddable; @@ -12,6 +13,9 @@ import org.hibernate.AssertionFailure; import org.hibernate.FetchMode; import org.hibernate.MappingException; +import org.hibernate.dialect.HSQLDialect; +import org.hibernate.sql.Template; +import org.hibernate.util.StringHelper; import org.hibernate.annotations.AccessType; import org.hibernate.cfg.AnnotatedClassType; import org.hibernate.cfg.AnnotationBinder; @@ -28,12 +32,16 @@ import org.hibernate.mapping.Collection; import org.hibernate.mapping.Column; import org.hibernate.mapping.Component; +import org.hibernate.mapping.DependantValue; import org.hibernate.mapping.Formula; import org.hibernate.mapping.Join; import org.hibernate.mapping.ManyToOne; +import org.hibernate.mapping.OneToMany; import org.hibernate.mapping.PersistentClass; import org.hibernate.mapping.Property; import org.hibernate.mapping.SimpleValue; +import org.hibernate.mapping.Table; +import org.hibernate.mapping.ToOne; import org.hibernate.mapping.Value; import org.hibernate.reflection.XAnnotatedElement; import org.hibernate.reflection.XClass; @@ -69,7 +77,8 @@ ); bindKeyFromAssociationTable( collType, persistentClasses, mapKeyPropertyName, property, isEmbedded, mappings, - mapKeyColumns, mapKeyManyToManyColumns + mapKeyColumns, mapKeyManyToManyColumns, + inverseColumns != null ? inverseColumns[0].getPropertyName() : null ); } }; @@ -78,7 +87,7 @@ private void bindKeyFromAssociationTable( String collType, Map persistentClasses, String mapKeyPropertyName, XProperty property, boolean isEmbedded, ExtendedMappings mappings, Ejb3Column[] mapKeyColumns, - Ejb3JoinColumn[] mapKeyManyToManyColumns + Ejb3JoinColumn[] mapKeyManyToManyColumns, String targetPropertyName ) { if ( mapKeyPropertyName != null ) { //this is an EJB3 @MapKey @@ -91,7 +100,7 @@ ); } org.hibernate.mapping.Map map = (org.hibernate.mapping.Map) this.collection; - Value indexValue = createFormulatedValue( mapProperty.getValue(), map ); + Value indexValue = createFormulatedValue( mapProperty.getValue(), map, targetPropertyName, associatedClass ); map.setIndex( indexValue ); } else { @@ -218,7 +227,52 @@ } } - protected Value createFormulatedValue(Value value, Collection collection) { + protected Value createFormulatedValue( + Value value, Collection collection, String targetPropertyName, PersistentClass associatedClass + ) { + Value element = collection.getElement(); + String fromAndWhere = null; + if ( ! ( element instanceof OneToMany ) ) { + String referencedPropertyName= null; + if ( element instanceof ToOne ) { + referencedPropertyName = ( (ToOne) element ).getReferencedPropertyName(); + } + else if ( element instanceof DependantValue ) { + //TODO this never happen I think + if ( propertyName != null ) { + Collection coll = (Collection) associatedClass.getProperty( propertyName ) + .getValue(); + referencedPropertyName = collection.getReferencedPropertyName(); + } + else { + throw new AnnotationException( "SecondaryTable JoinColumn cannot reference a non primary key" ); + } + } + Table table; + Iterator referencedEntityColumns; + if (referencedPropertyName == null) { + table = associatedClass.getTable(); + referencedEntityColumns = associatedClass.getIdentifier().getColumnIterator(); + } + else { + Property referencedProperty = associatedClass.getProperty( referencedPropertyName ); + table = referencedProperty.getValue().getTable(); + referencedEntityColumns = referencedProperty.getColumnIterator(); + } + String alias = "$alias$"; + StringBuilder fromAndWhereSb = new StringBuilder( " from " ) + .append( associatedClass.getTable().getName() ) + .append(" as ").append(alias).append(" where "); + Iterator collectionTableColumns = element.getColumnIterator(); + while ( collectionTableColumns.hasNext() ) { + Column colColumn = (Column) collectionTableColumns.next(); + Column refColumn = (Column) referencedEntityColumns.next(); + fromAndWhereSb.append(alias).append('.').append( refColumn.getQuotedName() ) + .append('=').append( colColumn.getQuotedName() ).append(','); + } + fromAndWhere = fromAndWhereSb.substring(0, fromAndWhereSb.length() - 1 ); + } + if ( value instanceof Component ) { Component component = (Component) value; Iterator properties = component.getPropertyIterator(); @@ -239,7 +293,9 @@ newProperty.setPersistentClass( current.getPersistentClass() ); newProperty.setPropertyAccessorName( current.getPropertyAccessorName() ); newProperty.setSelectable( current.isSelectable() ); - newProperty.setValue( createFormulatedValue( current.getValue(), collection) ); + newProperty.setValue( createFormulatedValue( current.getValue(), collection, targetPropertyName, + associatedClass + ) ); indexComponent.addProperty( newProperty ); } return indexComponent; @@ -262,19 +318,31 @@ targetValue.setTypeParameters( sourceValue.getTypeParameters() ); } Iterator columns = sourceValue.getColumnIterator(); + Random random = new Random(); while ( columns.hasNext() ) { Object current = columns.next(); Formula formula = new Formula(); + String formulaString; if ( current instanceof Column ) { - formula.setFormula( ( (Column) current ).getName() ); + formulaString = ( (Column) current ).getName(); //FIXME support quoted name } else if ( current instanceof Formula ) { - formula.setFormula( ( (Formula) current ).getFormula() ); + formulaString = ( (Formula) current ).getFormula(); } else { throw new AssertionFailure( "Unknown element in column iterator: " + current.getClass() ); } + if (fromAndWhere != null) { + formulaString = Template.renderWhereStringTemplate( formulaString, "$alias$", new HSQLDialect() ); + formulaString = "select " + formulaString + fromAndWhere; + formulaString = StringHelper.replace( + formulaString, + "$alias$", + "a" + random.nextInt( 16 ) + ); + } + formula.setFormula( formulaString ); targetValue.addFormula( formula ); } Modified: trunk/HibernateExt/metadata/src/test/org/hibernate/test/annotations/entity/BasicHibernateAnnotationsTest.java =================================================================== --- trunk/HibernateExt/metadata/src/test/org/hibernate/test/annotations/entity/BasicHibernateAnnotationsTest.java 2006-05-05 16:58:38 UTC (rev 9893) +++ trunk/HibernateExt/metadata/src/test/org/hibernate/test/annotations/entity/BasicHibernateAnnotationsTest.java 2006-05-05 18:01:32 UTC (rev 9894) @@ -214,12 +214,12 @@ s = openSession(); tx = s.beginTransaction(); s.enableFilter( "betweenLength" ).setParameter( "minLength", 5 ).setParameter( "maxLength", 50 ); - int count = ( (Integer) s.createQuery( "select count(*) from Forest" ).iterate().next() ).intValue(); + long count = ( (Long) s.createQuery( "select count(*) from Forest" ).iterate().next() ).intValue(); assertEquals( 1, count ); s.disableFilter( "betweenLength" ); s.enableFilter( "minLength" ).setParameter( "minLength", 5 ); - count = ( (Integer) s.createQuery( "select count(*) from Forest" ).iterate().next() ).intValue(); - assertEquals( 2, count ); + count = ( (Long) s.createQuery( "select count(*) from Forest" ).iterate().next() ).longValue(); + assertEquals( 2l, count ); s.disableFilter( "minLength" ); tx.rollback(); s.close(); Modified: trunk/HibernateExt/metadata/src/test/org/hibernate/test/annotations/inheritance/singletable/SingleTableTest.java =================================================================== --- trunk/HibernateExt/metadata/src/test/org/hibernate/test/annotations/inheritance/singletable/SingleTableTest.java 2006-05-05 16:58:38 UTC (rev 9893) +++ trunk/HibernateExt/metadata/src/test/org/hibernate/test/annotations/inheritance/singletable/SingleTableTest.java 2006-05-05 18:01:32 UTC (rev 9894) @@ -41,7 +41,7 @@ s = openSession(); tx = s.beginTransaction(); - assertEquals( 1, s.createQuery( "select count(*) from Fruit f where f.class = 'Apple'" ).uniqueResult() ); + assertEquals( 1l, s.createQuery( "select count(*) from Fruit f where f.class = 'Apple'" ).uniqueResult() ); List result = s.createCriteria( Fruit.class ).list(); assertNotNull( result ); assertEquals( 2, result.size() ); @@ -70,7 +70,7 @@ s = openSession(); tx = s.beginTransaction(); assertEquals( - 1, s.createQuery( "select count(*) from Trash f where f.class = :disc" ) + 1l, s.createQuery( "select count(*) from Trash f where f.class = :disc" ) .setString( "disc", String.valueOf( "PaperTrash".hashCode() ) ).uniqueResult() ); List result = s.createCriteria( Trash.class ).list(); Modified: trunk/HibernateExt/metadata/src/test/org/hibernate/test/annotations/onetomany/City.java =================================================================== --- trunk/HibernateExt/metadata/src/test/org/hibernate/test/annotations/onetomany/City.java 2006-05-05 16:58:38 UTC (rev 9893) +++ trunk/HibernateExt/metadata/src/test/org/hibernate/test/annotations/onetomany/City.java 2006-05-05 18:01:32 UTC (rev 9894) @@ -14,7 +14,7 @@ * @author Emmanuel Bernard */ @Entity -public class City { +class City { private Integer id; private String name; private List<Street> streets; @@ -40,7 +40,7 @@ @OneToMany(mappedBy = "city") @OrderBy("streetName, id") - public List<Street> getStreets() { + public synchronized List<Street> getStreets() { return streets; } |