You can subscribe to this list here.
2002 |
Jan
|
Feb
|
Mar
|
Apr
|
May
|
Jun
|
Jul
|
Aug
|
Sep
|
Oct
(22) |
Nov
(308) |
Dec
(131) |
---|---|---|---|---|---|---|---|---|---|---|---|---|
2003 |
Jan
(369) |
Feb
(171) |
Mar
(236) |
Apr
(187) |
May
(218) |
Jun
(217) |
Jul
(127) |
Aug
(448) |
Sep
(270) |
Oct
(231) |
Nov
(422) |
Dec
(255) |
2004 |
Jan
(111) |
Feb
(73) |
Mar
(338) |
Apr
(351) |
May
(349) |
Jun
(495) |
Jul
(394) |
Aug
(1048) |
Sep
(499) |
Oct
(142) |
Nov
(269) |
Dec
(638) |
2005 |
Jan
(825) |
Feb
(1272) |
Mar
(593) |
Apr
(690) |
May
(950) |
Jun
(958) |
Jul
(767) |
Aug
(839) |
Sep
(525) |
Oct
(449) |
Nov
(585) |
Dec
(455) |
2006 |
Jan
(603) |
Feb
(656) |
Mar
(195) |
Apr
(114) |
May
(136) |
Jun
(100) |
Jul
(128) |
Aug
(68) |
Sep
(7) |
Oct
(1) |
Nov
(1) |
Dec
(8) |
2007 |
Jan
(4) |
Feb
(3) |
Mar
(8) |
Apr
(16) |
May
(5) |
Jun
(4) |
Jul
(6) |
Aug
(23) |
Sep
(15) |
Oct
(5) |
Nov
(7) |
Dec
(5) |
2008 |
Jan
(5) |
Feb
(1) |
Mar
(1) |
Apr
(5) |
May
(1) |
Jun
(1) |
Jul
|
Aug
|
Sep
|
Oct
|
Nov
(1) |
Dec
|
2009 |
Jan
|
Feb
|
Mar
|
Apr
|
May
|
Jun
|
Jul
(1) |
Aug
|
Sep
|
Oct
|
Nov
(1) |
Dec
|
2011 |
Jan
|
Feb
|
Mar
|
Apr
|
May
|
Jun
|
Jul
|
Aug
|
Sep
|
Oct
|
Nov
|
Dec
(1) |
2012 |
Jan
|
Feb
|
Mar
|
Apr
(1) |
May
|
Jun
(1) |
Jul
(1) |
Aug
(1) |
Sep
|
Oct
(2) |
Nov
(3) |
Dec
(2) |
2013 |
Jan
(1) |
Feb
|
Mar
(2) |
Apr
(1) |
May
|
Jun
|
Jul
(1) |
Aug
|
Sep
|
Oct
|
Nov
|
Dec
|
2014 |
Jan
|
Feb
|
Mar
(1) |
Apr
|
May
(2) |
Jun
(1) |
Jul
|
Aug
(1) |
Sep
(1) |
Oct
|
Nov
(1) |
Dec
|
2015 |
Jan
|
Feb
|
Mar
|
Apr
(1) |
May
|
Jun
|
Jul
|
Aug
|
Sep
(1) |
Oct
|
Nov
|
Dec
|
2016 |
Jan
|
Feb
|
Mar
(1) |
Apr
|
May
(1) |
Jun
|
Jul
|
Aug
|
Sep
|
Oct
|
Nov
|
Dec
|
2017 |
Jan
(1) |
Feb
|
Mar
|
Apr
|
May
|
Jun
|
Jul
(1) |
Aug
|
Sep
|
Oct
|
Nov
|
Dec
|
From: <hib...@li...> - 2006-04-30 04:21:51
|
Author: epbernard Date: 2006-04-30 00:21:48 -0400 (Sun, 30 Apr 2006) New Revision: 9834 Modified: trunk/HibernateExt/ejb/doc/reference/en/modules/configuration.xml Log: rephrase hibernate.ejb.discard_pc_on_close Modified: trunk/HibernateExt/ejb/doc/reference/en/modules/configuration.xml =================================================================== --- trunk/HibernateExt/ejb/doc/reference/en/modules/configuration.xml 2006-04-30 04:08:48 UTC (rev 9833) +++ trunk/HibernateExt/ejb/doc/reference/en/modules/configuration.xml 2006-04-30 04:21:48 UTC (rev 9834) @@ -359,10 +359,10 @@ <row> <entry>hibernate.ejb.discard_pc_on_close</entry> - <entry>Whether or not em.close() actually discard the - persistence context right away or wait for the transaction - completion defore discarding it (default to falseuse Application - server class enhancement at deployment time (default to false, + <entry>If true, the persistence context will be discarded (think clear() + when the method is called. Otherwise the persistence context will stay alive + till the transaction completion: all objects will remain managed, and any + change will be sy,chronized with the database (default to false, ie wait the transaction completion)</entry> </row> </tbody> |
From: <hib...@li...> - 2006-04-30 04:08:57
|
Author: epbernard Date: 2006-04-30 00:08:48 -0400 (Sun, 30 Apr 2006) New Revision: 9833 Added: trunk/HibernateExt/metadata/src/test/org/hibernate/test/annotations/manytoone/BiggestForest.java trunk/HibernateExt/metadata/src/test/org/hibernate/test/annotations/manytoone/ForestType.java trunk/HibernateExt/metadata/src/test/org/hibernate/test/annotations/manytoone/ManyToOneJoinTest.java trunk/HibernateExt/metadata/src/test/org/hibernate/test/annotations/manytoone/TreeType.java Modified: trunk/HibernateExt/metadata/doc/reference/en/modules/entity.xml trunk/HibernateExt/metadata/src/java/org/hibernate/cfg/AbstractPropertyHolder.java trunk/HibernateExt/metadata/src/java/org/hibernate/cfg/AnnotationBinder.java trunk/HibernateExt/metadata/src/java/org/hibernate/cfg/ClassPropertyHolder.java trunk/HibernateExt/metadata/src/java/org/hibernate/cfg/CollectionPropertyHolder.java trunk/HibernateExt/metadata/src/java/org/hibernate/cfg/ComponentPropertyHolder.java trunk/HibernateExt/metadata/src/java/org/hibernate/cfg/Ejb3JoinColumn.java trunk/HibernateExt/metadata/src/java/org/hibernate/cfg/PropertyHolder.java trunk/HibernateExt/metadata/src/java/org/hibernate/cfg/PropertyHolderBuilder.java trunk/HibernateExt/metadata/src/java/org/hibernate/cfg/ToOneMappedBySecondPass.java trunk/HibernateExt/metadata/src/java/org/hibernate/cfg/annotations/CollectionBinder.java trunk/HibernateExt/metadata/src/java/org/hibernate/cfg/annotations/EntityBinder.java trunk/HibernateExt/metadata/src/java/org/hibernate/cfg/annotations/TableBinder.java trunk/HibernateExt/metadata/src/test/org/hibernate/test/annotations/join/Death.java trunk/HibernateExt/metadata/src/test/org/hibernate/test/annotations/join/JoinTest.java trunk/HibernateExt/metadata/src/test/org/hibernate/test/annotations/onetoone/OneToOneTest.java Log: ANN-158 to one associations through an association table (bidirectional) Modified: trunk/HibernateExt/metadata/doc/reference/en/modules/entity.xml =================================================================== --- trunk/HibernateExt/metadata/doc/reference/en/modules/entity.xml 2006-04-28 15:44:49 UTC (rev 9832) +++ trunk/HibernateExt/metadata/doc/reference/en/modules/entity.xml 2006-04-30 04:08:48 UTC (rev 9833) @@ -961,11 +961,13 @@ <title>One-to-one</title> <para>You can associate entity beans through a one-to-one relationship - using <literal>@OneToOne</literal>. There are two cases for one-to-one - associations: either the associated entities share the same primary - keys values or a foreign key is held by one of the entities (note that - this FK column in the database should be constrained unique to - simulate one-to-one multiplicity).</para> + using <literal>@OneToOne</literal>. There are three cases for + one-to-one associations: either the associated entities share the same + primary keys values, a foreign key is held by one of the entities + (note that this FK column in the database should be constrained unique + to simulate one-to-one multiplicity), or a association table is used + to store the link between the 2 entities (a unique constraint has to + be defined on each fk to ensure the one to one multiplicity)</para> <para>First, we map a real one-to-one association using shared primary keys:</para> @@ -1051,6 +1053,53 @@ example <literal>passport_id</literal> because the property name is <literal>passport</literal> and the column id of <literal>Passport </literal>is <literal>id</literal>.</para> + + <para>The third possibility (using an association table) is very + exotic.</para> + + <programlisting> +@Entity +public class Customer implements Serializable { + @OneToOne(cascade = CascadeType.ALL) + <emphasis role="bold">@JoinTable(name = "CustomerPassports" + joinColumns = @JoinColumn(name="customer_fk"), + inverseJoinColumns = @JoinColumns(name="passport_fk")</emphasis> + ) + public Passport getPassport() { + ... + } + +@Entity +public class Passport implements Serializable { + @OneToOne(<emphasis role="bold">mappedBy = "passport"</emphasis>) + public Customer getOwner() { + ... +} + </programlisting> + + <para>A <classname>Customer</classname> is linked to a + <classname>Passport</classname> through a association table named + <literal>CustomerPassports</literal> ; this association table has a + foreign key column named <literal>passport_fk</literal> pointing to + the <literal>Passport</literal> table (materialized by the + <literal>inverseJoinColumn</literal>, and a foreign key column named + <literal>customer_fk</literal> pointing to the + <literal>Customer</literal> table materialized by the + <literal>joinColumns</literal> attribute.</para> + + <para>The association may be bidirectional. In a bidirectional + relationship, one of the sides (and only one) has to be the owner: the + owner is responsible for the association column(s) update. To declare + a side as <emphasis>not</emphasis> responsible for the relationship, + the attribute <literal>mappedBy</literal> is used. + <literal>mappedBy</literal> refers to the property name of the + association on the owner side. In our case, this is + <literal>passport</literal>. As you can see, you don't have to (must + not) declare the join column since it has already been declared on the + owners side.</para> + + <para>You must declare the join table name and the join columns + explicitly in such a mapping.</para> </sect3> <sect3> @@ -1101,6 +1150,29 @@ public interface Company { ... </programlisting> + + <para>You can alse map a many to one association through an + association table. This association table described by the + <literal>@JoinTable</literal> annotation will contains a foreign key + referencing back the entity table (through + <literal>@JoinTable.joinColumns</literal>) and a a foreign key + referencing the target entity table (through + <literal>@JoinTable.inverseJoinColumns</literal>).</para> + + <programlisting> +@Entity() +public class Flight implements Serializable { + @ManyToOne( cascade = {CascadeType.PERSIST, CascadeType.MERGE} ) + <emphasis role="bold">@JoinTable(name="Flight_Company", + joinColumns = @JoinColumn(name="FLIGHT_ID"), + inverseJoinColumns = @JoinColumns(name="COMP_ID") + )</emphasis> + public Company getCompany() { + return company; + } + ... +} + </programlisting> </sect3> <sect3 id="entity-mapping-association-collections"> @@ -1308,8 +1380,8 @@ side as the owning side, you have to remove the <literal>mappedBy</literal> element and set the many to one <literal>@JoinColumn</literal> as insertable and updatable to - false. This solution is obviously not optimized from the number of - needed statements.</para> + false. This solution is obviously not optimized and will produce + some additional UPDATE statements.</para> <programlisting>@Entity public class Troop { @@ -2563,7 +2635,7 @@ <para>EJB3 comes with the <literal>fetch</literal> option to define lazy loading and fetching modes, however Hibernate has a much more option set in this area. To fine tune the lazy loading and fetching - strategies, some additional annotations have been introduced: </para> + strategies, some additional annotations have been introduced:</para> <itemizedlist> <listitem> @@ -2589,7 +2661,7 @@ </listitem> <listitem> - <para> <literal>@Fetch</literal>: defines the fetching strategy + <para><literal>@Fetch</literal>: defines the fetching strategy used to load the association. <literal>FetchMode</literal> can be <literal>SELECT</literal> (a select is triggered when the association needs to be loaded), <literal>SUBSELECT</literal> Modified: trunk/HibernateExt/metadata/src/java/org/hibernate/cfg/AbstractPropertyHolder.java =================================================================== --- trunk/HibernateExt/metadata/src/java/org/hibernate/cfg/AbstractPropertyHolder.java 2006-04-28 15:44:49 UTC (rev 9832) +++ trunk/HibernateExt/metadata/src/java/org/hibernate/cfg/AbstractPropertyHolder.java 2006-04-30 04:08:48 UTC (rev 9833) @@ -13,17 +13,17 @@ import javax.persistence.JoinColumn; import javax.persistence.MappedSuperclass; +import org.hibernate.AssertionFailure; import org.hibernate.reflection.XAnnotatedElement; import org.hibernate.reflection.XClass; import org.hibernate.reflection.XProperty; import org.hibernate.util.StringHelper; -import org.hibernate.AssertionFailure; /** * @author Emmanuel Bernard */ public abstract class AbstractPropertyHolder implements PropertyHolder { - private PropertyHolder parent; + protected PropertyHolder parent; private Map<String, Column[]> holderColumnOverride; private Map<String, Column[]> currentPropertyColumnOverride; private Map<String, JoinColumn[]> holderJoinColumnOverride; @@ -183,6 +183,6 @@ } public void setParentProperty(String parentProperty) { - throw new AssertionFailure("Setting the parent property to a non component"); + throw new AssertionFailure( "Setting the parent property to a non component" ); } } Modified: trunk/HibernateExt/metadata/src/java/org/hibernate/cfg/AnnotationBinder.java =================================================================== --- trunk/HibernateExt/metadata/src/java/org/hibernate/cfg/AnnotationBinder.java 2006-04-28 15:44:49 UTC (rev 9832) +++ trunk/HibernateExt/metadata/src/java/org/hibernate/cfg/AnnotationBinder.java 2006-04-30 04:08:48 UTC (rev 9833) @@ -61,6 +61,7 @@ import org.hibernate.annotations.Check; import org.hibernate.annotations.CollectionOfElements; import org.hibernate.annotations.Columns; +import org.hibernate.annotations.Fetch; import org.hibernate.annotations.Filter; import org.hibernate.annotations.FilterDef; import org.hibernate.annotations.FilterDefs; @@ -68,6 +69,8 @@ import org.hibernate.annotations.Formula; import org.hibernate.annotations.GenericGenerator; import org.hibernate.annotations.Index; +import org.hibernate.annotations.LazyToOne; +import org.hibernate.annotations.LazyToOneOption; import org.hibernate.annotations.NotFound; import org.hibernate.annotations.NotFoundAction; import org.hibernate.annotations.OnDelete; @@ -75,16 +78,13 @@ import org.hibernate.annotations.OrderBy; import org.hibernate.annotations.ParamDef; import org.hibernate.annotations.Parameter; +import org.hibernate.annotations.Parent; import org.hibernate.annotations.Proxy; import org.hibernate.annotations.Sort; import org.hibernate.annotations.Type; import org.hibernate.annotations.TypeDef; import org.hibernate.annotations.TypeDefs; import org.hibernate.annotations.Where; -import org.hibernate.annotations.Parent; -import org.hibernate.annotations.LazyToOne; -import org.hibernate.annotations.Fetch; -import org.hibernate.annotations.LazyToOneOption; import org.hibernate.cfg.annotations.CollectionBinder; import org.hibernate.cfg.annotations.EntityBinder; import org.hibernate.cfg.annotations.Nullability; @@ -110,8 +110,8 @@ import org.hibernate.mapping.SingleTableSubclass; import org.hibernate.mapping.Subclass; import org.hibernate.mapping.Table; +import org.hibernate.mapping.ToOne; import org.hibernate.mapping.UnionSubclass; -import org.hibernate.mapping.ToOne; import org.hibernate.persister.entity.JoinedSubclassEntityPersister; import org.hibernate.persister.entity.SingleTableEntityPersister; import org.hibernate.persister.entity.UnionSubclassEntityPersister; @@ -377,6 +377,7 @@ final boolean hasJoinedColumns = inheritanceState.hasParents && InheritanceType.JOINED.equals( inheritanceState.type ); if ( hasJoinedColumns ) { + //@Inheritance(JOINED) subclass need to link back to the super entity PrimaryKeyJoinColumns jcsAnn = annotatedClass.getAnnotation( PrimaryKeyJoinColumns.class ); boolean explicitInheritanceJoinedColumns = jcsAnn != null && jcsAnn.value().length != 0; if ( explicitInheritanceJoinedColumns ) { @@ -386,7 +387,7 @@ for ( int colIndex = 0; colIndex < nbrOfInhJoinedColumns ; colIndex++ ) { jcAnn = jcsAnn.value()[colIndex]; inheritanceJoinedColumns[colIndex] = Ejb3JoinColumn.buildJoinColumn( - jcAnn, superEntity.getIdentifier(), + jcAnn, null, superEntity.getIdentifier(), (Map<String, Join>) null, (PropertyHolder) null, mappings ); } @@ -395,7 +396,7 @@ PrimaryKeyJoinColumn jcAnn = annotatedClass.getAnnotation( PrimaryKeyJoinColumn.class ); inheritanceJoinedColumns = new Ejb3JoinColumn[1]; inheritanceJoinedColumns[0] = Ejb3JoinColumn.buildJoinColumn( - jcAnn, superEntity.getIdentifier(), + jcAnn, null, superEntity.getIdentifier(), (Map<String, Join>) null, (PropertyHolder) null, mappings ); } @@ -498,7 +499,7 @@ PropertyHolder propertyHolder = PropertyHolderBuilder.buildPropertyHolder( clazzToProcess, persistentClass, - entityBinder.getSecondaryTables(), mappings + entityBinder, mappings ); javax.persistence.SecondaryTable secTabAnn = annotatedClass.getAnnotation( @@ -507,9 +508,7 @@ javax.persistence.SecondaryTables secTabsAnn = annotatedClass.getAnnotation( javax.persistence.SecondaryTables.class ); - PrimaryKeyJoinColumn joinColAnn = annotatedClass.getAnnotation( PrimaryKeyJoinColumn.class ); - PrimaryKeyJoinColumns joinColsAnn = annotatedClass.getAnnotation( PrimaryKeyJoinColumns.class ); - entityBinder.firstLevelSecondaryTablesBinding( secTabAnn, secTabsAnn, joinColAnn, joinColsAnn ); + entityBinder.firstLevelSecondaryTablesBinding( secTabAnn, secTabsAnn ); OnDelete onDeleteAnn = annotatedClass.getAnnotation( OnDelete.class ); boolean onDeleteAppropriate = false; @@ -977,8 +976,10 @@ propertyHolder.setParentProperty( property.getName() ); } else { - throw new AnnotationException("@Parent cannot be applied outside an embeddable object: " - + StringHelper.qualify( propertyHolder.getPath(), property.getName() ) ); + throw new AnnotationException( + "@Parent cannot be applied outside an embeddable object: " + + StringHelper.qualify( propertyHolder.getPath(), property.getName() ) + ); } return; } @@ -1026,11 +1027,17 @@ || property.isAnnotationPresent( OneToOne.class ) ) ) { if ( property.isAnnotationPresent( JoinTable.class ) ) { - JoinTable assocTable = property.getAnnotation( JoinTable.class ); - //entityBinder.firstLevelSecondaryTablesBinding(assocTable); - throw new NotYetImplementedException( - "association table on a single ended association is not yet supported" + JoinTable joinTableAnn = property.getAnnotation( JoinTable.class ); + joinColumns = Ejb3JoinColumn.buildJoinColumns( + joinTableAnn.inverseJoinColumns(), null, entityBinder.getSecondaryTables(), + propertyHolder, inferredData.getPropertyName(), mappings ); + if ( StringHelper.isEmpty( joinTableAnn.name() ) ) { + throw new AnnotationException( + "JoinTable.name() on a @ToOne association has to be explicit: " + + StringHelper.qualify( propertyHolder.getPath(), inferredData.getPropertyName() ) + ); + } } else { OneToOne oneToOneAnn = property.getAnnotation( OneToOne.class ); @@ -1178,6 +1185,13 @@ boolean ignoreNotFound = notFound != null && notFound.action().equals( NotFoundAction.IGNORE ); OnDelete onDeleteAnn = property.getAnnotation( OnDelete.class ); boolean onDeleteCascade = onDeleteAnn != null && OnDeleteAction.CASCADE.equals( onDeleteAnn.action() ); + JoinTable assocTable = property.getAnnotation( JoinTable.class ); + if ( assocTable != null ) { + Join join = propertyHolder.addJoin( assocTable, false ); + for ( Ejb3JoinColumn joinColumn : joinColumns ) { + joinColumn.setSecondaryTableName( join.getTable().getName() ); + } + } bindManyToOne( getCascadeStrategy( ann.cascade(), hibernateCascade ), joinColumns, @@ -1198,6 +1212,13 @@ boolean ignoreNotFound = notFound != null && notFound.action().equals( NotFoundAction.IGNORE ); OnDelete onDeleteAnn = property.getAnnotation( OnDelete.class ); boolean onDeleteCascade = onDeleteAnn != null && OnDeleteAction.CASCADE.equals( onDeleteAnn.action() ); + JoinTable assocTable = property.getAnnotation( JoinTable.class ); + if ( assocTable != null ) { + Join join = propertyHolder.addJoin( assocTable, false ); + for ( Ejb3JoinColumn joinColumn : joinColumns ) { + joinColumn.setSecondaryTableName( join.getTable().getName() ); + } + } bindOneToOne( getCascadeStrategy( ann.cascade(), hibernateCascade ), joinColumns, @@ -1264,7 +1285,7 @@ collectionBinder.setPropertyAccessorName( inferredData.getDefaultAccess() ); Ejb3Column[] elementColumns = null; - PropertyData wrappedInferredData = new WrappedInferredData(inferredData, "element"); + PropertyData wrappedInferredData = new WrappedInferredData( inferredData, "element" ); if ( property.isAnnotationPresent( Column.class ) || property.isAnnotationPresent( Formula.class ) ) { @@ -1299,8 +1320,10 @@ ); } - org.hibernate.annotations.MapKey hibMapKeyAnn = property.getAnnotation( org.hibernate.annotations.MapKey.class ); - wrappedInferredData = new WrappedInferredData(inferredData, "key"); + org.hibernate.annotations.MapKey hibMapKeyAnn = property.getAnnotation( + org.hibernate.annotations.MapKey.class + ); + wrappedInferredData = new WrappedInferredData( inferredData, "key" ); Ejb3Column[] mapColumns = Ejb3Column.buildColumnFromAnnotation( hibMapKeyAnn != null && hibMapKeyAnn.columns().length > 0 ? hibMapKeyAnn.columns() : null, null, @@ -1310,7 +1333,7 @@ entityBinder.getSecondaryTables(), mappings ); - collectionBinder.setMapKeyColumns(mapColumns); + collectionBinder.setMapKeyColumns( mapColumns ); //potential element collectionBinder.setEmbedded( property.isAnnotationPresent( Embedded.class ) ); @@ -1724,24 +1747,26 @@ ManyToOne manyToOne = property.getAnnotation( ManyToOne.class ); OneToOne oneToOne = property.getAnnotation( OneToOne.class ); FetchType fetchType; - if (manyToOne != null) { + if ( manyToOne != null ) { fetchType = manyToOne.fetch(); } - else if (oneToOne != null) { + else if ( oneToOne != null ) { fetchType = oneToOne.fetch(); } else { - throw new AssertionFailure( "Define fetch strategy on a property not annotated with @OneToMany nor @OneToOne"); + throw new AssertionFailure( + "Define fetch strategy on a property not annotated with @OneToMany nor @OneToOne" + ); } - if (lazy != null) { - toOne.setLazy( ! (lazy.value() == LazyToOneOption.FALSE) ); - toOne.setUnwrapProxy( (lazy.value() == LazyToOneOption.NO_PROXY) ); + if ( lazy != null ) { + toOne.setLazy( ! ( lazy.value() == LazyToOneOption.FALSE ) ); + toOne.setUnwrapProxy( ( lazy.value() == LazyToOneOption.NO_PROXY ) ); } else { toOne.setLazy( fetchType == FetchType.LAZY ); toOne.setUnwrapProxy( false ); } - if (fetch != null) { + if ( fetch != null ) { if ( fetch.value() == org.hibernate.annotations.FetchMode.JOIN ) { toOne.setFetchMode( FetchMode.JOIN ); toOne.setLazy( false ); @@ -1751,7 +1776,7 @@ toOne.setFetchMode( FetchMode.SELECT ); } else if ( fetch.value() == org.hibernate.annotations.FetchMode.SUBSELECT ) { - throw new AnnotationException( "Use of FetchMode.SUBSELECT not allowed on ToOne associations"); + throw new AnnotationException( "Use of FetchMode.SUBSELECT not allowed on ToOne associations" ); } else { throw new AssertionFailure( "Unknown FetchMode: " + fetch.value() ); @@ -1798,16 +1823,19 @@ if ( trueOneToOne || mapToPK || ! isDefault( mappedBy ) ) { //is a true one-to-one //FIXME referencedColumnName ignored => ordering may fail. + org.hibernate.mapping.OneToOne value = new org.hibernate.mapping.OneToOne( propertyHolder.getTable(), propertyHolder.getPersistentClass() ); value.setPropertyName( propertyName ); + String referencedEntityName; if ( isDefault( targetEntity, mappings ) ) { - value.setReferencedEntityName( inferredData.getClassOrElementName() ); + referencedEntityName = inferredData.getClassOrElementName(); } else { - value.setReferencedEntityName( targetEntity.getName() ); + referencedEntityName = targetEntity.getName(); } + value.setReferencedEntityName( referencedEntityName ); defineFetchingStrategy( value, inferredData.getProperty() ); //value.setFetchMode( fetchMode ); value.setCascadeDeleteEnabled( cascadeOnDelete ); @@ -1819,7 +1847,12 @@ ForeignKeyDirection.FOREIGN_KEY_FROM_PARENT : ForeignKeyDirection.FOREIGN_KEY_TO_PARENT ); - + PropertyBinder binder = new PropertyBinder(); + binder.setName( propertyName ); + binder.setValue( value ); + binder.setCascade( cascadeStrategy ); + binder.setPropertyAccessorName( inferredData.getDefaultAccess() ); + Property prop = binder.make(); if ( ! isDefault( mappedBy ) ) { mappings.addSecondPass( new ToOneMappedBySecondPass( @@ -1827,7 +1860,7 @@ value, propertyHolder.getEntityName(), propertyName, - mappings + prop, propertyHolder, ignoreNotFound, mappings ) ); } @@ -1840,17 +1873,11 @@ path, mappings ) ); + //no column associated since its a one to one + propertyHolder.addProperty( prop ); } - PropertyBinder binder = new PropertyBinder(); - binder.setName( propertyName ); - binder.setValue( value ); - binder.setCascade( cascadeStrategy ); - binder.setPropertyAccessorName( inferredData.getDefaultAccess() ); - Property prop = binder.make(); - prop.setCascade( cascadeStrategy ); - //no column associated since its a one to one - propertyHolder.addProperty( prop ); + } else { //has a FK on the table Modified: trunk/HibernateExt/metadata/src/java/org/hibernate/cfg/ClassPropertyHolder.java =================================================================== --- trunk/HibernateExt/metadata/src/java/org/hibernate/cfg/ClassPropertyHolder.java 2006-04-28 15:44:49 UTC (rev 9832) +++ trunk/HibernateExt/metadata/src/java/org/hibernate/cfg/ClassPropertyHolder.java 2006-04-30 04:08:48 UTC (rev 9833) @@ -3,7 +3,9 @@ import java.util.HashMap; import java.util.Map; +import javax.persistence.JoinTable; +import org.hibernate.cfg.annotations.EntityBinder; import org.hibernate.mapping.Component; import org.hibernate.mapping.Join; import org.hibernate.mapping.KeyValue; @@ -19,6 +21,7 @@ private PersistentClass persistentClass; private Map<String, Join> joins; private transient Map<String, Join> joinsPerRealTableName; + private EntityBinder entityBinder; public ClassPropertyHolder( PersistentClass persistentClass, XClass clazzToProcess, Map<String, Join> joins, ExtendedMappings mappings @@ -28,6 +31,14 @@ this.joins = joins; } + public ClassPropertyHolder( + PersistentClass persistentClass, XClass clazzToProcess, EntityBinder entityBinder, + ExtendedMappings mappings + ) { + this( persistentClass, clazzToProcess, entityBinder.getSecondaryTables(), mappings ); + this.entityBinder = entityBinder; + } + public String getEntityName() { return persistentClass.getEntityName(); } @@ -43,6 +54,12 @@ } } + public Join addJoin(JoinTable joinTableAnn, boolean noDelayInPkColumnCreation) { + Join join = entityBinder.addJoin( joinTableAnn, this, noDelayInPkColumnCreation ); + this.joins = entityBinder.getSecondaryTables(); + return join; + } + public void addProperty(Property prop) { if ( prop.getValue() instanceof Component ) { //TODO handle quote and non quote table comparison Modified: trunk/HibernateExt/metadata/src/java/org/hibernate/cfg/CollectionPropertyHolder.java =================================================================== --- trunk/HibernateExt/metadata/src/java/org/hibernate/cfg/CollectionPropertyHolder.java 2006-04-28 15:44:49 UTC (rev 9832) +++ trunk/HibernateExt/metadata/src/java/org/hibernate/cfg/CollectionPropertyHolder.java 2006-04-30 04:08:48 UTC (rev 9833) @@ -1,8 +1,11 @@ //$Id$ package org.hibernate.cfg; +import javax.persistence.JoinTable; + import org.hibernate.AssertionFailure; import org.hibernate.mapping.Collection; +import org.hibernate.mapping.Join; import org.hibernate.mapping.KeyValue; import org.hibernate.mapping.PersistentClass; import org.hibernate.mapping.Property; @@ -57,4 +60,8 @@ //Ejb3Column.checkPropertyConsistency( ); //already called earlier throw new AssertionFailure( "addProperty to a join table of a collection: does it make sense?" ); } + + public Join addJoin(JoinTable joinTableAnn, boolean noDelayInPkColumnCreation) { + throw new AssertionFailure( "Add a <join> in a second pass" ); + } } Modified: trunk/HibernateExt/metadata/src/java/org/hibernate/cfg/ComponentPropertyHolder.java =================================================================== --- trunk/HibernateExt/metadata/src/java/org/hibernate/cfg/ComponentPropertyHolder.java 2006-04-28 15:44:49 UTC (rev 9832) +++ trunk/HibernateExt/metadata/src/java/org/hibernate/cfg/ComponentPropertyHolder.java 2006-04-30 04:08:48 UTC (rev 9833) @@ -3,6 +3,7 @@ import javax.persistence.Column; import javax.persistence.JoinColumn; +import javax.persistence.JoinTable; import org.hibernate.AnnotationException; import org.hibernate.mapping.Component; @@ -10,6 +11,7 @@ import org.hibernate.mapping.PersistentClass; import org.hibernate.mapping.Property; import org.hibernate.mapping.Table; +import org.hibernate.mapping.Join; /** * Component implementation of property holder @@ -47,6 +49,11 @@ addProperty( prop ); } + public Join addJoin(JoinTable joinTableAnn, boolean noDelayInPkColumnCreation) { + return parent.addJoin( joinTableAnn, noDelayInPkColumnCreation ); + + } + public ComponentPropertyHolder( Component component, String path, PropertyData inferredData, PropertyHolder parent, ExtendedMappings mappings Modified: trunk/HibernateExt/metadata/src/java/org/hibernate/cfg/Ejb3JoinColumn.java =================================================================== --- trunk/HibernateExt/metadata/src/java/org/hibernate/cfg/Ejb3JoinColumn.java 2006-04-28 15:44:49 UTC (rev 9832) +++ trunk/HibernateExt/metadata/src/java/org/hibernate/cfg/Ejb3JoinColumn.java 2006-04-30 04:08:48 UTC (rev 9833) @@ -114,7 +114,7 @@ StringHelper.qualify( propertyHolder.getPath(), propertyName ) ); if ( actualColumns == null ) actualColumns = anns; - if ( actualColumns == null ) { + if ( actualColumns == null || actualColumns.length == 0 ) { return new Ejb3JoinColumn[]{ buildJoinColumn( (JoinColumn) null, mappedBy, joins, propertyHolder, propertyName, mappings ) }; @@ -199,7 +199,8 @@ * Build JoinColumn for a JOINED hierarchy */ public static Ejb3JoinColumn buildJoinColumn( - PrimaryKeyJoinColumn ann, + PrimaryKeyJoinColumn pkJoinAnn, + JoinColumn joinAnn, Value identifier, Map<String, Join> joins, PropertyHolder propertyHolder, ExtendedMappings mappings @@ -207,14 +208,27 @@ Column col = (Column) identifier.getColumnIterator().next(); String defaultName = mappings.getLogicalColumnName( col.getName(), identifier.getTable() ); - if ( ann != null ) { - String sqlType = ann.columnDefinition().equals( "" ) ? null : ann.columnDefinition(); - String name = ann.name().equals( "" ) ? defaultName : ann.name(); + if ( pkJoinAnn != null || joinAnn != null ) { + String colName; + String columnDefinition; + String referencedColumnName; + if ( pkJoinAnn != null ) { + colName = pkJoinAnn.name(); + columnDefinition = pkJoinAnn.columnDefinition(); + referencedColumnName = pkJoinAnn.referencedColumnName(); + } + else { + colName = joinAnn.name(); + columnDefinition = joinAnn.columnDefinition(); + referencedColumnName = joinAnn.referencedColumnName(); + } + String sqlType = "".equals( columnDefinition ) ? null : columnDefinition; + String name = "".equals( colName ) ? defaultName : colName; return new Ejb3JoinColumn( sqlType, name, false, false, true, true, - ann.referencedColumnName(), + referencedColumnName, null, joins, propertyHolder, null, null, false, mappings ); @@ -230,10 +244,11 @@ /** * Override persistent class on oneToMany Cases for late settings + * Must only be used on second level pass binding */ public void setPersistentClass(PersistentClass persistentClass, Map<String, Join> joins) { //FIXME shouldn't we deduce the classname from the persistentclasS? - this.propertyHolder = PropertyHolderBuilder.buildPropertyHolder( null, persistentClass, joins, getMappings() ); + this.propertyHolder = PropertyHolderBuilder.buildPropertyHolder( persistentClass, joins, getMappings() ); } public static void checkIfJoinColumn(Object columns, PropertyHolder holder, PropertyData property) { Modified: trunk/HibernateExt/metadata/src/java/org/hibernate/cfg/PropertyHolder.java =================================================================== --- trunk/HibernateExt/metadata/src/java/org/hibernate/cfg/PropertyHolder.java 2006-04-28 15:44:49 UTC (rev 9832) +++ trunk/HibernateExt/metadata/src/java/org/hibernate/cfg/PropertyHolder.java 2006-04-30 04:08:48 UTC (rev 9833) @@ -2,11 +2,13 @@ import javax.persistence.Column; import javax.persistence.JoinColumn; +import javax.persistence.JoinTable; import org.hibernate.mapping.KeyValue; import org.hibernate.mapping.PersistentClass; import org.hibernate.mapping.Property; import org.hibernate.mapping.Table; +import org.hibernate.mapping.Join; /** * Property holder abstract property containers from their direct implementation @@ -43,4 +45,6 @@ String getEntityName(); void addProperty(Property prop, Ejb3Column[] columns); + + Join addJoin(JoinTable joinTableAnn, boolean noDelayInPkColumnCreation); } Modified: trunk/HibernateExt/metadata/src/java/org/hibernate/cfg/PropertyHolderBuilder.java =================================================================== --- trunk/HibernateExt/metadata/src/java/org/hibernate/cfg/PropertyHolderBuilder.java 2006-04-28 15:44:49 UTC (rev 9832) +++ trunk/HibernateExt/metadata/src/java/org/hibernate/cfg/PropertyHolderBuilder.java 2006-04-30 04:08:48 UTC (rev 9833) @@ -3,6 +3,7 @@ import java.util.Map; +import org.hibernate.cfg.annotations.EntityBinder; import org.hibernate.mapping.Collection; import org.hibernate.mapping.Component; import org.hibernate.mapping.Join; @@ -22,9 +23,11 @@ public static PropertyHolder buildPropertyHolder( XClass clazzToProcess, PersistentClass persistentClass, - Map<String, Join> joins, ExtendedMappings mappings + EntityBinder entityBinder, + //Map<String, Join> joins, + ExtendedMappings mappings ) { - return (PropertyHolder) new ClassPropertyHolder( persistentClass, clazzToProcess, joins, mappings ); + return (PropertyHolder) new ClassPropertyHolder( persistentClass, clazzToProcess, entityBinder, mappings ); } /** @@ -52,10 +55,13 @@ return new CollectionPropertyHolder( collection, path, clazzToProcess, property, mappings ); } + /** + * must only be used on second level phases (<join> has to be settled already) + */ public static PropertyHolder buildPropertyHolder( PersistentClass persistentClass, Map<String, Join> joins, ExtendedMappings mappings ) { - return buildPropertyHolder( null, persistentClass, joins, mappings ); + return (PropertyHolder) new ClassPropertyHolder( persistentClass, null, joins, mappings ); } } Modified: trunk/HibernateExt/metadata/src/java/org/hibernate/cfg/ToOneMappedBySecondPass.java =================================================================== --- trunk/HibernateExt/metadata/src/java/org/hibernate/cfg/ToOneMappedBySecondPass.java 2006-04-28 15:44:49 UTC (rev 9832) +++ trunk/HibernateExt/metadata/src/java/org/hibernate/cfg/ToOneMappedBySecondPass.java 2006-04-30 04:08:48 UTC (rev 9833) @@ -1,42 +1,55 @@ //$Id$ package org.hibernate.cfg; +import java.util.Iterator; import java.util.Map; import org.hibernate.AnnotationException; import org.hibernate.MappingException; +import org.hibernate.mapping.Column; +import org.hibernate.mapping.DependantValue; +import org.hibernate.mapping.Join; import org.hibernate.mapping.ManyToOne; import org.hibernate.mapping.OneToOne; import org.hibernate.mapping.PersistentClass; import org.hibernate.mapping.Property; +import org.hibernate.mapping.SimpleValue; import org.hibernate.mapping.ToOne; import org.hibernate.util.StringHelper; public class ToOneMappedBySecondPass implements SecondPass { private String mappedBy; private ToOne value; - private Mappings mappings; + private ExtendedMappings mappings; private String ownerEntity; private String ownerProperty; + private PropertyHolder propertyHolder; + private Property property; + private boolean ignoreNotFound; public ToOneMappedBySecondPass( - String mappedBy, ToOne value, String ownerEntity, String ownerProperty, Mappings mappings + String mappedBy, ToOne value, String ownerEntity, String ownerProperty, Property property, + PropertyHolder propertyHolder, boolean ignoreNotFound, + ExtendedMappings mappings ) { this.ownerEntity = ownerEntity; this.ownerProperty = ownerProperty; this.mappedBy = mappedBy; this.value = value; + this.propertyHolder = propertyHolder; this.mappings = mappings; + this.property = property; + this.ignoreNotFound = ignoreNotFound; } public void doSecondPass(Map persistentClasses, Map inheritedMetas) throws MappingException { PersistentClass otherSide = (PersistentClass) persistentClasses.get( value.getReferencedEntityName() ); - Property property; + Property otherSideProperty; try { if ( otherSide == null ) { throw new MappingException( "Unable to find entity: " + value.getReferencedEntityName() ); } - property = otherSide.getProperty( mappedBy ); + otherSideProperty = otherSide.getProperty( mappedBy ); } catch (MappingException e) { throw new AnnotationException( @@ -45,10 +58,56 @@ + StringHelper.qualify( value.getReferencedEntityName(), mappedBy ) ); } - if ( property.getValue() instanceof OneToOne ) { - //do nothing + if ( otherSideProperty.getValue() instanceof OneToOne ) { + propertyHolder.addProperty( property ); } - else if ( property.getValue() instanceof ManyToOne ) { + else if ( otherSideProperty.getValue() instanceof ManyToOne ) { + Iterator it = otherSide.getJoinIterator(); + Join otherSideJoin = null; + while ( it.hasNext() ) { + otherSideJoin = (Join) it.next(); + if ( otherSideJoin.containsProperty( otherSideProperty ) ) { + break; + } + } + if ( otherSideJoin != null ) { + //@OneToOne @JoinTable + Join mappedByJoin = buildJoin( + (PersistentClass) persistentClasses.get( ownerEntity ), otherSideProperty, otherSideJoin + ); + ManyToOne manyToOne = new ManyToOne( mappedByJoin.getTable() ); + //FIXME use ignore not found here + manyToOne.setIgnoreNotFound( ignoreNotFound ); + manyToOne.setCascadeDeleteEnabled( value.isCascadeDeleteEnabled() ); + manyToOne.setEmbedded( value.isEmbedded() ); + manyToOne.setFetchMode( value.getFetchMode() ); + manyToOne.setLazy( value.isLazy() ); + manyToOne.setReferencedEntityName( value.getReferencedEntityName() ); + manyToOne.setUnwrapProxy( value.isUnwrapProxy() ); + property.setValue( manyToOne ); + Iterator otherSideJoinKeyColumns = otherSideJoin.getKey().getColumnIterator(); + while ( otherSideJoinKeyColumns.hasNext() ) { + Column column = (Column) otherSideJoinKeyColumns.next(); + Column copy = new Column(); + copy.setLength( column.getLength() ); + copy.setScale( column.getScale() ); + copy.setValue( manyToOne ); + copy.setName( column.getQuotedName() ); + copy.setNullable( column.isNullable() ); + copy.setPrecision( column.getPrecision() ); + copy.setUnique( column.isUnique() ); + copy.setSqlType( column.getSqlType() ); + copy.setCheckConstraint( column.getCheckConstraint() ); + copy.setComment( column.getComment() ); + copy.setDefaultValue( column.getDefaultValue() ); + manyToOne.addColumn( copy ); + } + mappedByJoin.addProperty( property ); + } + else { + propertyHolder.addProperty( property ); + } + value.setReferencedPropertyName( mappedBy ); String propertyRef = value.getReferencedPropertyName(); @@ -68,4 +127,40 @@ ); } } + + //dirty dupe of EntityBinder.bindSecondaryTable + private Join buildJoin(PersistentClass persistentClass, Property otherSideProperty, Join originalJoin) { + Join join = new Join(); + join.setPersistentClass( persistentClass ); + + //no check constraints available on joins + join.setTable( originalJoin.getTable() ); + join.setInverse( true ); + SimpleValue key = new DependantValue( join.getTable(), persistentClass.getIdentifier() ); + join.setKey( key ); + join.setSequentialSelect( false ); + join.setOptional( true ); //perhaps not quite per-spec, but a Good Thing anyway + key.setCascadeDeleteEnabled( false ); + Iterator mappedByColumns = otherSideProperty.getValue().getColumnIterator(); + while ( mappedByColumns.hasNext() ) { + Column column = (Column) mappedByColumns.next(); + Column copy = new Column(); + copy.setLength( column.getLength() ); + copy.setScale( column.getScale() ); + copy.setValue( key ); + copy.setName( column.getQuotedName() ); + copy.setNullable( column.isNullable() ); + copy.setPrecision( column.getPrecision() ); + copy.setUnique( column.isUnique() ); + copy.setSqlType( column.getSqlType() ); + copy.setCheckConstraint( column.getCheckConstraint() ); + copy.setComment( column.getComment() ); + copy.setDefaultValue( column.getDefaultValue() ); + key.addColumn( copy ); + } + join.createPrimaryKey(); + join.createForeignKey(); + persistentClass.addJoin( join ); + return join; + } } Modified: trunk/HibernateExt/metadata/src/java/org/hibernate/cfg/annotations/CollectionBinder.java =================================================================== --- trunk/HibernateExt/metadata/src/java/org/hibernate/cfg/annotations/CollectionBinder.java 2006-04-28 15:44:49 UTC (rev 9832) +++ trunk/HibernateExt/metadata/src/java/org/hibernate/cfg/annotations/CollectionBinder.java 2006-04-30 04:08:48 UTC (rev 9833) @@ -258,9 +258,13 @@ log.debug( "Collection role: " + StringHelper.qualify( propertyHolder.getPath(), propertyName ) ); collection.setRole( StringHelper.qualify( propertyHolder.getPath(), propertyName ) ); - if (property.isAnnotationPresent( org.hibernate.annotations.MapKey.class) && mapKeyPropertyName != null) { - throw new AnnotationException("Cannot mix @javax.persistence.MapKey and @org.hibernate.annotations.MapKey " - + "on the same collection: " + StringHelper.qualify( propertyHolder.getPath(), propertyName ) ); + if ( property.isAnnotationPresent( org.hibernate.annotations.MapKey.class ) && mapKeyPropertyName != null ) { + throw new AnnotationException( + "Cannot mix @javax.persistence.MapKey and @org.hibernate.annotations.MapKey " + + "on the same collection: " + StringHelper.qualify( + propertyHolder.getPath(), propertyName + ) + ); } //set laziness @@ -382,27 +386,29 @@ ManyToMany manyToMany = property.getAnnotation( ManyToMany.class ); CollectionOfElements elements = property.getAnnotation( CollectionOfElements.class ); FetchType fetchType; - if (oneToMany != null) { + if ( oneToMany != null ) { fetchType = oneToMany.fetch(); } - else if (manyToMany != null) { + else if ( manyToMany != null ) { fetchType = manyToMany.fetch(); } - else if (elements != null) { + else if ( elements != null ) { fetchType = elements.fetch(); } else { - throw new AssertionFailure( "Define fetch strategy on a property not annotated with @ManyToOne nor @OneToMany nor @CollectionOfElements"); + throw new AssertionFailure( + "Define fetch strategy on a property not annotated with @ManyToOne nor @OneToMany nor @CollectionOfElements" + ); } - if (lazy != null) { - collection.setLazy( ! (lazy.value() == LazyCollectionOption.FALSE) ); + if ( lazy != null ) { + collection.setLazy( ! ( lazy.value() == LazyCollectionOption.FALSE ) ); collection.setExtraLazy( lazy.value() == LazyCollectionOption.EXTRA ); } else { collection.setLazy( fetchType == FetchType.LAZY ); collection.setExtraLazy( false ); } - if (fetch != null) { + if ( fetch != null ) { if ( fetch.value() == org.hibernate.annotations.FetchMode.JOIN ) { collection.setFetchMode( FetchMode.JOIN ); collection.setLazy( false ); @@ -412,8 +418,8 @@ } else if ( fetch.value() == org.hibernate.annotations.FetchMode.SUBSELECT ) { collection.setFetchMode( FetchMode.SELECT ); - collection.setSubselectLoadable(true); - collection.getOwner().setSubselectLoadableCollections(true); + collection.setSubselectLoadable( true ); + collection.getOwner().setSubselectLoadableCollections( true ); } else { throw new AssertionFailure( "Unknown FetchMode: " + fetch.value() ); @@ -473,12 +479,32 @@ XProperty property, boolean unique, TableBinder associationTableBinder, boolean ignoreNotFound, ExtendedMappings mappings ) { - boolean isEntity = persistentClasses.containsKey( collType ); - if ( isEntity + PersistentClass persistentClass = (PersistentClass) persistentClasses.get( collType ); + boolean reversePropertyInJoin = false; + if ( persistentClass != null && StringHelper.isNotEmpty( this.mappedBy ) ) { + try { + reversePropertyInJoin = 0 != persistentClass.getJoinNumber( + persistentClass.getProperty( this.mappedBy ) + ); + } + catch (MappingException e) { + StringBuilder error = new StringBuilder( 80 ); + error.append( "mappedBy reference an unknown property: " ) + .append( collType ).append( "." ).append( this.mappedBy ) + .append( " in " ) + .append( collection.getOwnerEntityName() ) + .append( "." ) + .append( this.mappedBy ); + throw new AnnotationException( error.toString() ); + } + } + if ( persistentClass != null + && ! reversePropertyInJoin && oneToMany && ! this.isExplicitAssociationTable - && ( joinColumns[0].isImplicit() && ! AnnotationBinder.isDefault( this.mappedBy ) - || ! fkJoinColumns[0].isImplicit() ) ) { + && ( joinColumns[0].isImplicit() && ! AnnotationBinder.isDefault( this.mappedBy ) //implicit @JoinColumn + || ! fkJoinColumns[0].isImplicit() ) //this is an explicit @JoinColumn + ) { //this is a Foreign key bindOneToManySecondPass( getCollection(), @@ -780,7 +806,15 @@ .append( joinColumns[0].getPropertyName() ); throw new AnnotationException( error.toString() ); } - Table table = ( (Collection) otherSideProperty.getValue() ).getCollectionTable(); + Table table; + if ( otherSideProperty.getValue() instanceof Collection ) { + //this is a collection on the other side + table = ( (Collection) otherSideProperty.getValue() ).getCollectionTable(); + } + else { + //This is a ToOne with a @JoinTable or a regular property + table = otherSideProperty.getValue().getTable(); + } collValue.setCollectionTable( table ); String entityName = collectionEntity.getEntityName(); for ( Ejb3JoinColumn column : joinColumns ) { @@ -979,7 +1013,24 @@ final String mappedBy = columns[0].getMappedBy(); if ( StringHelper.isNotEmpty( mappedBy ) ) { final Property property = referencedEntity.getProperty( mappedBy ); - Iterator mappedByColumns = ( (Collection) property.getValue() ).getKey().getColumnIterator(); + Iterator mappedByColumns; + if ( property.getValue() instanceof Collection ) { + mappedByColumns = ( (Collection) property.getValue() ).getKey().getColumnIterator(); + } + else { + //find the appropriate reference key, can be in a join + Iterator joinsIt = referencedEntity.getJoinIterator(); + KeyValue key = null; + while ( joinsIt.hasNext() ) { + Join join = (Join) joinsIt.next(); + if ( join.containsProperty( property ) ) { + key = join.getKey(); + break; + } + } + if ( key == null ) key = property.getPersistentClass().getIdentifier(); + mappedByColumns = key.getColumnIterator(); + } while ( mappedByColumns.hasNext() ) { Column column = (Column) mappedByColumns.next(); columns[0].linkValueUsingAColumnCopy( column, value ); Modified: trunk/HibernateExt/metadata/src/java/org/hibernate/cfg/annotations/EntityBinder.java =================================================================== --- trunk/HibernateExt/metadata/src/java/org/hibernate/cfg/annotations/EntityBinder.java 2006-04-28 15:44:49 UTC (rev 9832) +++ trunk/HibernateExt/metadata/src/java/org/hibernate/cfg/annotations/EntityBinder.java 2006-04-30 04:08:48 UTC (rev 9833) @@ -7,8 +7,9 @@ import java.util.List; import java.util.Map; import javax.persistence.Entity; +import javax.persistence.JoinColumn; +import javax.persistence.JoinTable; import javax.persistence.PrimaryKeyJoinColumn; -import javax.persistence.PrimaryKeyJoinColumns; import javax.persistence.SecondaryTable; import javax.persistence.SecondaryTables; import javax.persistence.UniqueConstraint; @@ -340,37 +341,62 @@ while ( joins.hasNext() ) { Object uncastedColumn = joinColumns.next(); + Join join = (Join) joins.next(); + createPrimaryColumnsToSecondaryTable( uncastedColumn, propertyHolder, join ); + } + mappings.addJoins( persistentClass, secondaryTables ); + } - Ejb3JoinColumn[] ejb3JoinColumns; - PrimaryKeyJoinColumn[] columns = null; - if ( uncastedColumn instanceof PrimaryKeyJoinColumn[] ) { - columns = (PrimaryKeyJoinColumn[]) uncastedColumn; - } - if ( columns == null ) { + private void createPrimaryColumnsToSecondaryTable(Object uncastedColumn, PropertyHolder propertyHolder, Join join) { + Ejb3JoinColumn[] ejb3JoinColumns; + PrimaryKeyJoinColumn[] pkColumnsAnn = null; + JoinColumn[] joinColumnsAnn = null; + if ( uncastedColumn instanceof PrimaryKeyJoinColumn[] ) { + pkColumnsAnn = (PrimaryKeyJoinColumn[]) uncastedColumn; + } + if ( uncastedColumn instanceof JoinColumn[] ) { + joinColumnsAnn = (JoinColumn[]) uncastedColumn; + } + if ( pkColumnsAnn == null && joinColumnsAnn == null ) { + ejb3JoinColumns = new Ejb3JoinColumn[1]; + ejb3JoinColumns[0] = Ejb3JoinColumn.buildJoinColumn( + null, + null, + persistentClass.getIdentifier(), + secondaryTables, + propertyHolder, mappings + ); + } + else { + int nbrOfJoinColumns = pkColumnsAnn != null ? pkColumnsAnn.length : joinColumnsAnn.length; + if ( nbrOfJoinColumns == 0 ) { ejb3JoinColumns = new Ejb3JoinColumn[1]; ejb3JoinColumns[0] = Ejb3JoinColumn.buildJoinColumn( - (PrimaryKeyJoinColumn) uncastedColumn, + null, + null, persistentClass.getIdentifier(), secondaryTables, propertyHolder, mappings ); } else { - int nbrOfJoinColumns = columns.length; - if ( nbrOfJoinColumns == 0 ) { - ejb3JoinColumns = new Ejb3JoinColumn[1]; - ejb3JoinColumns[0] = Ejb3JoinColumn.buildJoinColumn( - (PrimaryKeyJoinColumn) null, - persistentClass.getIdentifier(), - secondaryTables, - propertyHolder, mappings - ); + ejb3JoinColumns = new Ejb3JoinColumn[nbrOfJoinColumns]; + if ( pkColumnsAnn != null ) { + for ( int colIndex = 0; colIndex < nbrOfJoinColumns ; colIndex++ ) { + ejb3JoinColumns[colIndex] = Ejb3JoinColumn.buildJoinColumn( + pkColumnsAnn[colIndex], + null, + persistentClass.getIdentifier(), + secondaryTables, + propertyHolder, mappings + ); + } } else { - ejb3JoinColumns = new Ejb3JoinColumn[nbrOfJoinColumns]; for ( int colIndex = 0; colIndex < nbrOfJoinColumns ; colIndex++ ) { ejb3JoinColumns[colIndex] = Ejb3JoinColumn.buildJoinColumn( - columns[colIndex], + null, + joinColumnsAnn[colIndex], persistentClass.getIdentifier(), secondaryTables, propertyHolder, mappings @@ -378,14 +404,12 @@ } } } + } - for ( Ejb3JoinColumn joinColumn : ejb3JoinColumns ) { - joinColumn.forceNotNull(); - } - Join join = (Join) joins.next(); - bindJoinToPersistentClass( join, ejb3JoinColumns, persistentClass, mappings ); + for ( Ejb3JoinColumn joinColumn : ejb3JoinColumns ) { + joinColumn.forceNotNull(); } - mappings.addJoins( persistentClass, secondaryTables ); + bindJoinToPersistentClass( join, ejb3JoinColumns, persistentClass, mappings ); } public static void bindJoinToPersistentClass( @@ -404,51 +428,80 @@ } public void firstLevelSecondaryTablesBinding( - SecondaryTable secTable, SecondaryTables secTables, PrimaryKeyJoinColumn joinCol, - PrimaryKeyJoinColumns joinCols + SecondaryTable secTable, SecondaryTables secTables ) { if ( secTables != null ) { //loop through it for ( SecondaryTable tab : secTables.value() ) { - bindFirstLevelSecondaryTable( tab, null, null ); + addJoin( tab, null, null, false ); } } else { - if ( secTable != null ) bindFirstLevelSecondaryTable( secTable, joinCol, joinCols ); + if ( secTable != null ) addJoin( secTable, null, null, false ); } } - private void bindFirstLevelSecondaryTable( - SecondaryTable tabAnn, PrimaryKeyJoinColumn joinColAnn, PrimaryKeyJoinColumns joinColsAnn + public Join addJoin(JoinTable joinTable, PropertyHolder holder, boolean noDelayInPkColumnCreation) { + Join join = addJoin( null, joinTable, holder, noDelayInPkColumnCreation ); + join.setOptional( true ); + return join; + } + + /** + * A non null propertyHolder means than we process the Pk creation without delay + */ + private Join addJoin( + SecondaryTable secondaryTable, JoinTable joinTable, PropertyHolder propertyHolder, + boolean noDelayInPkColumnCreation ) { - List uniqueConstraints = new ArrayList(); - if ( tabAnn.uniqueConstraints().length != 0 ) { - for ( UniqueConstraint uc : tabAnn.uniqueConstraints() ) { + Join join = new Join(); + join.setPersistentClass( persistentClass ); + String schema; + String catalog; + String table; + String realTable; + UniqueConstraint[] uniqueCosntraintsAnn; + if ( secondaryTable != null ) { + schema = secondaryTable.schema(); + catalog = secondaryTable.catalog(); + table = secondaryTable.name(); + realTable = mappings.getNamingStrategy().tableName( table ); //always an explicit table name + uniqueCosntraintsAnn = secondaryTable.uniqueConstraints(); + } + else if ( joinTable != null ) { + schema = joinTable.schema(); + catalog = joinTable.catalog(); + table = joinTable.name(); + realTable = mappings.getNamingStrategy().tableName( table ); //always an explicit table name + uniqueCosntraintsAnn = joinTable.uniqueConstraints(); + } + else { + throw new AssertionFailure( "Both JoinTable and SecondaryTable are null" ); + } + List uniqueConstraints = new ArrayList( uniqueCosntraintsAnn == null ? 0 : uniqueCosntraintsAnn.length ); + if ( uniqueCosntraintsAnn != null && uniqueCosntraintsAnn.length != 0 ) { + for ( UniqueConstraint uc : uniqueCosntraintsAnn ) { uniqueConstraints.add( uc.columnNames() ); } } - addSecondaryTable( - tabAnn.schema(), - tabAnn.catalog(), - tabAnn.name(), - uniqueConstraints, - joinColAnn, - joinColsAnn == null ? tabAnn.pkJoinColumns() : joinColsAnn.value() + Table tableMapping = TableBinder.fillTable( + schema, + catalog, + realTable, + table, false, uniqueConstraints, null, null, mappings ); - } + //no check constraints available on joins + join.setTable( tableMapping ); - private void addSecondaryTable( - String schema, String catalog, String table, List uniqueConstraints, PrimaryKeyJoinColumn joinColAnn, - PrimaryKeyJoinColumn[] joinColArray - ) { - Join join = buildJoin( schema, catalog, table, uniqueConstraints, persistentClass, mappings ); //somehow keep joins() for later. //Has to do the work later because it needs persistentClass id! - if ( joinColAnn != null ) { - secondaryTableJoins.put( table, joinColAnn ); + Object joinColumns = null; + //get the appropriate pk columns + if ( secondaryTable != null ) { + joinColumns = secondaryTable.pkJoinColumns(); } - else { - secondaryTableJoins.put( table, joinColArray ); + else if ( joinTable != null ) { + joinColumns = joinTable.joinColumns(); } if ( log.isInfoEnabled() ) { log.info( @@ -456,24 +509,14 @@ .getName() ); } - secondaryTables.put( table, join ); - } + if ( noDelayInPkColumnCreation ) { + createPrimaryColumnsToSecondaryTable( joinColumns, propertyHolder, join ); - private static Join buildJoin( - String schema, String catalog, String table, List uniqueConstraints, PersistentClass persistentClass, - ExtendedMappings mappings - ) { - Join join = new Join(); - join.setPersistentClass( persistentClass ); - String realTableName = mappings.getNamingStrategy().tableName( table ); //always an explicit table name - Table tableMapping = TableBinder.fillTable( - schema, - catalog, - realTableName, - table, false, uniqueConstraints, null, null, mappings - ); - //no check constraints available on joins - join.setTable( tableMapping ); + } + else { + secondaryTables.put( table, join ); + secondaryTableJoins.put( table, joinColumns ); + } return join; } Modified: trunk/HibernateExt/metadata/src/java/org/hibernate/cfg/annotations/TableBinder.java =================================================================== --- trunk/HibernateExt/metadata/src/java/org/hibernate/cfg/annotations/TableBinder.java 2006-04-28 15:44:49 UTC (rev 9832) +++ trunk/HibernateExt/metadata/src/java/org/hibernate/cfg/annotations/TableBinder.java 2006-04-30 04:08:48 UTC (rev 9833) @@ -128,7 +128,10 @@ mappings.addUniqueConstraints( table, uniqueConstraints ); } if ( constraints != null ) table.addCheckConstraint( constraints ); - mappings.addTableBinding( schema, catalog, logicalName, realTableName, denormalizedSuperTable ); + //logicalName is null if we are in the second pass + if ( logicalName != null ) { + mappings.addTableBinding( schema, catalog, logicalName, realTableName, denormalizedSuperTable ); + } return table; } Modified: trunk/HibernateExt/metadata/src/test/org/hibernate/test/annotations/join/Death.java =================================================================== --- trunk/HibernateExt/metadata/src/test/org/hibernate/test/annotations/join/Death.java 2006-04-28 15:44:49 UTC (rev 9832) +++ trunk/HibernateExt/metadata/src/test/org/hibernate/test/annotations/join/Death.java 2006-04-30 04:08:48 UTC (rev 9833) @@ -8,17 +8,17 @@ import javax.persistence.GeneratedValue; import javax.persistence.GenerationType; import javax.persistence.Id; +import javax.persistence.SecondaryTable; import javax.persistence.PrimaryKeyJoinColumn; -import javax.persistence.SecondaryTable; /** * @author Emmanuel Bernard */ @Entity @SecondaryTable( - name = "ExtendedDeath" + name = "ExtendedDeath", + pkJoinColumns = @PrimaryKeyJoinColumn(name = "DEATH_ID") ) -@PrimaryKeyJoinColumn(name = "DEATH_ID") public class Death implements Serializable { @Id @GeneratedValue(strategy = GenerationType.AUTO) Modified: trunk/HibernateExt/metadata/src/test/org/hibernate/test/annotations/join/JoinTest.java =================================================================== --- trunk/HibernateExt/metadata/src/test/org/hibernate/test/annotations/join/JoinTest.java 2006-04-28 15:44:49 UTC (rev 9832) +++ trunk/HibernateExt/metadata/src/test/org/hibernate/test/annotations/join/JoinTest.java 2006-04-30 04:08:48 UTC (rev 9833) @@ -9,6 +9,7 @@ import org.hibernate.Session; import org.hibernate.Transaction; import org.hibernate.criterion.Expression; +import org.hibernate.mapping.Join; import org.hibernate.test.annotations.TestCase; /** @@ -21,6 +22,11 @@ } public void testDefaultValue() throws Exception { + Join join = (Join) getCfg().getClassMapping( Life.class.getName() ).getJoinClosureIterator().next(); + assertEquals( "ExtendedLife", join.getTable().getName() ); + org.hibernate.mapping.Column owner = new org.hibernate.mapping.Column(); + owner.setName( "LIFE_ID" ); + assertTrue( join.getTable().getPrimaryKey().containsColumn( owner ) ); Session s = openSession(); Transaction tx = s.beginTransaction(); Life life = new Life(); @@ -40,6 +46,11 @@ } public void testCompositePK() throws Exception { + Join join = (Join) getCfg().getClassMapping( Dog.class.getName() ).getJoinClosureIterator().next(); + assertEquals( "DogThoroughbred", join.getTable().getName() ); + org.hibernate.mapping.Column owner = new org.hibernate.mapping.Column(); + owner.setName( "OWNER_NAME" ); + assertTrue( join.getTable().getPrimaryKey().containsColumn( owner ) ); Session s = openSession(); Transaction tx = s.beginTransaction(); Dog dog = new Dog(); Added: trunk/HibernateExt/metadata/src/test/org/hibernate/test/annotations/manytoone/BiggestForest.java =================================================================== --- trunk/HibernateExt/metadata/src/test/org/hibernate/test/annotations/manytoone/BiggestForest.java 2006-04-28 15:44:49 UTC (rev 9832) +++ trunk/HibernateExt/metadata/src/test/org/hibernate/test/annotations/manytoone/BiggestForest.java 2006-04-30 04:08:48 UTC (rev 9833) @@ -0,0 +1,34 @@ +//$Id: $ +package org.hibernate.test.annotations.manytoone; + +import javax.persistence.Entity; +import javax.persistence.OneToOne; +import javax.persistence.Id; +import javax.persistence.GeneratedValue; + +/** + * @author Emmanuel Bernard + */ +@Entity +public class BiggestForest { + private Integer id; + private ForestType type; + + @Id @GeneratedValue + public Integer getId() { + return id; + } + + public void setId(Integer id) { + this.id = id; + } + + @OneToOne(mappedBy = "biggestRepresentative") + public ForestType getType() { + return type; + } + + public void setType(ForestType type) { + this.type = type; + } +} Added: trunk/HibernateExt/metadata/src/test/org/hibernate/test/annotations/manytoone/ForestType.java =================================================================== --- trunk/HibernateExt/metadata/src/test/org/hibernate/test/annotations/manytoone/ForestType.java 2006-04-28 15:44:49 UTC (rev 9832) +++ trunk/HibernateExt/metadata/src/test/org/hibernate/test/annotations/manytoone/ForestType.java 2006-04-30 04:08:48 UTC (rev 9833) @@ -0,0 +1,61 @@ +//$Id: $ +package org.hibernate.test.annotations.manytoone; + +import java.util.Set; +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.Id; +import javax.persistence.OneToMany; +import javax.persistence.OneToOne; +import javax.persistence.JoinTable; +import javax.persistence.JoinColumn; + +/** + * @author Emmanuel Bernard + */ +@Entity +public class ForestType { + private Integer id; + private String name; + private Set<TreeType> trees; + private BiggestForest biggestRepresentative; + + @OneToOne + @JoinTable(name="BiggestRepresentativePerForestType", + joinColumns = @JoinColumn(name="forest_type"), + inverseJoinColumns = @JoinColumn(name="forest") + ) + public BiggestForest getBiggestRepresentative() { + return biggestRepresentative; + } + + public void setBiggestRepresentative(BiggestForest biggestRepresentative) { + this.biggestRepresentative = biggestRepresentative; + } + + @OneToMany(mappedBy="forestType") + public Set<TreeType> getTrees() { + return trees; + } + + public void setTrees(Set<TreeType> trees) { + this.trees = trees; + } + + @Id @GeneratedValue + public Integer ... [truncated message content] |
From: <hib...@li...> - 2006-04-28 15:45:11
|
Author: epbernard Date: 2006-04-28 11:44:49 -0400 (Fri, 28 Apr 2006) New Revision: 9832 Modified: trunk/HibernateExt/metadata/src/java/org/hibernate/reflection/java/EJB3OverridenAnnotationReader.java trunk/HibernateExt/metadata/src/test/org/hibernate/test/annotations/collectionelement/CollectionElementTest.java Log: ANN-333 shown @Join* when @CollectionOfElements is used Modified: trunk/HibernateExt/metadata/src/java/org/hibernate/reflection/java/EJB3OverridenAnnotationReader.java =================================================================== --- trunk/HibernateExt/metadata/src/java/org/hibernate/reflection/java/EJB3OverridenAnnotationReader.java 2006-04-28 15:32:01 UTC (rev 9831) +++ trunk/HibernateExt/metadata/src/java/org/hibernate/reflection/java/EJB3OverridenAnnotationReader.java 2006-04-28 15:44:49 UTC (rev 9832) @@ -77,6 +77,7 @@ import org.hibernate.annotationfactory.AnnotationFactory; import org.hibernate.annotations.AccessType; import org.hibernate.annotations.Columns; +import org.hibernate.annotations.CollectionOfElements; import org.hibernate.reflection.Filter; import org.hibernate.reflection.java.xml.XMLContext; import org.hibernate.util.ReflectHelper; @@ -479,6 +480,40 @@ annotation = super.getAnnotation( Columns.class ); if ( annotation != null ) annotationList.add( annotation ); } + else if ( super.isAnnotationPresent( CollectionOfElements.class ) ) { + annotation = overridesDefaultsInJoinTable( defaults ); + if ( annotation != null ) annotationList.add( annotation ); + annotation = super.getAnnotation( JoinColumn.class ); + if ( annotation != null ) annotationList.add( annotation ); + annotation = super.getAnnotation( JoinColumns.class ); + if ( annotation != null ) annotationList.add( annotation ); + annotation = super.getAnnotation( PrimaryKeyJoinColumn.class ); + if ( annotation != null ) annotationList.add( annotation ); + annotation = super.getAnnotation( PrimaryKeyJoinColumns.class ); + if ( annotation != null ) annotationList.add( annotation ); + annotation = super.getAnnotation( MapKey.class ); + if ( annotation != null ) annotationList.add( annotation ); + annotation = super.getAnnotation( OrderBy.class ); + if ( annotation != null ) annotationList.add( annotation ); + annotation = super.getAnnotation( AttributeOverride.class ); + if ( annotation != null ) annotationList.add( annotation ); + annotation = super.getAnnotation( AttributeOverrides.class ); + if ( annotation != null ) annotationList.add( annotation ); + annotation = super.getAnnotation( AssociationOverride.class ); + if ( annotation != null ) annotationList.add( annotation ); + annotation = super.getAnnotation( AssociationOverrides.class ); + if ( annotation != null ) annotationList.add( annotation ); + annotation = super.getAnnotation( Lob.class ); + if ( annotation != null ) annotationList.add( annotation ); + annotation = super.getAnnotation( Enumerated.class ); + if ( annotation != null ) annotationList.add( annotation ); + annotation = super.getAnnotation( Temporal.class ); + if ( annotation != null ) annotationList.add( annotation ); + annotation = super.getAnnotation( Column.class ); + if ( annotation != null ) annotationList.add( annotation ); + annotation = super.getAnnotation( Columns.class ); + if ( annotation != null ) annotationList.add( annotation ); + } } } Modified: trunk/HibernateExt/metadata/src/test/org/hibernate/test/annotations/collectionelement/CollectionElementTest.java =================================================================== --- trunk/HibernateExt/metadata/src/test/org/hibernate/test/annotations/collectionelement/CollectionElementTest.java 2006-04-28 15:32:01 UTC (rev 9831) +++ trunk/HibernateExt/metadata/src/test/org/hibernate/test/annotations/collectionelement/CollectionElementTest.java 2006-04-28 15:44:49 UTC (rev 9832) @@ -12,6 +12,10 @@ public class CollectionElementTest extends TestCase { public void testSimpleElement() throws Exception { + assertEquals( + "BoyFavoriteNumbers", + getCfg().getCollectionMapping( Boy.class.getName() + '.' + "favoriteNumbers" ).getCollectionTable().getName() + ); Session s = openSession(); s.getTransaction().begin(); Boy boy = new Boy(); |
From: <hib...@li...> - 2006-04-28 15:32:16
|
Author: epbernard Date: 2006-04-28 11:32:01 -0400 (Fri, 28 Apr 2006) New Revision: 9831 Modified: trunk/HibernateExt/metadata/src/java/org/hibernate/cfg/AnnotationBinder.java trunk/HibernateExt/metadata/src/java/org/hibernate/cfg/annotations/ArrayBinder.java trunk/HibernateExt/metadata/src/java/org/hibernate/cfg/annotations/CollectionBinder.java trunk/HibernateExt/metadata/src/java/org/hibernate/cfg/annotations/ListBinder.java trunk/HibernateExt/metadata/src/java/org/hibernate/cfg/annotations/MapBinder.java Log: ANN-224 @Fetch(FetchMode) @LazyToOne(LazyToOneOption) @LazyCollection(LazyCollectionOption) Clean up the old fetching mechanism Modified: trunk/HibernateExt/metadata/src/java/org/hibernate/cfg/AnnotationBinder.java =================================================================== --- trunk/HibernateExt/metadata/src/java/org/hibernate/cfg/AnnotationBinder.java 2006-04-28 15:16:41 UTC (rev 9830) +++ trunk/HibernateExt/metadata/src/java/org/hibernate/cfg/AnnotationBinder.java 2006-04-28 15:32:01 UTC (rev 9831) @@ -1335,7 +1335,6 @@ collectionBinder.setTargetEntity( mappings.getReflectionManager().toXClass( oneToManyAnn.targetEntity() ) ); - collectionBinder.setFetchType( oneToManyAnn.fetch() ); collectionBinder.setCascadeStrategy( getCascadeStrategy( oneToManyAnn.cascade(), hibernateCascade ) ); collectionBinder.setOneToMany( true ); } @@ -1350,7 +1349,6 @@ collectionBinder.setTargetEntity( mappings.getReflectionManager().toXClass( collectionOfElementsAnn.targetElement() ) ); - collectionBinder.setFetchType( collectionOfElementsAnn.fetch() ); //collectionBinder.setCascadeStrategy( getCascadeStrategy( embeddedCollectionAnn.cascade(), hibernateCascade ) ); collectionBinder.setOneToMany( true ); } @@ -1359,7 +1357,6 @@ collectionBinder.setTargetEntity( mappings.getReflectionManager().toXClass( manyToManyAnn.targetEntity() ) ); - collectionBinder.setFetchType( manyToManyAnn.fetch() ); collectionBinder.setCascadeStrategy( getCascadeStrategy( manyToManyAnn.cascade(), hibernateCascade ) ); collectionBinder.setOneToMany( false ); } Modified: trunk/HibernateExt/metadata/src/java/org/hibernate/cfg/annotations/ArrayBinder.java =================================================================== --- trunk/HibernateExt/metadata/src/java/org/hibernate/cfg/annotations/ArrayBinder.java 2006-04-28 15:16:41 UTC (rev 9830) +++ trunk/HibernateExt/metadata/src/java/org/hibernate/cfg/annotations/ArrayBinder.java 2006-04-28 15:32:01 UTC (rev 9831) @@ -1,8 +1,5 @@ package org.hibernate.cfg.annotations; -import javax.persistence.FetchType; - -import org.hibernate.FetchMode; import org.hibernate.mapping.Array; import org.hibernate.mapping.Collection; import org.hibernate.mapping.PersistentClass; @@ -17,11 +14,6 @@ public ArrayBinder() { } - public void setFetchType(FetchType fetch) { - //workaround to hibernate3 bug, remove it once fixed - fetchMode = FetchMode.SELECT; - } - protected Collection createCollection(PersistentClass persistentClass) { return new Array( persistentClass ); } Modified: trunk/HibernateExt/metadata/src/java/org/hibernate/cfg/annotations/CollectionBinder.java =================================================================== --- trunk/HibernateExt/metadata/src/java/org/hibernate/cfg/annotations/CollectionBinder.java 2006-04-28 15:16:41 UTC (rev 9830) +++ trunk/HibernateExt/metadata/src/java/org/hibernate/cfg/annotations/CollectionBinder.java 2006-04-28 15:32:01 UTC (rev 9831) @@ -75,7 +75,6 @@ protected Collection collection; protected String propertyName; - FetchMode fetchMode; PropertyHolder propertyHolder; int batchSize; String where; @@ -343,7 +342,6 @@ elementColumns, mapKeyColumns, isEmbedded, property, collType, - fetchMode, ignoreNotFound, oneToMany, tableBinder, mappings ); @@ -448,7 +446,7 @@ final Ejb3Column[] elementColumns, final Ejb3Column[] mapKeyColumns, final boolean isEmbedded, final XProperty property, final String collType, - final FetchMode fetchMode, final boolean ignoreNotFound, final boolean unique, + final boolean ignoreNotFound, final boolean unique, final TableBinder assocTableBinder, final ExtendedMappings mappings ) { @@ -458,7 +456,7 @@ throws MappingException { bindStarToManySecondPass( persistentClasses, collType, fkJoinColumns, keyColumns, inverseColumns, elementColumns, - isEmbedded, property, fetchMode, unique, assocTableBinder, ignoreNotFound, mappings + isEmbedded, property, unique, assocTableBinder, ignoreNotFound, mappings ); } @@ -472,7 +470,7 @@ Map persistentClasses, String collType, Ejb3JoinColumn[] fkJoinColumns, Ejb3JoinColumn[] keyColumns, Ejb3JoinColumn[] inverseColumns, Ejb3Column[] elementColumns, boolean isEmbedded, - XProperty property, FetchMode fetchMode, boolean unique, + XProperty property, boolean unique, TableBinder associationTableBinder, boolean ignoreNotFound, ExtendedMappings mappings ) { boolean isEntity = persistentClasses.containsKey( collType ); @@ -502,7 +500,6 @@ inverseColumns, elementColumns, isEmbedded, collType, - fetchMode, ignoreNotFound, unique, cascadeDeleteEnabled, associationTableBinder, property, mappings @@ -579,15 +576,6 @@ } } - public void setFetchType(FetchType fetch) { - if ( fetch == FetchType.EAGER ) { - fetchMode = FetchMode.JOIN; - } - else { - fetchMode = FetchMode.SELECT; - } - } - public void addFilter(String name, String condition) { filters.put( name, condition ); } @@ -747,7 +735,6 @@ Ejb3Column[] elementColumns, boolean isEmbedded, String collType, - FetchMode fetchMode, boolean ignoreNotFound, boolean unique, boolean cascadeDeleteEnabled, TableBinder associationTableBinder, XProperty property, ExtendedMappings mappings Modified: trunk/HibernateExt/metadata/src/java/org/hibernate/cfg/annotations/ListBinder.java =================================================================== --- trunk/HibernateExt/metadata/src/java/org/hibernate/cfg/annotations/ListBinder.java 2006-04-28 15:16:41 UTC (rev 9830) +++ trunk/HibernateExt/metadata/src/java/org/hibernate/cfg/annotations/ListBinder.java 2006-04-28 15:32:01 UTC (rev 9831) @@ -5,7 +5,6 @@ import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.hibernate.AnnotationException; -import org.hibernate.FetchMode; import org.hibernate.MappingException; import org.hibernate.annotations.OrderBy; import org.hibernate.annotations.Sort; @@ -56,7 +55,7 @@ final Ejb3Column[] elementColumns, Ejb3Column[] mapKeyColumns, final boolean isEmbedded, final XProperty property, final String collType, - final FetchMode fetchMode, final boolean ignoreNotFound, final boolean unique, + final boolean ignoreNotFound, final boolean unique, final TableBinder assocTableBinder, final ExtendedMappings mappings ) { return new CollectionSecondPass( mappings, ListBinder.this.collection ) { @@ -64,7 +63,7 @@ throws MappingException { bindStarToManySecondPass( persistentClasses, collType, fkJoinColumns, keyColumns, inverseColumns, elementColumns, - isEmbedded, property, fetchMode, unique, assocTableBinder, ignoreNotFound, mappings + isEmbedded, property, unique, assocTableBinder, ignoreNotFound, mappings ); bindIndex( mappings ); } Modified: trunk/HibernateExt/metadata/src/java/org/hibernate/cfg/annotations/MapBinder.java =================================================================== --- trunk/HibernateExt/metadata/src/java/org/hibernate/cfg/annotations/MapBinder.java 2006-04-28 15:16:41 UTC (rev 9830) +++ trunk/HibernateExt/metadata/src/java/org/hibernate/cfg/annotations/MapBinder.java 2006-04-28 15:32:01 UTC (rev 9831) @@ -57,7 +57,7 @@ final Ejb3Column[] elementColumns, final Ejb3Column[] mapKeyColumns, final boolean isEmbedded, final XProperty property, final String collType, - final FetchMode fetchMode, final boolean ignoreNotFound, final boolean unique, + final boolean ignoreNotFound, final boolean unique, final TableBinder assocTableBinder, final ExtendedMappings mappings ) { return new CollectionSecondPass( mappings, MapBinder.this.collection ) { @@ -65,7 +65,7 @@ throws MappingException { bindStarToManySecondPass( persistentClasses, collType, fkJoinColumns, keyColumns, inverseColumns, elementColumns, - isEmbedded, property, fetchMode, unique, assocTableBinder, ignoreNotFound, mappings + isEmbedded, property, unique, assocTableBinder, ignoreNotFound, mappings ); bindKeyFromAssociationTable( collType, persistentClasses, mapKeyPropertyName, property, ignoreNotFound, isEmbedded, mappings, |
Author: epbernard Date: 2006-04-28 11:16:41 -0400 (Fri, 28 Apr 2006) New Revision: 9830 Added: trunk/HibernateExt/metadata/src/java/org/hibernate/annotations/Fetch.java trunk/HibernateExt/metadata/src/java/org/hibernate/annotations/FetchMode.java trunk/HibernateExt/metadata/src/java/org/hibernate/annotations/LazyCollection.java trunk/HibernateExt/metadata/src/java/org/hibernate/annotations/LazyCollectionOption.java trunk/HibernateExt/metadata/src/java/org/hibernate/annotations/LazyToOne.java trunk/HibernateExt/metadata/src/java/org/hibernate/annotations/LazyToOneOption.java Modified: trunk/HibernateExt/metadata/doc/reference/en/modules/entity.xml trunk/HibernateExt/metadata/src/java/org/hibernate/cfg/AnnotationBinder.java trunk/HibernateExt/metadata/src/java/org/hibernate/cfg/annotations/CollectionBinder.java trunk/HibernateExt/metadata/src/test/org/hibernate/test/annotations/fetch/FetchingTest.java trunk/HibernateExt/metadata/src/test/org/hibernate/test/annotations/fetch/Person.java trunk/HibernateExt/metadata/src/test/org/hibernate/test/annotations/fetch/Stay.java Log: ANN-224 @Fetch(FetchMode) @LazyToOne(LazyToOneOption) @LazyCollection(LazyCollectionOption) Modified: trunk/HibernateExt/metadata/doc/reference/en/modules/entity.xml =================================================================== --- trunk/HibernateExt/metadata/doc/reference/en/modules/entity.xml 2006-04-28 14:11:16 UTC (rev 9829) +++ trunk/HibernateExt/metadata/doc/reference/en/modules/entity.xml 2006-04-28 15:16:41 UTC (rev 9830) @@ -2556,6 +2556,106 @@ <para>In this case Hibernate generates a cascade delete constraint at the database level.</para> + + <sect3> + <title>Lazy options and fetching modes</title> + + <para>EJB3 comes with the <literal>fetch</literal> option to define + lazy loading and fetching modes, however Hibernate has a much more + option set in this area. To fine tune the lazy loading and fetching + strategies, some additional annotations have been introduced: </para> + + <itemizedlist> + <listitem> + <para><literal>@LazyToOne</literal>: defines the lazyness option + on <literal>@ManyToOne</literal> and <literal>@OneToOne</literal> + associations. <literal>LazyToOneOption</literal> can be + <literal>PROXY</literal> (ie use a proxy based lazy loading), + <literal>NO_PROXY</literal> (use a bytecode enhancement based lazy + loading - note that build time bytecode processing is necessary) + and <literal>FALSE</literal> (association not lazy)</para> + </listitem> + + <listitem> + <para><literal>@LazyCollection</literal>: defines the lazyness + option on <literal>@ManyTo</literal>Many and + <literal>@OneToMany</literal> associations. LazyCollectionOption + can be <literal>TRUE</literal> (the collection is lazy and will be + loaded when its state is accessed), <literal>EXTRA</literal> (the + collection is lazy and all operations will try to avoid the + collection loading, this is especially useful for huge collections + when loading all the elements is not necessary) and FALSE + (association not lazy)</para> + </listitem> + + <listitem> + <para> <literal>@Fetch</literal>: defines the fetching strategy + used to load the association. <literal>FetchMode</literal> can be + <literal>SELECT</literal> (a select is triggered when the + association needs to be loaded), <literal>SUBSELECT</literal> + (only available for collections, use a subselect strategy - please + refers to the Hibernate Reference Documentation for more + information) or <literal>JOIN</literal> (use a SQL JOIN to load + the association while loading the owner entity). + <literal>JOIN</literal> overrides any lazy attribute (an + association loaded through a <literal>JOIN</literal> strategy + cannot be lazy).</para> + </listitem> + </itemizedlist> + + <para>The Hibernate annotations overrides the EJB3 fetching + options.</para> + + <table> + <title>Lazy and fetch options equivalent</title> + + <tgroup cols="3"> + <thead> + <row> + <entry>Annotations</entry> + + <entry>Lazy</entry> + + <entry>Fetch</entry> + </row> + </thead> + + <tbody> + <row> + <entry>@[One|Many]ToOne](fetch=FetchType.LAZY)</entry> + + <entry>@LazyToOne(PROXY)</entry> + + <entry>@Fetch(SELECT)</entry> + </row> + + <row> + <entry>@[One|Many]ToOne](fetch=FetchType.EAGER)</entry> + + <entry>@LazyToOne(FALSE)</entry> + + <entry>@Fetch(JOIN)</entry> + </row> + + <row> + <entry>@ManyTo[One|Many](fetch=FetchType.LAZY)</entry> + + <entry>@LazyCollection(TRUE)</entry> + + <entry>@Fetch(SELECT)</entry> + </row> + + <row> + <entry>@ManyTo[One|Many](fetch=FetchType.EAGER)</entry> + + <entry>@LazyCollection(FALSE)</entry> + + <entry>@Fetch(JOIN)</entry> + </row> + </tbody> + </tgroup> + </table> + </sect3> </sect2> <sect2 id="entity-hibspec-collection" revision="2"> Added: trunk/HibernateExt/metadata/src/java/org/hibernate/annotations/Fetch.java =================================================================== --- trunk/HibernateExt/metadata/src/java/org/hibernate/annotations/Fetch.java 2006-04-28 14:11:16 UTC (rev 9829) +++ trunk/HibernateExt/metadata/src/java/org/hibernate/annotations/Fetch.java 2006-04-28 15:16:41 UTC (rev 9830) @@ -0,0 +1,18 @@ +//$Id: $ +package org.hibernate.annotations; + +import java.lang.annotation.Target; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + +/** + * Define the fetching strategy used for the given association + * + * @author Emmanuel Bernard + */ +@Target({ElementType.METHOD, ElementType.FIELD}) +@Retention(RetentionPolicy.RUNTIME) +public @interface Fetch { + FetchMode value(); +} Added: trunk/HibernateExt/metadata/src/java/org/hibernate/annotations/FetchMode.java =================================================================== --- trunk/HibernateExt/metadata/src/java/org/hibernate/annotations/FetchMode.java 2006-04-28 14:11:16 UTC (rev 9829) +++ trunk/HibernateExt/metadata/src/java/org/hibernate/annotations/FetchMode.java 2006-04-28 15:16:41 UTC (rev 9830) @@ -0,0 +1,22 @@ +//$Id: $ +package org.hibernate.annotations; + +/** + * Fetch options on associations + * + * @author Emmanuel Bernard + */ +public enum FetchMode { + /** + * use a select for each individual entity, collection, or join load + */ + SELECT, + /** + * use an outer join to load the related entities, collections or joins + */ + JOIN, + /** + * use a subselect query to load the additional collections + */ + SUBSELECT +} Added: trunk/HibernateExt/metadata/src/java/org/hibernate/annotations/LazyCollection.java =================================================================== --- trunk/HibernateExt/metadata/src/java/org/hibernate/annotations/LazyCollection.java 2006-04-28 14:11:16 UTC (rev 9829) +++ trunk/HibernateExt/metadata/src/java/org/hibernate/annotations/LazyCollection.java 2006-04-28 15:16:41 UTC (rev 9830) @@ -0,0 +1,18 @@ +//$Id: $ +package org.hibernate.annotations; + +import java.lang.annotation.Target; +import java.lang.annotation.Retention; +import java.lang.annotation.ElementType; +import java.lang.annotation.RetentionPolicy; + +/** + * Define the lazy status of a collection + * + * @author Emmanuel Bernard + */ +@Target({ElementType.METHOD, ElementType.FIELD}) +@Retention(RetentionPolicy.RUNTIME) +public @interface LazyCollection { + LazyCollectionOption value(); +} Added: trunk/HibernateExt/metadata/src/java/org/hibernate/annotations/LazyCollectionOption.java =================================================================== --- trunk/HibernateExt/metadata/src/java/org/hibernate/annotations/LazyCollectionOption.java 2006-04-28 14:11:16 UTC (rev 9829) +++ trunk/HibernateExt/metadata/src/java/org/hibernate/annotations/LazyCollectionOption.java 2006-04-28 15:16:41 UTC (rev 9830) @@ -0,0 +1,16 @@ +//$Id: $ +package org.hibernate.annotations; + +/** + * Lazy options available for a collection + * + * @author Emmanuel Bernard + */ +public enum LazyCollectionOption { + /** eagerly load it */ + FALSE, + /** load it when the state is requested */ + TRUE, + /** prefer extra queries over fill collection loading */ + EXTRA +} Added: trunk/HibernateExt/metadata/src/java/org/hibernate/annotations/LazyToOne.java =================================================================== --- trunk/HibernateExt/metadata/src/java/org/hibernate/annotations/LazyToOne.java 2006-04-28 14:11:16 UTC (rev 9829) +++ trunk/HibernateExt/metadata/src/java/org/hibernate/annotations/LazyToOne.java 2006-04-28 15:16:41 UTC (rev 9830) @@ -0,0 +1,19 @@ +//$Id: $ +package org.hibernate.annotations; + +import java.lang.annotation.Target; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + +/** + * Define the lazy status of a ToOne association + * (ie OneToOne or ManyToOne) + * + * @author Emmanuel Bernard + */ +@Target({ElementType.METHOD, ElementType.FIELD}) +@Retention(RetentionPolicy.RUNTIME) +public @interface LazyToOne { + LazyToOneOption value(); +} Added: trunk/HibernateExt/metadata/src/java/org/hibernate/annotations/LazyToOneOption.java =================================================================== --- trunk/HibernateExt/metadata/src/java/org/hibernate/annotations/LazyToOneOption.java 2006-04-28 14:11:16 UTC (rev 9829) +++ trunk/HibernateExt/metadata/src/java/org/hibernate/annotations/LazyToOneOption.java 2006-04-28 15:16:41 UTC (rev 9830) @@ -0,0 +1,23 @@ +//$Id: $ +package org.hibernate.annotations; + +/** + * Lazy options available for a ToOne association + * + * @author Emmanuel Bernard + */ +public enum LazyToOneOption { + /** eagerly load the association */ + FALSE, + /** + * Lazy, give back a proxy which will be loaded when the state is requested + * This should be the prefered option + */ + PROXY, + /** Lazy, give back the real object loaded when a reference is requested + * (Bytecode enhancement is mandatory for this option, fall back to PROXY + * if the class is not enhanced) + * This option should be avoided unless you can't afford the use of proxies + */ + NO_PROXY +} Modified: trunk/HibernateExt/metadata/src/java/org/hibernate/cfg/AnnotationBinder.java =================================================================== --- trunk/HibernateExt/metadata/src/java/org/hibernate/cfg/AnnotationBinder.java 2006-04-28 14:11:16 UTC (rev 9829) +++ trunk/HibernateExt/metadata/src/java/org/hibernate/cfg/AnnotationBinder.java 2006-04-28 15:16:41 UTC (rev 9830) @@ -82,6 +82,9 @@ import org.hibernate.annotations.TypeDefs; import org.hibernate.annotations.Where; import org.hibernate.annotations.Parent; +import org.hibernate.annotations.LazyToOne; +import org.hibernate.annotations.Fetch; +import org.hibernate.annotations.LazyToOneOption; import org.hibernate.cfg.annotations.CollectionBinder; import org.hibernate.cfg.annotations.EntityBinder; import org.hibernate.cfg.annotations.Nullability; @@ -108,6 +111,7 @@ import org.hibernate.mapping.Subclass; import org.hibernate.mapping.Table; import org.hibernate.mapping.UnionSubclass; +import org.hibernate.mapping.ToOne; import org.hibernate.persister.entity.JoinedSubclassEntityPersister; import org.hibernate.persister.entity.SingleTableEntityPersister; import org.hibernate.persister.entity.UnionSubclassEntityPersister; @@ -1016,7 +1020,7 @@ ); } - //set default values in needed + //set default values if needed if ( joinColumns == null && ( property.isAnnotationPresent( ManyToOne.class ) || property.isAnnotationPresent( OneToOne.class ) ) @@ -1178,7 +1182,6 @@ getCascadeStrategy( ann.cascade(), hibernateCascade ), joinColumns, ann.optional(), - getFetchMode( ann.fetch() ), ignoreNotFound, onDeleteCascade, mappings.getReflectionManager().toXClass( ann.targetEntity() ), propertyHolder, @@ -1662,7 +1665,7 @@ } private static void bindManyToOne( - String cascadeStrategy, Ejb3JoinColumn[] columns, boolean optional, FetchMode fetchMode, + String cascadeStrategy, Ejb3JoinColumn[] columns, boolean optional, boolean ignoreNotFound, boolean cascadeOnDelete, XClass targetEntity, PropertyHolder propertyHolder, PropertyData inferredData, boolean unique, boolean isIdentifierMapper, ExtendedMappings mappings @@ -1675,10 +1678,11 @@ else { value.setReferencedEntityName( targetEntity.getName() ); } - value.setFetchMode( fetchMode ); + defineFetchingStrategy( value, inferredData.getProperty() ); + //value.setFetchMode( fetchMode ); value.setIgnoreNotFound( ignoreNotFound ); value.setCascadeDeleteEnabled( cascadeOnDelete ); - value.setLazy( fetchMode != FetchMode.JOIN ); + //value.setLazy( fetchMode != FetchMode.JOIN ); if ( !optional ) { for ( Ejb3JoinColumn column : columns ) { column.setNullable( false ); @@ -1717,6 +1721,50 @@ propertyHolder.addProperty( prop, columns ); } + private static void defineFetchingStrategy(ToOne toOne, XProperty property) { + LazyToOne lazy = property.getAnnotation( LazyToOne.class ); + Fetch fetch = property.getAnnotation( Fetch.class ); + ManyToOne manyToOne = property.getAnnotation( ManyToOne.class ); + OneToOne oneToOne = property.getAnnotation( OneToOne.class ); + FetchType fetchType; + if (manyToOne != null) { + fetchType = manyToOne.fetch(); + } + else if (oneToOne != null) { + fetchType = oneToOne.fetch(); + } + else { + throw new AssertionFailure( "Define fetch strategy on a property not annotated with @OneToMany nor @OneToOne"); + } + if (lazy != null) { + toOne.setLazy( ! (lazy.value() == LazyToOneOption.FALSE) ); + toOne.setUnwrapProxy( (lazy.value() == LazyToOneOption.NO_PROXY) ); + } + else { + toOne.setLazy( fetchType == FetchType.LAZY ); + toOne.setUnwrapProxy( false ); + } + if (fetch != null) { + if ( fetch.value() == org.hibernate.annotations.FetchMode.JOIN ) { + toOne.setFetchMode( FetchMode.JOIN ); + toOne.setLazy( false ); + toOne.setUnwrapProxy( false ); + } + else if ( fetch.value() == org.hibernate.annotations.FetchMode.SELECT ) { + toOne.setFetchMode( FetchMode.SELECT ); + } + else if ( fetch.value() == org.hibernate.annotations.FetchMode.SUBSELECT ) { + throw new AnnotationException( "Use of FetchMode.SUBSELECT not allowed on ToOne associations"); + } + else { + throw new AssertionFailure( "Unknown FetchMode: " + fetch.value() ); + } + } + else { + toOne.setFetchMode( getFetchMode( fetchType ) ); + } + } + private static void bindOneToOne( String cascadeStrategy, Ejb3JoinColumn[] columns, @@ -1763,9 +1811,10 @@ else { value.setReferencedEntityName( targetEntity.getName() ); } - value.setFetchMode( fetchMode ); + defineFetchingStrategy( value, inferredData.getProperty() ); + //value.setFetchMode( fetchMode ); value.setCascadeDeleteEnabled( cascadeOnDelete ); - value.setLazy( fetchMode != FetchMode.JOIN ); + //value.setLazy( fetchMode != FetchMode.JOIN ); if ( !optional ) value.setConstrained( true ); value.setForeignKeyType( @@ -1809,7 +1858,7 @@ else { //has a FK on the table bindManyToOne( - cascadeStrategy, columns, optional, fetchMode, ignoreNotFound, cascadeOnDelete, + cascadeStrategy, columns, optional, ignoreNotFound, cascadeOnDelete, targetEntity, propertyHolder, inferredData, true, isIdentifierMapper, mappings ); @@ -1911,7 +1960,7 @@ return cascade.length() > 0 ? cascade.substring( 1 ) : "none"; } - private static FetchMode getFetchMode(FetchType fetch) { + public static FetchMode getFetchMode(FetchType fetch) { if ( fetch == FetchType.EAGER ) { return FetchMode.JOIN; } Modified: trunk/HibernateExt/metadata/src/java/org/hibernate/cfg/annotations/CollectionBinder.java =================================================================== --- trunk/HibernateExt/metadata/src/java/org/hibernate/cfg/annotations/CollectionBinder.java 2006-04-28 14:11:16 UTC (rev 9829) +++ trunk/HibernateExt/metadata/src/java/org/hibernate/cfg/annotations/CollectionBinder.java 2006-04-28 15:16:41 UTC (rev 9830) @@ -11,7 +11,9 @@ import javax.persistence.AttributeOverrides; import javax.persistence.Embeddable; import javax.persistence.FetchType; +import javax.persistence.ManyToMany; import javax.persistence.MapKey; +import javax.persistence.OneToMany; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; @@ -23,6 +25,9 @@ import org.hibernate.annotations.BatchSize; import org.hibernate.annotations.Cache; import org.hibernate.annotations.CollectionOfElements; +import org.hibernate.annotations.Fetch; +import org.hibernate.annotations.LazyCollection; +import org.hibernate.annotations.LazyCollectionOption; import org.hibernate.annotations.OrderBy; import org.hibernate.annotations.Sort; import org.hibernate.annotations.SortType; @@ -260,8 +265,9 @@ } //set laziness - collection.setFetchMode( fetchMode ); - collection.setLazy( fetchMode == FetchMode.SELECT ); + defineFetchingStrategy(); + //collection.setFetchMode( fetchMode ); + //collection.setLazy( fetchMode == FetchMode.SELECT ); collection.setBatchSize( batchSize ); if ( orderBy != null && hqlOrderBy != null ) { throw new AnnotationException( @@ -371,6 +377,55 @@ propertyHolder.addProperty( prop ); } + private void defineFetchingStrategy() { + LazyCollection lazy = property.getAnnotation( LazyCollection.class ); + Fetch fetch = property.getAnnotation( Fetch.class ); + OneToMany oneToMany = property.getAnnotation( OneToMany.class ); + ManyToMany manyToMany = property.getAnnotation( ManyToMany.class ); + CollectionOfElements elements = property.getAnnotation( CollectionOfElements.class ); + FetchType fetchType; + if (oneToMany != null) { + fetchType = oneToMany.fetch(); + } + else if (manyToMany != null) { + fetchType = manyToMany.fetch(); + } + else if (elements != null) { + fetchType = elements.fetch(); + } + else { + throw new AssertionFailure( "Define fetch strategy on a property not annotated with @ManyToOne nor @OneToMany nor @CollectionOfElements"); + } + if (lazy != null) { + collection.setLazy( ! (lazy.value() == LazyCollectionOption.FALSE) ); + collection.setExtraLazy( lazy.value() == LazyCollectionOption.EXTRA ); + } + else { + collection.setLazy( fetchType == FetchType.LAZY ); + collection.setExtraLazy( false ); + } + if (fetch != null) { + if ( fetch.value() == org.hibernate.annotations.FetchMode.JOIN ) { + collection.setFetchMode( FetchMode.JOIN ); + collection.setLazy( false ); + } + else if ( fetch.value() == org.hibernate.annotations.FetchMode.SELECT ) { + collection.setFetchMode( FetchMode.SELECT ); + } + else if ( fetch.value() == org.hibernate.annotations.FetchMode.SUBSELECT ) { + collection.setFetchMode( FetchMode.SELECT ); + collection.setSubselectLoadable(true); + collection.getOwner().setSubselectLoadableCollections(true); + } + else { + throw new AssertionFailure( "Unknown FetchMode: " + fetch.value() ); + } + } + else { + collection.setFetchMode( AnnotationBinder.getFetchMode( fetchType ) ); + } + } + private XClass getCollectionType() { if ( AnnotationBinder.isDefault( targetEntity, mappings ) ) { if ( collectionType != null ) { Modified: trunk/HibernateExt/metadata/src/test/org/hibernate/test/annotations/fetch/FetchingTest.java =================================================================== --- trunk/HibernateExt/metadata/src/test/org/hibernate/test/annotations/fetch/FetchingTest.java 2006-04-28 14:11:16 UTC (rev 9829) +++ trunk/HibernateExt/metadata/src/test/org/hibernate/test/annotations/fetch/FetchingTest.java 2006-04-28 15:16:41 UTC (rev 9830) @@ -32,6 +32,41 @@ s.close(); } + public void testHibernateFetchingLazy() throws Exception { + Session s; + Transaction tx; + s = openSession(); + tx = s.beginTransaction(); + Person p = new Person( "Gavin", "King", "JBoss Inc" ); + Stay stay = new Stay( null, new Date(), new Date(), "A380", "Blah", "Blah" ); + Stay stay2 = new Stay( null, new Date(), new Date(), "A320", "Blah", "Blah" ); + Stay stay3 = new Stay( null, new Date(), new Date(), "A340", "Blah", "Blah" ); + stay.setOldPerson( p ); + stay2.setVeryOldPerson( p ); + stay3.setVeryOldPerson( p ); + p.addOldStay( stay ); + p.addVeryOldStay( stay2 ); + p.addVeryOldStay( stay3 ); + s.persist( p ); + tx.commit(); + s.clear(); + tx = s.beginTransaction(); + p = (Person) s.createQuery( "from Person p where p.firstName = :name" ) + .setParameter( "name", "Gavin" ).uniqueResult(); + assertFalse( Hibernate.isInitialized( p.getOldStays() ) ); + assertEquals( 1, p.getOldStays().size() ); + assertFalse( "lazy extra is failing", Hibernate.isInitialized( p.getOldStays() ) ); + s.clear(); + stay = (Stay) s.get( Stay.class, stay.getId() ); + assertTrue( ! Hibernate.isInitialized( stay.getOldPerson() ) ); + s.clear(); + stay3 = (Stay) s.get( Stay.class, stay3.getId() ); + assertTrue( "FetchMode.JOIN should overrides lazy options", Hibernate.isInitialized( stay3.getVeryOldPerson() ) ); + s.delete( stay3.getVeryOldPerson() ); + tx.commit(); + s.close(); + } + public FetchingTest(String x) { super( x ); } Modified: trunk/HibernateExt/metadata/src/test/org/hibernate/test/annotations/fetch/Person.java =================================================================== --- trunk/HibernateExt/metadata/src/test/org/hibernate/test/annotations/fetch/Person.java 2006-04-28 14:11:16 UTC (rev 9829) +++ trunk/HibernateExt/metadata/src/test/org/hibernate/test/annotations/fetch/Person.java 2006-04-28 15:16:41 UTC (rev 9830) @@ -14,7 +14,12 @@ import javax.persistence.OneToMany; import javax.persistence.Table; +import org.hibernate.annotations.Fetch; +import org.hibernate.annotations.FetchMode; +import org.hibernate.annotations.LazyCollection; +import org.hibernate.annotations.LazyCollectionOption; + /** * @author Emmanuel Bernard */ @@ -27,8 +32,9 @@ private String firstName; private String lastName; private String companyName; - private Collection<Stay> stays; + private Collection<Stay> oldStays; + private Collection<Stay> veryOldStays; // constructors public Person() { @@ -86,7 +92,28 @@ this.stays = stays; } + @OneToMany(cascade=CascadeType.ALL, mappedBy = "oldPerson") + @LazyCollection(LazyCollectionOption.EXTRA) + @Fetch(FetchMode.SUBSELECT) + public Collection<Stay> getOldStays() { + return oldStays; + } + public void setOldStays(Collection<Stay> oldStays) { + this.oldStays = oldStays; + } + + @OneToMany(cascade=CascadeType.ALL, mappedBy = "veryOldPerson") + @Fetch(FetchMode.SELECT) + public Collection<Stay> getVeryOldStays() { + return veryOldStays; + } + + public void setVeryOldStays(Collection<Stay> veryOldStays) { + this.veryOldStays = veryOldStays; + } + + // business logic public void addStay(Date startDate, Date endDate, String vessel, String authoriser, String comments) { Stay stay = new Stay( this, startDate, endDate, vessel, authoriser, comments ); @@ -102,4 +129,34 @@ this.stays = stays; } + + public void addOldStay(Date startDate, Date endDate, String vessel, String authoriser, String comments) { + Stay stay = new Stay( this, startDate, endDate, vessel, authoriser, comments ); + addOldStay( stay ); + } + + public void addOldStay(Stay stay) { + Collection<Stay> stays = getOldStays(); + if ( stays == null ) { + stays = new ArrayList<Stay>(); + } + stays.add( stay ); + + this.oldStays = stays; + } + + public void addVeryOldStay(Date startDate, Date endDate, String vessel, String authoriser, String comments) { + Stay stay = new Stay( this, startDate, endDate, vessel, authoriser, comments ); + addVeryOldStay( stay ); + } + + public void addVeryOldStay(Stay stay) { + Collection<Stay> stays = getVeryOldStays(); + if ( stays == null ) { + stays = new ArrayList<Stay>(); + } + stays.add( stay ); + + this.veryOldStays = stays; + } } Modified: trunk/HibernateExt/metadata/src/test/org/hibernate/test/annotations/fetch/Stay.java =================================================================== --- trunk/HibernateExt/metadata/src/test/org/hibernate/test/annotations/fetch/Stay.java 2006-04-28 14:11:16 UTC (rev 9829) +++ trunk/HibernateExt/metadata/src/test/org/hibernate/test/annotations/fetch/Stay.java 2006-04-28 15:16:41 UTC (rev 9830) @@ -12,6 +12,11 @@ import javax.persistence.ManyToOne; import javax.persistence.Table; +import org.hibernate.annotations.LazyToOne; +import org.hibernate.annotations.LazyToOneOption; +import org.hibernate.annotations.Fetch; +import org.hibernate.annotations.FetchMode; + /** * @author Emmanuel Bernard */ @@ -22,6 +27,8 @@ // member declaration private int id; private Person person; + private Person oldPerson; + private Person veryOldPerson; private Date startDate; private Date endDate; private String vessel; @@ -92,6 +99,30 @@ this.person = person; } + @ManyToOne(cascade = CascadeType.ALL) + @LazyToOne(LazyToOneOption.PROXY) + @Fetch(FetchMode.SELECT) + @JoinColumn(name = "oldperson") + public Person getOldPerson() { + return oldPerson; + } + + public void setOldPerson(Person oldPerson) { + this.oldPerson = oldPerson; + } + + @ManyToOne(cascade = CascadeType.ALL, fetch = FetchType.LAZY) + @LazyToOne(LazyToOneOption.PROXY) + @Fetch(FetchMode.JOIN) + @JoinColumn(name = "veryoldperson") + public Person getVeryOldPerson() { + return veryOldPerson; + } + + public void setVeryOldPerson(Person veryOldPerson) { + this.veryOldPerson = veryOldPerson; + } + public Date getStartDate() { return startDate; } |
From: <hib...@li...> - 2006-04-28 14:11:31
|
Author: max...@jb... Date: 2006-04-28 10:11:16 -0400 (Fri, 28 Apr 2006) New Revision: 9829 Added: branches/TOOLS_3_1_0_BETA5a_branch/tools/ Log: branching tools for 3.1/3.2 eclipse Copied: branches/TOOLS_3_1_0_BETA5a_branch/tools (from rev 9828, trunk/HibernateExt/tools) |
From: <hib...@li...> - 2006-04-28 14:09:25
|
Author: max...@jb... Date: 2006-04-28 10:09:18 -0400 (Fri, 28 Apr 2006) New Revision: 9828 Added: branches/TOOLS_3_1_0_BETA5a_branch/ Log: branching tools for 3.1/3.2 eclipse |
From: <hib...@li...> - 2006-04-28 13:47:54
|
Author: max...@jb... Date: 2006-04-28 09:47:28 -0400 (Fri, 28 Apr 2006) New Revision: 9827 Added: trunk/HibernateExt/tools/doc/reference/en/images/entitymodel.gif Removed: trunk/HibernateExt/tools/doc/reference/en/images/entitymodel_zoomout.png Modified: trunk/HibernateExt/tools/lib/testlibs/jboss-annotations-ejb3.jar trunk/HibernateExt/tools/lib/testlibs/jboss-seam.jar trunk/HibernateExt/tools/src/java/org/hibernate/tool/hbm2x/Cfg2HbmTool.java trunk/HibernateExt/tools/src/java/org/hibernate/tool/hbm2x/Cfg2JavaTool.java trunk/HibernateExt/tools/src/java/org/hibernate/tool/hbm2x/Version.java trunk/HibernateExt/tools/src/java/org/hibernate/tool/hbm2x/pojo/BasicPOJOClass.java trunk/HibernateExt/tools/src/templates/hbm/column.hbm.ftl trunk/HibernateExt/tools/src/templates/hbm/set.hbm.ftl trunk/HibernateExt/tools/src/templates/pojo/PojoConstructors.ftl trunk/HibernateExt/tools/src/test/org/hibernate/tool/hbm2x/Customer.hbm.xml Log: Added: trunk/HibernateExt/tools/doc/reference/en/images/entitymodel.gif =================================================================== (Binary files differ) Property changes on: trunk/HibernateExt/tools/doc/reference/en/images/entitymodel.gif ___________________________________________________________________ Name: svn:mime-type + application/octet-stream Deleted: trunk/HibernateExt/tools/doc/reference/en/images/entitymodel_zoomout.png =================================================================== (Binary files differ) Modified: trunk/HibernateExt/tools/lib/testlibs/jboss-annotations-ejb3.jar =================================================================== (Binary files differ) Modified: trunk/HibernateExt/tools/lib/testlibs/jboss-seam.jar =================================================================== (Binary files differ) Modified: trunk/HibernateExt/tools/src/java/org/hibernate/tool/hbm2x/Cfg2HbmTool.java =================================================================== --- trunk/HibernateExt/tools/src/java/org/hibernate/tool/hbm2x/Cfg2HbmTool.java 2006-04-28 01:00:21 UTC (rev 9826) +++ trunk/HibernateExt/tools/src/java/org/hibernate/tool/hbm2x/Cfg2HbmTool.java 2006-04-28 13:47:28 UTC (rev 9827) @@ -98,11 +98,20 @@ return isOneToMany(property.getValue()); } + public boolean isManyToMany(Property property) { + Value value = property.getValue(); + if(value instanceof Collection && !((Collection)value).isOneToMany()) { + return true; + } else { + return false; + } + + } public boolean isOneToMany(Value value) { if(value instanceof Collection) { return ( (Collection)value ).isOneToMany(); }else if(value instanceof OneToMany){ - return true; + return true; } return false; } Modified: trunk/HibernateExt/tools/src/java/org/hibernate/tool/hbm2x/Cfg2JavaTool.java =================================================================== --- trunk/HibernateExt/tools/src/java/org/hibernate/tool/hbm2x/Cfg2JavaTool.java 2006-04-28 01:00:21 UTC (rev 9826) +++ trunk/HibernateExt/tools/src/java/org/hibernate/tool/hbm2x/Cfg2JavaTool.java 2006-04-28 13:47:28 UTC (rev 9827) @@ -461,4 +461,8 @@ public String simplePluralize(String str) { return ReverseEngineeringStrategyUtil.simplePluralize(str); } + + public boolean isArray(String typeName) { + return typeName!=null && typeName.endsWith("[]"); + } } Modified: trunk/HibernateExt/tools/src/java/org/hibernate/tool/hbm2x/Version.java =================================================================== --- trunk/HibernateExt/tools/src/java/org/hibernate/tool/hbm2x/Version.java 2006-04-28 01:00:21 UTC (rev 9826) +++ trunk/HibernateExt/tools/src/java/org/hibernate/tool/hbm2x/Version.java 2006-04-28 13:47:28 UTC (rev 9827) @@ -1,11 +1,20 @@ package org.hibernate.tool.hbm2x; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + final public class Version { - public static final String VERSION = "3.1.0.beta4"; + public static final String VERSION = "3.1.0.beta5"; private static final Version instance = new Version(); + private static Log log = LogFactory.getLog( Version.class ); + + static { + log.info( "Hibernate Tools " + VERSION ); + } + private Version() { // dont instantiate me } @@ -21,4 +30,10 @@ public String toString() { return getVersion(); } + + public static void touch() {} + + public static void main(String[] args) { + System.out.println(new Version()); + } } Modified: trunk/HibernateExt/tools/src/java/org/hibernate/tool/hbm2x/pojo/BasicPOJOClass.java =================================================================== --- trunk/HibernateExt/tools/src/java/org/hibernate/tool/hbm2x/pojo/BasicPOJOClass.java 2006-04-28 01:00:21 UTC (rev 9826) +++ trunk/HibernateExt/tools/src/java/org/hibernate/tool/hbm2x/pojo/BasicPOJOClass.java 2006-04-28 13:47:28 UTC (rev 9827) @@ -251,6 +251,8 @@ else { if(useCompareTo( typeName )) { return "( (" + lh + "==" + rh + ") || ( " + lh + "!=null && " + rh + "!=null && " + lh + ".compareTo(" + rh + ")==0 ) )"; + } else if ( c2j.isArray( typeName ) ) { + return "( java.util.Arrays.equals(" + lh + "," + rh + ") )"; } else { return "( (" + lh + "==" + rh + ") || ( " + lh + "!=null && " + rh + "!=null && " + lh + ".equals(" + rh + ") ) )"; } Modified: trunk/HibernateExt/tools/src/templates/hbm/column.hbm.ftl =================================================================== --- trunk/HibernateExt/tools/src/templates/hbm/column.hbm.ftl 2006-04-28 01:00:21 UTC (rev 9826) +++ trunk/HibernateExt/tools/src/templates/hbm/column.hbm.ftl 2006-04-28 13:47:28 UTC (rev 9827) @@ -1,11 +1,8 @@ <#if column.isFormula()> -<formula>${column.formula}</formula> +<formula>${column.getFormula()}</formula> <#else> -<column name="${column.quotedName}" ${c2h.columnAttributes(column)} -<#if column.comment?exists>> - <comment>${column.comment}</comment> -</column> -<#else> -/> +<column name="${column.quotedName}" ${c2h.columnAttributes(column)}<#if column.comment?exists>> +<comment>${column.comment}</comment> +</column><#else>/> </#if> </#if> \ No newline at end of file Modified: trunk/HibernateExt/tools/src/templates/hbm/set.hbm.ftl =================================================================== --- trunk/HibernateExt/tools/src/templates/hbm/set.hbm.ftl 2006-04-28 01:00:21 UTC (rev 9826) +++ trunk/HibernateExt/tools/src/templates/hbm/set.hbm.ftl 2006-04-28 13:47:28 UTC (rev 9827) @@ -3,9 +3,23 @@ inverse="${property.value.inverse?string}" > <key> - <#foreach column in property.value.key.columnIterator> <#include "column.hbm.ftl"> </#foreach> </key> - <#if c2h.isOneToMany(property)> <one-to-many + <#foreach column in property.value.key.columnIterator> + <#include "column.hbm.ftl"> + </#foreach> + </key> +<#if c2h.isOneToMany(property)> + <one-to-many class="${property.getValue().getElement().getAssociatedClass().getClassName()}" -<#if !property.getValue().getElement().getAssociatedClass().getClassName().equals(property.getValue().getElement().getReferencedEntityName())> entity-name="${property.getValue().getElement().getReferencedEntityName()}" -</#if> /> - </#if> </set> +<#if !property.getValue().getElement().getAssociatedClass().getClassName().equals(property.getValue().getElement().getReferencedEntityName())> + entity-name="${property.getValue().getElement().getReferencedEntityName()}" +</#if> + /> +<#elseif c2h.isManyToMany(property)> + <many-to-many + entity-name="${property.getValue().getElement().referencedEntityName}"> <#-- lookup needed classname --> +<#foreach column in property.getValue().getElement().columnIterator> + <#include "column.hbm.ftl"> +</#foreach> + </many-to-many> +</#if> + </set> Modified: trunk/HibernateExt/tools/src/templates/pojo/PojoConstructors.ftl =================================================================== --- trunk/HibernateExt/tools/src/templates/pojo/PojoConstructors.ftl 2006-04-28 01:00:21 UTC (rev 9826) +++ trunk/HibernateExt/tools/src/templates/pojo/PojoConstructors.ftl 2006-04-28 13:47:28 UTC (rev 9827) @@ -6,13 +6,21 @@ <#if pojo.needsMinimalConstructor()> /** minimal constructor */ public ${pojo.getDeclarationName()}(${c2j.asParameterList(pojo.getPropertyClosureForMinimalConstructor(), jdk5, pojo)}) { -<#if pojo.isSubclass() && !pojo.getPropertyClosureForSuperclassMinimalConstructor().isEmpty()> super(${c2j.asArgumentList(pojo.getPropertyClosureForSuperclassMinimalConstructor())}); -</#if><#foreach field in pojo.getPropertiesForMinimalConstructor()> this.${field.name} = ${field.name}; -</#foreach> } +<#if pojo.isSubclass() && !pojo.getPropertyClosureForSuperclassMinimalConstructor().isEmpty()> + super(${c2j.asArgumentList(pojo.getPropertyClosureForSuperclassMinimalConstructor())}); +</#if> +<#foreach field in pojo.getPropertiesForMinimalConstructor()> + this.${field.name} = ${field.name}; +</#foreach> + } </#if> /** full constructor */ public ${pojo.getDeclarationName()}(${c2j.asParameterList(pojo.getPropertyClosureForFullConstructor(), jdk5, pojo)}) { -<#if pojo.isSubclass() && !pojo.getPropertyClosureForSuperclassFullConstructor().isEmpty()> super(${c2j.asArgumentList(pojo.getPropertyClosureForSuperclassFullConstructor())}); -</#if><#foreach field in pojo.getPropertiesForFullConstructor()> this.${field.name} = ${field.name}; -</#foreach> } +<#if pojo.isSubclass() && !pojo.getPropertyClosureForSuperclassFullConstructor().isEmpty()> + super(${c2j.asArgumentList(pojo.getPropertyClosureForSuperclassFullConstructor())}); +</#if> +<#foreach field in pojo.getPropertiesForFullConstructor()> + this.${field.name} = ${field.name}; +</#foreach> + } Modified: trunk/HibernateExt/tools/src/test/org/hibernate/tool/hbm2x/Customer.hbm.xml =================================================================== --- trunk/HibernateExt/tools/src/test/org/hibernate/tool/hbm2x/Customer.hbm.xml 2006-04-28 01:00:21 UTC (rev 9826) +++ trunk/HibernateExt/tools/src/test/org/hibernate/tool/hbm2x/Customer.hbm.xml 2006-04-28 13:47:28 UTC (rev 9827) @@ -32,6 +32,10 @@ <property name="customDate" type="org.hibernate.tool.hbm2x.DummyDateType" not-null="true" length="200"/> + <property name="acl" type="byte[]"> + <meta attribute="use-in-equals">true</meta> + </property> + <component name="addressComponent" class="Address"> <property name="streetAddress1" type="string" column="StreetAddress1" not-null="true"> |
From: <hib...@li...> - 2006-04-28 01:00:24
|
Author: epbernard Date: 2006-04-27 21:00:21 -0400 (Thu, 27 Apr 2006) New Revision: 9826 Added: trunk/HibernateExt/metadata/src/test/org/hibernate/test/annotations/manytoone/Order.java trunk/HibernateExt/metadata/src/test/org/hibernate/test/annotations/manytoone/OrderLine.java Modified: trunk/HibernateExt/metadata/src/test/org/hibernate/test/annotations/manytoone/ManyToOneTest.java Log: ANN-97 tests to reflect the issue solved in core Modified: trunk/HibernateExt/metadata/src/test/org/hibernate/test/annotations/manytoone/ManyToOneTest.java =================================================================== --- trunk/HibernateExt/metadata/src/test/org/hibernate/test/annotations/manytoone/ManyToOneTest.java 2006-04-28 00:55:24 UTC (rev 9825) +++ trunk/HibernateExt/metadata/src/test/org/hibernate/test/annotations/manytoone/ManyToOneTest.java 2006-04-28 01:00:21 UTC (rev 9826) @@ -241,6 +241,26 @@ } + public void testManyToOneNonPk() throws Exception { + Session s = openSession(); + Transaction tx = s.beginTransaction(); + Order order = new Order(); + order.setOrderNbr( "123" ); + s.persist( order ); + OrderLine ol = new OrderLine(); + ol.setItem( "Mouse" ); + ol.setOrder( order ); + s.persist( ol ); + s.flush(); + s.clear(); + ol = (OrderLine) s.get( OrderLine.class, ol.getId() ); + assertNotNull( ol.getOrder() ); + assertEquals( "123", ol.getOrder().getOrderNbr() ); + assertTrue( ol.getOrder().getOrderLines().contains( ol ) ); + tx.rollback(); + s.close(); + } + /** * @see org.hibernate.test.annotations.TestCase#getMappings() */ @@ -258,7 +278,9 @@ Child.class, Node.class, User.class, - DistrictUser.class + DistrictUser.class, + Order.class, + OrderLine.class }; } Added: trunk/HibernateExt/metadata/src/test/org/hibernate/test/annotations/manytoone/Order.java =================================================================== --- trunk/HibernateExt/metadata/src/test/org/hibernate/test/annotations/manytoone/Order.java 2006-04-28 00:55:24 UTC (rev 9825) +++ trunk/HibernateExt/metadata/src/test/org/hibernate/test/annotations/manytoone/Order.java 2006-04-28 01:00:21 UTC (rev 9826) @@ -0,0 +1,50 @@ +//$Id: $ +package org.hibernate.test.annotations.manytoone; + +import java.io.Serializable; +import java.util.Set; +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.Id; +import javax.persistence.Column; +import javax.persistence.Table; +import javax.persistence.OneToMany; + +/** + * @author Emmanuel Bernard + */ +@Entity +@Table(name="ORDERS") +public class Order implements Serializable { + private Integer id; + private String orderNbr; + private Set<OrderLine> orderLines; + + @Id + @GeneratedValue + public Integer getId() { + return id; + } + + public void setId(Integer id) { + this.id = id; + } + + @Column(name="order_nbr", unique = true) + public String getOrderNbr() { + return orderNbr; + } + + public void setOrderNbr(String orderNbr) { + this.orderNbr = orderNbr; + } + + @OneToMany(mappedBy = "order") + public Set<OrderLine> getOrderLines() { + return orderLines; + } + + public void setOrderLines(Set<OrderLine> orderLines) { + this.orderLines = orderLines; + } +} Added: trunk/HibernateExt/metadata/src/test/org/hibernate/test/annotations/manytoone/OrderLine.java =================================================================== --- trunk/HibernateExt/metadata/src/test/org/hibernate/test/annotations/manytoone/OrderLine.java 2006-04-28 00:55:24 UTC (rev 9825) +++ trunk/HibernateExt/metadata/src/test/org/hibernate/test/annotations/manytoone/OrderLine.java 2006-04-28 01:00:21 UTC (rev 9826) @@ -0,0 +1,45 @@ +//$Id: $ +package org.hibernate.test.annotations.manytoone; + +import javax.persistence.Entity; +import javax.persistence.Id; +import javax.persistence.GeneratedValue; +import javax.persistence.ManyToOne; +import javax.persistence.JoinColumn; + +/** + * @author Emmanuel Bernard + */ +@Entity +public class OrderLine { + private Integer id; + private String item; + private Order order; + + @Id @GeneratedValue + public Integer getId() { + return id; + } + + public void setId(Integer id) { + this.id = id; + } + + public String getItem() { + return item; + } + + public void setItem(String item) { + this.item = item; + } + + @ManyToOne + @JoinColumn(name="order_nbr", referencedColumnName = "order_nbr", unique = true) + public Order getOrder() { + return order; + } + + public void setOrder(Order order) { + this.order = order; + } +} |
From: <hib...@li...> - 2006-04-28 00:55:26
|
Author: epbernard Date: 2006-04-27 20:55:24 -0400 (Thu, 27 Apr 2006) New Revision: 9825 Modified: trunk/Hibernate3/src/org/hibernate/mapping/Table.java Log: HHH-1704 deduplicate unique constraints per table Modified: trunk/Hibernate3/src/org/hibernate/mapping/Table.java =================================================================== --- trunk/Hibernate3/src/org/hibernate/mapping/Table.java 2006-04-27 23:30:54 UTC (rev 9824) +++ trunk/Hibernate3/src/org/hibernate/mapping/Table.java 2006-04-28 00:55:24 UTC (rev 9825) @@ -200,11 +200,37 @@ } public Iterator getUniqueKeyIterator() { - return uniqueKeys.values().iterator(); + return getUniqueKeys().values().iterator(); } Map getUniqueKeys() { - return uniqueKeys; + if ( uniqueKeys.size() > 1) { + //deduplicate unique constraints sharing the same columns + //this is needed by Hibernate Annotations since it creates automagically + // unique constraints for the user + Iterator it = uniqueKeys.entrySet().iterator(); + Map finalUniqueKeys = new HashMap( uniqueKeys.size() ); + while ( it.hasNext() ) { + Map.Entry entry = (Map.Entry) it.next(); + UniqueKey uk = (UniqueKey) entry.getValue(); + List columns = uk.getColumns(); + int size = finalUniqueKeys.size(); + boolean skip = false; + Iterator tempUks = finalUniqueKeys.entrySet().iterator(); + while ( tempUks.hasNext() ) { + final UniqueKey currentUk = (UniqueKey) ( (Map.Entry) tempUks.next() ).getValue(); + if ( currentUk.getColumns().containsAll( columns ) && columns.containsAll( currentUk.getColumns() ) ) { + skip = true; + break; + } + } + if (! skip) finalUniqueKeys.put(entry.getKey(), uk); + } + return finalUniqueKeys; + } + else { + return uniqueKeys; + } } public void validateColumns(Dialect dialect, Mapping mapping, TableMetadata tableInfo) { |
From: <hib...@li...> - 2006-04-27 23:30:58
|
Author: epbernard Date: 2006-04-27 19:30:54 -0400 (Thu, 27 Apr 2006) New Revision: 9824 Modified: trunk/Hibernate3/src/org/hibernate/cfg/HbmBinder.java Log: allow generated=insert and updatable property but actually fix the bug ;-) Modified: trunk/Hibernate3/src/org/hibernate/cfg/HbmBinder.java =================================================================== --- trunk/Hibernate3/src/org/hibernate/cfg/HbmBinder.java 2006-04-27 23:28:48 UTC (rev 9823) +++ trunk/Hibernate3/src/org/hibernate/cfg/HbmBinder.java 2006-04-27 23:30:54 UTC (rev 9824) @@ -1229,7 +1229,7 @@ ); } property.setInsertable( false ); - property.setUpdateable( false ); + property.setUpdateable( generation != PropertyGeneration.ALWAYS ); property.setGeneration( generation ); } |
From: <hib...@li...> - 2006-04-27 23:28:56
|
Author: epbernard Date: 2006-04-27 19:28:48 -0400 (Thu, 27 Apr 2006) New Revision: 9823 Modified: trunk/Hibernate3/src/org/hibernate/cfg/HbmBinder.java Log: allow generated=insert and updatable property Modified: trunk/Hibernate3/src/org/hibernate/cfg/HbmBinder.java =================================================================== --- trunk/Hibernate3/src/org/hibernate/cfg/HbmBinder.java 2006-04-27 23:11:39 UTC (rev 9822) +++ trunk/Hibernate3/src/org/hibernate/cfg/HbmBinder.java 2006-04-27 23:28:48 UTC (rev 9823) @@ -1221,7 +1221,7 @@ propName ); } - if ( updateNode != null && property.isUpdateable() ) { + if ( updateNode != null && property.isUpdateable() && generation == PropertyGeneration.ALWAYS ) { throw new MappingException( "cannot specify both update=\"true\" and generated=\"" + generation.getName() + "\" for property: " + |
Author: epbernard Date: 2006-04-27 19:11:39 -0400 (Thu, 27 Apr 2006) New Revision: 9822 Added: trunk/HibernateExt/metadata/src/java/org/hibernate/annotations/Generated.java trunk/HibernateExt/metadata/src/java/org/hibernate/annotations/GenerationTime.java trunk/HibernateExt/metadata/src/test/org/hibernate/test/annotations/various/Antenna.java trunk/HibernateExt/metadata/src/test/org/hibernate/test/annotations/various/GeneratedTest.java Modified: trunk/HibernateExt/metadata/doc/reference/en/modules/entity.xml trunk/HibernateExt/metadata/src/java/org/hibernate/cfg/AnnotationBinder.java trunk/HibernateExt/metadata/src/java/org/hibernate/cfg/annotations/CollectionBinder.java trunk/HibernateExt/metadata/src/java/org/hibernate/cfg/annotations/PropertyBinder.java Log: ANN-89 support Generated properties Modified: trunk/HibernateExt/metadata/doc/reference/en/modules/entity.xml =================================================================== --- trunk/HibernateExt/metadata/doc/reference/en/modules/entity.xml 2006-04-27 21:12:40 UTC (rev 9821) +++ trunk/HibernateExt/metadata/doc/reference/en/modules/entity.xml 2006-04-27 23:11:39 UTC (rev 9822) @@ -2472,6 +2472,35 @@ person == person.address.owner</programlisting> </sect3> + + <sect3> + <title>Generated properties</title> + + <para>Some properties are generated at insert or update time by your + database. Hibernate can deal with such properties and triggers a + subsequent select to read these properties.</para> + + <programlisting>@Entity +public class Antenna { + @Id public Integer id; + @Generated(GenerationTime.ALWAYS) @Column(insertable = false, updatable = false) + public String longitude; + + @Generated(GenerationTime.INSERT) @Column(insertable = false) + public String latitude; +}</programlisting> + + <para>Annotate your property as <literal>@Generated</literal> You have + to make sure your insertability or updatability does not conflict with + the generation strategy you have chosen. When GenerationTime.INSERT is + chosen, the property must not contains insertable columns, when + GenerationTime.ALWAYS is chosen, the property must not contains + insertable nor updatable columns.</para> + + <para><literal>@Version</literal> properties cannot be + <literal>@Generated(INSERT)</literal> by design, it has to be either + <literal>NEVER</literal> or <literal>ALWAYS</literal>.</para> + </sect3> </sect2> <sect2> Added: trunk/HibernateExt/metadata/src/java/org/hibernate/annotations/Generated.java =================================================================== --- trunk/HibernateExt/metadata/src/java/org/hibernate/annotations/Generated.java 2006-04-27 21:12:40 UTC (rev 9821) +++ trunk/HibernateExt/metadata/src/java/org/hibernate/annotations/Generated.java 2006-04-27 23:11:39 UTC (rev 9822) @@ -0,0 +1,18 @@ +//$Id: $ +package org.hibernate.annotations; + +import java.lang.annotation.Target; +import java.lang.annotation.Retention; +import java.lang.annotation.ElementType; +import java.lang.annotation.RetentionPolicy; + +/** + * The annotated property is generated by the database + * + * @author Emmanuel Bernard + */ +@Target({ElementType.FIELD, ElementType.METHOD}) +@Retention(RetentionPolicy.RUNTIME) +public @interface Generated { + GenerationTime value(); +} Added: trunk/HibernateExt/metadata/src/java/org/hibernate/annotations/GenerationTime.java =================================================================== --- trunk/HibernateExt/metadata/src/java/org/hibernate/annotations/GenerationTime.java 2006-04-27 21:12:40 UTC (rev 9821) +++ trunk/HibernateExt/metadata/src/java/org/hibernate/annotations/GenerationTime.java 2006-04-27 23:11:39 UTC (rev 9822) @@ -0,0 +1,13 @@ +//$Id: $ +package org.hibernate.annotations; + +/** + * When should the generation occurs + * + * @author Emmanuel Bernard + */ +public enum GenerationTime { + NEVER, + INSERT, + ALWAYS +} Modified: trunk/HibernateExt/metadata/src/java/org/hibernate/cfg/AnnotationBinder.java =================================================================== --- trunk/HibernateExt/metadata/src/java/org/hibernate/cfg/AnnotationBinder.java 2006-04-27 21:12:40 UTC (rev 9821) +++ trunk/HibernateExt/metadata/src/java/org/hibernate/cfg/AnnotationBinder.java 2006-04-27 23:11:39 UTC (rev 9822) @@ -1179,12 +1179,10 @@ joinColumns, ann.optional(), getFetchMode( ann.fetch() ), - ignoreNotFound, onDeleteCascade, inferredData.getPropertyName(), - inferredData.getClassOrElementName(), + ignoreNotFound, onDeleteCascade, mappings.getReflectionManager().toXClass( ann.targetEntity() ), - inferredData.getDefaultAccess(), propertyHolder, - false, isIdentifierMapper, mappings + inferredData, false, isIdentifierMapper, mappings ); } else if ( property.isAnnotationPresent( OneToOne.class ) ) { @@ -1202,12 +1200,10 @@ joinColumns, ann.optional(), getFetchMode( ann.fetch() ), - ignoreNotFound, onDeleteCascade, inferredData.getPropertyName(), - inferredData.getClassOrElementName(), + ignoreNotFound, onDeleteCascade, mappings.getReflectionManager().toXClass( ann.targetEntity() ), - inferredData.getDefaultAccess(), propertyHolder, - ann.mappedBy(), trueOneToOne, isIdentifierMapper, mappings + inferredData, ann.mappedBy(), trueOneToOne, isIdentifierMapper, mappings ); } else if ( property.isAnnotationPresent( OneToMany.class ) @@ -1504,6 +1500,7 @@ PropertyBinder binder = new PropertyBinder(); binder.setName( inferredData.getPropertyName() ); binder.setValue( comp ); + binder.setProperty( inferredData.getProperty() ); binder.setPropertyAccessorName( inferredData.getDefaultAccess() ); Property prop = binder.make(); propertyHolder.addProperty( prop ); @@ -1658,6 +1655,7 @@ binder.setName( inferredData.getPropertyName() ); binder.setValue( id ); binder.setPropertyAccessorName( inferredData.getDefaultAccess() ); + binder.setProperty( inferredData.getProperty() ); Property prop = binder.make(); rootClass.setIdentifierProperty( prop ); } @@ -1665,14 +1663,14 @@ private static void bindManyToOne( String cascadeStrategy, Ejb3JoinColumn[] columns, boolean optional, FetchMode fetchMode, - boolean ignoreNotFound, boolean cascadeOnDelete, String propertyName, - String returnedClassName, XClass targetEntity, String propertyAccessorName, PropertyHolder propertyHolder, - boolean unique, boolean isIdentifierMapper, ExtendedMappings mappings + boolean ignoreNotFound, boolean cascadeOnDelete, + XClass targetEntity, PropertyHolder propertyHolder, + PropertyData inferredData, boolean unique, boolean isIdentifierMapper, ExtendedMappings mappings ) { //All FK columns should be in the same table org.hibernate.mapping.ManyToOne value = new org.hibernate.mapping.ManyToOne( columns[0].getTable() ); if ( isDefault( targetEntity, mappings ) ) { - value.setReferencedEntityName( returnedClassName ); + value.setReferencedEntityName( inferredData.getClassOrElementName() ); } else { value.setReferencedEntityName( targetEntity.getName() ); @@ -1686,7 +1684,8 @@ column.setNullable( false ); } } - value.setTypeName( returnedClassName ); + value.setTypeName( inferredData.getClassOrElementName() ); + final String propertyName = inferredData.getPropertyName(); value.setTypeUsingReflection( propertyHolder.getClassName(), propertyName ); //value.createForeignKey(); @@ -1711,7 +1710,7 @@ binder.setInsertable( columns[0].isInsertable() ); binder.setUpdatable( columns[0].isUpdatable() ); } - binder.setPropertyAccessorName( propertyAccessorName ); + binder.setPropertyAccessorName( inferredData.getDefaultAccess() ); binder.setCascade( cascadeStrategy ); Property prop = binder.make(); //composite FK columns are in the same table so its OK @@ -1725,16 +1724,14 @@ FetchMode fetchMode, boolean ignoreNotFound, boolean cascadeOnDelete, - String propertyName, - String returnedClassName, XClass targetEntity, - String propertyAccessorName, PropertyHolder propertyHolder, - String mappedBy, + PropertyData inferredData, String mappedBy, boolean trueOneToOne, boolean isIdentifierMapper, ExtendedMappings mappings ) { //column.getTable() => persistentClass.getTable() + final String propertyName = inferredData.getPropertyName(); log.debug( "Fetching " + propertyName + " with " + fetchMode ); boolean mapToPK = true; if ( ! trueOneToOne ) { @@ -1761,7 +1758,7 @@ ); value.setPropertyName( propertyName ); if ( isDefault( targetEntity, mappings ) ) { - value.setReferencedEntityName( returnedClassName ); + value.setReferencedEntityName( inferredData.getClassOrElementName() ); } else { value.setReferencedEntityName( targetEntity.getName() ); @@ -1803,7 +1800,7 @@ binder.setName( propertyName ); binder.setValue( value ); binder.setCascade( cascadeStrategy ); - binder.setPropertyAccessorName( propertyAccessorName ); + binder.setPropertyAccessorName( inferredData.getDefaultAccess() ); Property prop = binder.make(); prop.setCascade( cascadeStrategy ); //no column associated since its a one to one @@ -1813,8 +1810,8 @@ //has a FK on the table bindManyToOne( cascadeStrategy, columns, optional, fetchMode, ignoreNotFound, cascadeOnDelete, - propertyName, returnedClassName, targetEntity, - propertyAccessorName, propertyHolder, true, isIdentifierMapper, mappings + targetEntity, + propertyHolder, inferredData, true, isIdentifierMapper, mappings ); } } Modified: trunk/HibernateExt/metadata/src/java/org/hibernate/cfg/annotations/CollectionBinder.java =================================================================== --- trunk/HibernateExt/metadata/src/java/org/hibernate/cfg/annotations/CollectionBinder.java 2006-04-27 21:12:40 UTC (rev 9821) +++ trunk/HibernateExt/metadata/src/java/org/hibernate/cfg/annotations/CollectionBinder.java 2006-04-27 23:11:39 UTC (rev 9822) @@ -363,6 +363,7 @@ collection.setOrphanDelete( true ); } binder.setPropertyAccessorName( propertyAccessorName ); + binder.setProperty( property ); binder.setInsertable( insertable ); binder.setUpdatable( updatable ); Property prop = binder.make(); Modified: trunk/HibernateExt/metadata/src/java/org/hibernate/cfg/annotations/PropertyBinder.java =================================================================== --- trunk/HibernateExt/metadata/src/java/org/hibernate/cfg/annotations/PropertyBinder.java 2006-04-27 21:12:40 UTC (rev 9821) +++ trunk/HibernateExt/metadata/src/java/org/hibernate/cfg/annotations/PropertyBinder.java 2006-04-27 23:11:39 UTC (rev 9822) @@ -3,14 +3,19 @@ import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; +import org.hibernate.annotations.Generated; +import org.hibernate.annotations.GenerationTime; import org.hibernate.cfg.Ejb3Column; import org.hibernate.cfg.ExtendedMappings; import org.hibernate.cfg.PropertyHolder; import org.hibernate.mapping.Property; import org.hibernate.mapping.SimpleValue; import org.hibernate.mapping.Value; +import org.hibernate.mapping.PropertyGeneration; import org.hibernate.reflection.XClass; import org.hibernate.reflection.XProperty; +import org.hibernate.AnnotationException; +import org.hibernate.util.StringHelper; /** * @author Emmanuel Bernard @@ -28,6 +33,10 @@ private boolean insertable = true; private boolean updatable = true; private String cascade; + /* + * property can be null + * prefer propertyName to property.getName() since some are overloaded + */ private XProperty property; private XClass returnedClass; @@ -119,6 +128,32 @@ prop.setLazy( lazy ); prop.setCascade( cascade ); prop.setPropertyAccessorName( propertyAccessorName ); + Generated ann = property != null ? + property.getAnnotation( Generated.class ) : + null; + GenerationTime generated = ann != null ? + ann.value() : + null; + if (generated != null) { + if ( ! GenerationTime.NEVER.equals( generated ) ) { + if ( property.isAnnotationPresent( javax.persistence.Version.class ) + && GenerationTime.INSERT.equals( generated ) ) { + throw new AnnotationException("@Generated(INSERT) on a @Version property not allowed, use ALWAYS: " + + StringHelper.qualify( holder.getPath(), name ) ); + } + if ( prop.isInsertable() ) { + throw new AnnotationException("Cannot have @Generated property and insertable columns: " + + StringHelper.qualify( holder.getPath(), name ) ); + } + if ( GenerationTime.ALWAYS.equals( generated ) && prop.isUpdateable() ) { + throw new AnnotationException("Cannot have @Generated(ALWAYS) property and updatable columns: " + + StringHelper.qualify( holder.getPath(), name ) ); + } + prop.setInsertable( false ); + prop.setUpdateable( false ); + prop.setGeneration( PropertyGeneration.parse( generated.toString().toLowerCase() ) ); + } + } log.debug( "Cascading " + name + " with " + cascade ); return prop; } Added: trunk/HibernateExt/metadata/src/test/org/hibernate/test/annotations/various/Antenna.java =================================================================== --- trunk/HibernateExt/metadata/src/test/org/hibernate/test/annotations/various/Antenna.java 2006-04-27 21:12:40 UTC (rev 9821) +++ trunk/HibernateExt/metadata/src/test/org/hibernate/test/annotations/various/Antenna.java 2006-04-27 23:11:39 UTC (rev 9822) @@ -0,0 +1,25 @@ +//$Id: $ +package org.hibernate.test.annotations.various; + +import javax.persistence.Entity; +import javax.persistence.Id; +import javax.persistence.Column; + +import org.hibernate.annotations.Generated; +import org.hibernate.annotations.GenerationTime; + +/** + * @author Emmanuel Bernard + */ +@Entity +public class Antenna { + @Id public Integer id; + @Generated(GenerationTime.ALWAYS) @Column(insertable = false, updatable = false) + public String longitude; + + @Generated(GenerationTime.INSERT) @Column(insertable = false) + public String latitude; + + @Generated(GenerationTime.NEVER) + public Double power; +} Added: trunk/HibernateExt/metadata/src/test/org/hibernate/test/annotations/various/GeneratedTest.java =================================================================== --- trunk/HibernateExt/metadata/src/test/org/hibernate/test/annotations/various/GeneratedTest.java 2006-04-27 21:12:40 UTC (rev 9821) +++ trunk/HibernateExt/metadata/src/test/org/hibernate/test/annotations/various/GeneratedTest.java 2006-04-27 23:11:39 UTC (rev 9822) @@ -0,0 +1,30 @@ +//$Id: $ +package org.hibernate.test.annotations.various; + +import org.hibernate.test.annotations.TestCase; +import org.hibernate.Session; +import org.hibernate.Transaction; + +/** + * @author Emmanuel Bernard + */ +public class GeneratedTest extends TestCase { + + public void testGenerated() throws Exception { + Session s = openSession(); + Transaction tx = s.beginTransaction(); + Antenna antenna = new Antenna(); + antenna.id = new Integer(1); + s.persist( antenna ); + assertNull( antenna.latitude ); + assertNull( antenna.longitude ); + tx.rollback(); + s.close(); + } + + protected Class[] getMappings() { + return new Class[] { + Antenna.class + }; + } +} |
From: <hib...@li...> - 2006-04-27 21:12:45
|
Author: epbernard Date: 2006-04-27 17:12:40 -0400 (Thu, 27 Apr 2006) New Revision: 9821 Added: trunk/HibernateExt/metadata/src/java/org/hibernate/annotations/Parent.java Modified: trunk/HibernateExt/metadata/doc/reference/en/modules/entity.xml trunk/HibernateExt/metadata/src/java/org/hibernate/cfg/AbstractPropertyHolder.java trunk/HibernateExt/metadata/src/java/org/hibernate/cfg/AnnotationBinder.java trunk/HibernateExt/metadata/src/java/org/hibernate/cfg/ComponentPropertyHolder.java trunk/HibernateExt/metadata/src/java/org/hibernate/cfg/PropertyHolder.java trunk/HibernateExt/metadata/src/test/org/hibernate/test/annotations/collectionelement/CollectionElementTest.java trunk/HibernateExt/metadata/src/test/org/hibernate/test/annotations/collectionelement/Toy.java trunk/HibernateExt/metadata/src/test/org/hibernate/test/annotations/embedded/EmbeddedTest.java trunk/HibernateExt/metadata/src/test/org/hibernate/test/annotations/embedded/Summary.java Log: ANN-40 support for @Parent and documentation if it Modified: trunk/HibernateExt/metadata/doc/reference/en/modules/entity.xml =================================================================== --- trunk/HibernateExt/metadata/doc/reference/en/modules/entity.xml 2006-04-27 17:14:58 UTC (rev 9820) +++ trunk/HibernateExt/metadata/doc/reference/en/modules/entity.xml 2006-04-27 21:12:40 UTC (rev 9821) @@ -2450,6 +2450,28 @@ return storyPart1; }</programlisting> </sect3> + + <sect3> + <title>@Parent</title> + + <para>When inside an embeddable object, you can define one of the + properties as a pointer back to the owner element.</para> + + <programlisting>@Entity +public class Person { + @Embeddable public Address address; + ... +} + +@Embeddable +public class Address { + @Parent public Person owner; + ... +} + + +person == person.address.owner</programlisting> + </sect3> </sect2> <sect2> @@ -2662,6 +2684,7 @@ public class Toy { public String name; public String serial; + public Boy owner; public String getName() { return name; @@ -2679,6 +2702,15 @@ this.serial = serial; } + <emphasis role="bold">@Parent</emphasis> + public Boy getOwner() { + return owner; + } + + public void setOwner(Boy owner) { + this.owner = owner; + } + public boolean equals(Object o) { if ( this == o ) return true; if ( o == null || getClass() != o.getClass() ) return false; @@ -2699,6 +2731,11 @@ } }</programlisting> + <para>On a collection of embeddable objects, the embeddable object can + have a proeprty annotated with <literal>@Parent</literal>. This + property will then point back to the entity containing the + collection.</para> + <note> <para>Previous versions of Hibernate Annotations used the <literal>@OneToMany</literal> to mark a collection of elements. Due Added: trunk/HibernateExt/metadata/src/java/org/hibernate/annotations/Parent.java =================================================================== --- trunk/HibernateExt/metadata/src/java/org/hibernate/annotations/Parent.java 2006-04-27 17:14:58 UTC (rev 9820) +++ trunk/HibernateExt/metadata/src/java/org/hibernate/annotations/Parent.java 2006-04-27 21:12:40 UTC (rev 9821) @@ -0,0 +1,18 @@ +//$Id: $ +package org.hibernate.annotations; + +import static java.lang.annotation.ElementType.FIELD; +import static java.lang.annotation.ElementType.METHOD; +import java.lang.annotation.Retention; +import static java.lang.annotation.RetentionPolicy.RUNTIME; +import java.lang.annotation.Target; + +/** + * Reference the property as a pointer back to the owner (generally the owning entity) + * + * @author Emmanuel Bernard + */ +@Target({METHOD, FIELD}) +@Retention(RUNTIME) +public @interface Parent { +} Modified: trunk/HibernateExt/metadata/src/java/org/hibernate/cfg/AbstractPropertyHolder.java =================================================================== --- trunk/HibernateExt/metadata/src/java/org/hibernate/cfg/AbstractPropertyHolder.java 2006-04-27 17:14:58 UTC (rev 9820) +++ trunk/HibernateExt/metadata/src/java/org/hibernate/cfg/AbstractPropertyHolder.java 2006-04-27 21:12:40 UTC (rev 9821) @@ -17,6 +17,7 @@ import org.hibernate.reflection.XClass; import org.hibernate.reflection.XProperty; import org.hibernate.util.StringHelper; +import org.hibernate.AssertionFailure; /** * @author Emmanuel Bernard @@ -180,4 +181,8 @@ } return columnOverride; } + + public void setParentProperty(String parentProperty) { + throw new AssertionFailure("Setting the parent property to a non component"); + } } Modified: trunk/HibernateExt/metadata/src/java/org/hibernate/cfg/AnnotationBinder.java =================================================================== --- trunk/HibernateExt/metadata/src/java/org/hibernate/cfg/AnnotationBinder.java 2006-04-27 17:14:58 UTC (rev 9820) +++ trunk/HibernateExt/metadata/src/java/org/hibernate/cfg/AnnotationBinder.java 2006-04-27 21:12:40 UTC (rev 9821) @@ -81,6 +81,7 @@ import org.hibernate.annotations.TypeDef; import org.hibernate.annotations.TypeDefs; import org.hibernate.annotations.Where; +import org.hibernate.annotations.Parent; import org.hibernate.cfg.annotations.CollectionBinder; import org.hibernate.cfg.annotations.EntityBinder; import org.hibernate.cfg.annotations.Nullability; @@ -967,6 +968,17 @@ ); } + if ( property.isAnnotationPresent( Parent.class ) ) { + if ( propertyHolder.isComponent() ) { + propertyHolder.setParentProperty( property.getName() ); + } + else { + throw new AnnotationException("@Parent cannot be applied outside an embeddable object: " + + StringHelper.qualify( propertyHolder.getPath(), property.getName() ) ); + } + return; + } + //process @JoinColumn(s) before @Column(s) to handle collection of elements properly { JoinColumn[] anns = null; @@ -1085,9 +1097,9 @@ localGenerators.putAll( buildLocalGenerators( property, mappings ) ); //manage composite related metadata - Embeddable embeddableAnn = returnedClass.getAnnotation( Embeddable.class ); //guess if its a component and find id data access (property, field etc) - final boolean isComponent = embeddableAnn != null || property.isAnnotationPresent( EmbeddedId.class ); + final boolean isComponent = returnedClass.isAnnotationPresent( Embeddable.class ) + || property.isAnnotationPresent( EmbeddedId.class ); boolean propertyAnnotated = entityBinder.isPropertyAnnotated( returnedClass ); String propertyAccessor = entityBinder.getPropertyAccessor( returnedClass ); //if ( isComponent && embeddableAnn != null && embeddableAnn.access() == AccessType.FIELD ) propertyAccess = false; Modified: trunk/HibernateExt/metadata/src/java/org/hibernate/cfg/ComponentPropertyHolder.java =================================================================== --- trunk/HibernateExt/metadata/src/java/org/hibernate/cfg/ComponentPropertyHolder.java 2006-04-27 17:14:58 UTC (rev 9820) +++ trunk/HibernateExt/metadata/src/java/org/hibernate/cfg/ComponentPropertyHolder.java 2006-04-27 21:12:40 UTC (rev 9821) @@ -80,6 +80,10 @@ return true; } + public void setParentProperty(String parentProperty) { + component.setParentProperty( parentProperty ); + } + @Override public Column[] getOverriddenColumn(String propertyName) { //FIXME this is yukky Modified: trunk/HibernateExt/metadata/src/java/org/hibernate/cfg/PropertyHolder.java =================================================================== --- trunk/HibernateExt/metadata/src/java/org/hibernate/cfg/PropertyHolder.java 2006-04-27 17:14:58 UTC (rev 9820) +++ trunk/HibernateExt/metadata/src/java/org/hibernate/cfg/PropertyHolder.java 2006-04-27 21:12:40 UTC (rev 9821) @@ -26,6 +26,8 @@ boolean isComponent(); + void setParentProperty(String parentProperty); + String getPath(); /** Modified: trunk/HibernateExt/metadata/src/test/org/hibernate/test/annotations/collectionelement/CollectionElementTest.java =================================================================== --- trunk/HibernateExt/metadata/src/test/org/hibernate/test/annotations/collectionelement/CollectionElementTest.java 2006-04-27 17:14:58 UTC (rev 9820) +++ trunk/HibernateExt/metadata/src/test/org/hibernate/test/annotations/collectionelement/CollectionElementTest.java 2006-04-27 21:12:40 UTC (rev 9821) @@ -65,6 +65,7 @@ boy = (Boy) s.get( Boy.class, boy.getId() ); assertNotNull( boy.getFavoriteToys() ); assertTrue( boy.getFavoriteToys().contains( toy ) ); + assertEquals( "@Parent is failing", boy, boy.getFavoriteToys().iterator().next().getOwner() ); s.delete( boy ); tx.commit(); s.close(); Modified: trunk/HibernateExt/metadata/src/test/org/hibernate/test/annotations/collectionelement/Toy.java =================================================================== --- trunk/HibernateExt/metadata/src/test/org/hibernate/test/annotations/collectionelement/Toy.java 2006-04-27 17:14:58 UTC (rev 9820) +++ trunk/HibernateExt/metadata/src/test/org/hibernate/test/annotations/collectionelement/Toy.java 2006-04-27 21:12:40 UTC (rev 9821) @@ -5,6 +5,8 @@ import javax.persistence.Column; import javax.persistence.Embeddable; +import org.hibernate.annotations.Parent; + /** * @author Emmanuel Bernard */ @@ -13,6 +15,7 @@ private String name; private Brand brand; private String serial; + private Boy owner; @AttributeOverride(name = "name", column = @Column(name = "brand_name")) public Brand getBrand() { @@ -39,6 +42,15 @@ this.serial = serial; } + @Parent + public Boy getOwner() { + return owner; + } + + public void setOwner(Boy owner) { + this.owner = owner; + } + public boolean equals(Object o) { if ( this == o ) return true; if ( o == null || getClass() != o.getClass() ) return false; Modified: trunk/HibernateExt/metadata/src/test/org/hibernate/test/annotations/embedded/EmbeddedTest.java =================================================================== --- trunk/HibernateExt/metadata/src/test/org/hibernate/test/annotations/embedded/EmbeddedTest.java 2006-04-27 17:14:58 UTC (rev 9820) +++ trunk/HibernateExt/metadata/src/test/org/hibernate/test/annotations/embedded/EmbeddedTest.java 2006-04-27 21:12:40 UTC (rev 9821) @@ -269,6 +269,31 @@ s.close(); } + public void testParent() throws Exception { + Session s; + s = openSession(); + s.getTransaction().begin(); + Book book = new Book(); + book.setIsbn( "1234" ); + book.setName( "HiA Second Edition" ); + Summary summary = new Summary(); + summary.setText( "This is a HiA SE summary" ); + summary.setSize( summary.getText().length() ); + book.setSummary( summary ); + s.persist( book ); + s.getTransaction().commit(); + + s.clear(); + + Transaction tx = s.beginTransaction(); + Book loadedBook = (Book) s.get( Book.class, book.getIsbn() ); + assertNotNull( loadedBook.getSummary() ); + assertEquals( loadedBook, loadedBook.getSummary().getSummarizedBook() ); + s.delete( loadedBook ); + tx.commit(); + s.close(); + } + public void testEmbeddedAndMultipleManyToOne() throws Exception { Session s; s = openSession(); Modified: trunk/HibernateExt/metadata/src/test/org/hibernate/test/annotations/embedded/Summary.java =================================================================== --- trunk/HibernateExt/metadata/src/test/org/hibernate/test/annotations/embedded/Summary.java 2006-04-27 17:14:58 UTC (rev 9820) +++ trunk/HibernateExt/metadata/src/test/org/hibernate/test/annotations/embedded/Summary.java 2006-04-27 21:12:40 UTC (rev 9821) @@ -3,6 +3,8 @@ import javax.persistence.Embeddable; +import org.hibernate.annotations.Parent; + /** * @author Emmanuel Bernard */ @@ -10,6 +12,7 @@ public class Summary { private int size; private String text; + private Book summarizedBook; public int getSize() { return size; @@ -26,4 +29,13 @@ public void setText(String text) { this.text = text; } + + @Parent + public Book getSummarizedBook() { + return summarizedBook; + } + + public void setSummarizedBook(Book summarizedBook) { + this.summarizedBook = summarizedBook; + } } |
From: <hib...@li...> - 2006-04-27 17:15:02
|
Author: epbernard Date: 2006-04-27 13:14:58 -0400 (Thu, 27 Apr 2006) New Revision: 9820 Modified: trunk/HibernateExt/metadata/src/java/org/hibernate/cfg/annotations/EntityBinder.java trunk/HibernateExt/metadata/src/test/org/hibernate/test/annotations/EntityTest.java Log: ANN-330 Modified: trunk/HibernateExt/metadata/src/java/org/hibernate/cfg/annotations/EntityBinder.java =================================================================== --- trunk/HibernateExt/metadata/src/java/org/hibernate/cfg/annotations/EntityBinder.java 2006-04-27 17:02:51 UTC (rev 9819) +++ trunk/HibernateExt/metadata/src/java/org/hibernate/cfg/annotations/EntityBinder.java 2006-04-27 17:14:58 UTC (rev 9820) @@ -296,7 +296,7 @@ private String getClassTableName(String tableName) { if ( StringHelper.isEmpty( tableName ) ) { - return mappings.getNamingStrategy().classToTableName( persistentClass.getEntityName() ); + return mappings.getNamingStrategy().classToTableName( name ); } else { return mappings.getNamingStrategy().tableName( tableName ); @@ -310,7 +310,7 @@ ) { String logicalName = StringHelper.isNotEmpty( tableName ) ? tableName : - StringHelper.unqualify( persistentClass.getEntityName() ); + StringHelper.unqualify( name ); Table table = TableBinder.fillTable( schema, catalog, getClassTableName( tableName ), Modified: trunk/HibernateExt/metadata/src/test/org/hibernate/test/annotations/EntityTest.java =================================================================== --- trunk/HibernateExt/metadata/src/test/org/hibernate/test/annotations/EntityTest.java 2006-04-27 17:02:51 UTC (rev 9819) +++ trunk/HibernateExt/metadata/src/test/org/hibernate/test/annotations/EntityTest.java 2006-04-27 17:14:58 UTC (rev 9820) @@ -24,6 +24,8 @@ public void testLoad() throws Exception { //put an object in DB + assertEquals( "Flight", getCfg().getClassMapping( Flight.class.getName() ).getTable().getName() ); + Session s = openSession(); Transaction tx = s.beginTransaction(); Flight firstOne = new Flight(); @@ -257,6 +259,7 @@ } public void testEntityName() throws Exception { + assertEquals( "Corporation", getCfg().getClassMapping( Company.class.getName() ).getTable().getName() ); Session s = openSession(); Transaction tx = s.beginTransaction(); Company comp = new Company(); |
From: <hib...@li...> - 2006-04-27 17:02:55
|
Author: epbernard Date: 2006-04-27 13:02:51 -0400 (Thu, 27 Apr 2006) New Revision: 9819 Added: tags/entitymanager_v31beta8b/HibernateExt/ Log: version "b" Copied: tags/entitymanager_v31beta8b/HibernateExt (from rev 9818, trunk/HibernateExt) |
From: <hib...@li...> - 2006-04-27 17:02:19
|
Author: epbernard Date: 2006-04-27 13:02:17 -0400 (Thu, 27 Apr 2006) New Revision: 9818 Added: tags/annotations_v31beta10b/HibernateExt/ Log: version "b" Copied: tags/annotations_v31beta10b/HibernateExt (from rev 9817, trunk/HibernateExt) |
From: <hib...@li...> - 2006-04-27 17:01:45
|
Author: epbernard Date: 2006-04-27 13:01:44 -0400 (Thu, 27 Apr 2006) New Revision: 9817 Added: tags/entitymanager_v31beta8b/ Log: version "b" |
From: <hib...@li...> - 2006-04-27 17:01:30
|
Author: epbernard Date: 2006-04-27 13:01:24 -0400 (Thu, 27 Apr 2006) New Revision: 9816 Added: tags/annotations_v31beta10b/ Log: version "b" |
From: <hib...@li...> - 2006-04-27 16:59:27
|
Author: epbernard Date: 2006-04-27 12:59:23 -0400 (Thu, 27 Apr 2006) New Revision: 9815 Modified: trunk/HibernateExt/ejb/lib/hibernate-annotations.jar Log: Modified: trunk/HibernateExt/ejb/lib/hibernate-annotations.jar =================================================================== (Binary files differ) |
From: <hib...@li...> - 2006-04-27 15:15:51
|
Author: epbernard Date: 2006-04-27 11:15:44 -0400 (Thu, 27 Apr 2006) New Revision: 9814 Modified: trunk/HibernateExt/ejb/changelog.txt trunk/HibernateExt/ejb/src/java/org/hibernate/ejb/Ejb3Configuration.java trunk/HibernateExt/ejb/src/java/org/hibernate/ejb/Version.java Log: version b Modified: trunk/HibernateExt/ejb/changelog.txt =================================================================== --- trunk/HibernateExt/ejb/changelog.txt 2006-04-27 15:15:03 UTC (rev 9813) +++ trunk/HibernateExt/ejb/changelog.txt 2006-04-27 15:15:44 UTC (rev 9814) @@ -1,10 +1,11 @@ Hibernate EntityManager Changelog ================================== -3.1.0.Beta8 (26-04-2006) ------------------------- +3.1.0.Beta8b (27-04-2006) +------------------------- ** Bug + * [EJB-121] - FileZippedJarVisitor can not handle URL with white spaces in windows XP professional. * [EJB-155] - assumes Map.Entry where string is returned * [EJB-156] - Setting a transaction factory raise an assertion failure * [EJB-166] - StaleObjectStaleException not wrapped into an optimisticLockException when merge is used Modified: trunk/HibernateExt/ejb/src/java/org/hibernate/ejb/Ejb3Configuration.java =================================================================== --- trunk/HibernateExt/ejb/src/java/org/hibernate/ejb/Ejb3Configuration.java 2006-04-27 15:15:03 UTC (rev 9813) +++ trunk/HibernateExt/ejb/src/java/org/hibernate/ejb/Ejb3Configuration.java 2006-04-27 15:15:44 UTC (rev 9814) @@ -76,6 +76,7 @@ private SettingsFactory settingsFactory; private EventListenerConfigurator listenerConfigurator; private PersistenceUnitTransactionType transactionType; + private static final String META_INF_ORM_XML = "META-INF/orm.xml"; public Ejb3Configuration() { settingsFactory = new InjectionSettingsFactory(); @@ -258,6 +259,7 @@ List<String> packages = new ArrayList<String>(); List<String> xmlFiles = new ArrayList<String>( 50 ); if ( info.getMappingFileNames() != null ) xmlFiles.addAll( info.getMappingFileNames() ); + if ( ! xmlFiles.contains( META_INF_ORM_XML ) ) xmlFiles.add( META_INF_ORM_XML ); // Object overridenTxType = integration.get( HibernatePersistence.TRANSACTION_TYPE ); // if (overridenTxType != null) { // defineTransactionType( overridenTxType, info.getPersistenceUnitName() ); @@ -395,14 +397,14 @@ if ( result[1] ) { filters[size - 1] = new JarVisitor.FileFilter( true ) { public boolean accept(String javaElementName) { - return javaElementName.endsWith( "hbm.xml" ) || javaElementName.endsWith( "META-INF/orm.xml" ); + return javaElementName.endsWith( "hbm.xml" ) || javaElementName.endsWith( META_INF_ORM_XML ); } }; } else { filters[size - 1] = new JarVisitor.FileFilter( true ) { public boolean accept(String javaElementName) { - return javaElementName.endsWith( "META-INF/orm.xml" ); + return javaElementName.endsWith( META_INF_ORM_XML ); } }; } Modified: trunk/HibernateExt/ejb/src/java/org/hibernate/ejb/Version.java =================================================================== --- trunk/HibernateExt/ejb/src/java/org/hibernate/ejb/Version.java 2006-04-27 15:15:03 UTC (rev 9813) +++ trunk/HibernateExt/ejb/src/java/org/hibernate/ejb/Version.java 2006-04-27 15:15:44 UTC (rev 9814) @@ -8,7 +8,7 @@ * @author Emmanuel Bernard */ public class Version { - public static String VERSION = "3.1.0.Beta8"; + public static String VERSION = "3.1.0.Beta8b"; private static Log log = LogFactory.getLog( Version.class ); static { |
From: <hib...@li...> - 2006-04-27 15:15:13
|
Author: epbernard Date: 2006-04-27 11:15:03 -0400 (Thu, 27 Apr 2006) New Revision: 9813 Modified: trunk/HibernateExt/metadata/changelog.txt trunk/HibernateExt/metadata/src/java/org/hibernate/cfg/annotations/CollectionBinder.java trunk/HibernateExt/metadata/src/java/org/hibernate/cfg/annotations/Version.java Log: ANN-328 and version b Modified: trunk/HibernateExt/metadata/changelog.txt =================================================================== --- trunk/HibernateExt/metadata/changelog.txt 2006-04-27 15:05:54 UTC (rev 9812) +++ trunk/HibernateExt/metadata/changelog.txt 2006-04-27 15:15:03 UTC (rev 9813) @@ -1,8 +1,8 @@ Hibernate Annotations Changelog =============================== -3.1.0.Beta10 Preview (26-04-2006) ---------------------------------- +3.1.0.Beta10b Preview (27-04-2006) +---------------------------------- ** Bug * [ANN-292] - @EmbeddedId object containing only @ManyToOne fails / wrong pk generation when@EmbeddedId contains @ManyToOne * [ANN-295] - Generators behave like allocationSize+1 @@ -10,6 +10,7 @@ * [ANN-301] - Validator won't validate "new" (=transient) bean when bean is CGLIB-instrumented * [ANN-319] - Make Hibernate Annotations types Serializable and thread safe * [ANN-321] - Discriminator column wo @DiscriminatorColumn has the wrong varchar length + * [ANN-328] - @javax.persistence.MapKey broken ** Improvement Modified: trunk/HibernateExt/metadata/src/java/org/hibernate/cfg/annotations/CollectionBinder.java =================================================================== --- trunk/HibernateExt/metadata/src/java/org/hibernate/cfg/annotations/CollectionBinder.java 2006-04-27 15:05:54 UTC (rev 9812) +++ trunk/HibernateExt/metadata/src/java/org/hibernate/cfg/annotations/CollectionBinder.java 2006-04-27 15:15:03 UTC (rev 9813) @@ -254,8 +254,8 @@ log.debug( "Collection role: " + StringHelper.qualify( propertyHolder.getPath(), propertyName ) ); collection.setRole( StringHelper.qualify( propertyHolder.getPath(), propertyName ) ); - if (mapKeyColumns != null && mapKeyPropertyName != null) { - throw new AnnotationException("Cannot mix @javax.persistence.MakKey and @org.hibernate.annotations.MapKey " + if (property.isAnnotationPresent( org.hibernate.annotations.MapKey.class) && mapKeyPropertyName != null) { + throw new AnnotationException("Cannot mix @javax.persistence.MapKey and @org.hibernate.annotations.MapKey " + "on the same collection: " + StringHelper.qualify( propertyHolder.getPath(), propertyName ) ); } Modified: trunk/HibernateExt/metadata/src/java/org/hibernate/cfg/annotations/Version.java =================================================================== --- trunk/HibernateExt/metadata/src/java/org/hibernate/cfg/annotations/Version.java 2006-04-27 15:05:54 UTC (rev 9812) +++ trunk/HibernateExt/metadata/src/java/org/hibernate/cfg/annotations/Version.java 2006-04-27 15:15:03 UTC (rev 9813) @@ -8,7 +8,7 @@ * @author Emmanuel Bernard */ public class Version { - public static String VERSION = "3.1.0.Beta10"; + public static String VERSION = "3.1.0.Beta10b"; private static Log log = LogFactory.getLog( Version.class ); static { |
From: <hib...@li...> - 2006-04-27 15:05:56
|
Author: epbernard Date: 2006-04-27 11:05:54 -0400 (Thu, 27 Apr 2006) New Revision: 9812 Modified: trunk/HibernateExt/ejb/src/java/org/hibernate/ejb/packaging/FileZippedJarVisitor.java Log: EJB-121 Modified: trunk/HibernateExt/ejb/src/java/org/hibernate/ejb/packaging/FileZippedJarVisitor.java =================================================================== --- trunk/HibernateExt/ejb/src/java/org/hibernate/ejb/packaging/FileZippedJarVisitor.java 2006-04-27 13:01:46 UTC (rev 9811) +++ trunk/HibernateExt/ejb/src/java/org/hibernate/ejb/packaging/FileZippedJarVisitor.java 2006-04-27 15:05:54 UTC (rev 9812) @@ -4,6 +4,7 @@ import java.io.BufferedInputStream; import java.io.IOException; import java.net.URL; +import java.net.URISyntaxException; import java.util.Enumeration; import java.util.jar.JarFile; import java.util.zip.ZipEntry; @@ -30,12 +31,16 @@ protected void doProcessElements() throws IOException { JarFile jarFile; try { - jarFile = new JarFile( jarUrl.getFile() ); + jarFile = new JarFile( jarUrl.toURI().getPath() ); } catch (IOException ze) { log.warn( "Unable to find file (ignored): " + jarUrl, ze ); return; } + catch (URISyntaxException e) { + log.warn( "Malformed url: " + jarUrl, e ); + return; + } Enumeration<? extends ZipEntry> entries = jarFile.entries(); while ( entries.hasMoreElements() ) { ZipEntry entry = entries.nextElement(); |
From: <hib...@li...> - 2006-04-27 13:01:59
|
Author: epbernard Date: 2006-04-27 09:01:46 -0400 (Thu, 27 Apr 2006) New Revision: 9811 Added: trunk/HibernateExt/metadata/src/test/org/hibernate/test/annotations/id/BreakDance.java Modified: trunk/HibernateExt/metadata/src/test/org/hibernate/test/annotations/id/IdTest.java Log: more tests on allocationSize Added: trunk/HibernateExt/metadata/src/test/org/hibernate/test/annotations/id/BreakDance.java =================================================================== --- trunk/HibernateExt/metadata/src/test/org/hibernate/test/annotations/id/BreakDance.java 2006-04-27 03:35:06 UTC (rev 9810) +++ trunk/HibernateExt/metadata/src/test/org/hibernate/test/annotations/id/BreakDance.java 2006-04-27 13:01:46 UTC (rev 9811) @@ -0,0 +1,27 @@ +//$Id: $ +package org.hibernate.test.annotations.id; + +import javax.persistence.Entity; +import javax.persistence.Id; +import javax.persistence.GeneratedValue; +import javax.persistence.TableGenerator; +import javax.persistence.GenerationType; + +/** + * @author Emmanuel Bernard + */ +@Entity +public class BreakDance { + @Id + @GeneratedValue(generator = "memencoIdGen", strategy = GenerationType.TABLE) + @TableGenerator( + name = "memencoIdGen", + table = "hi_id_key", + pkColumnName = "id_key", + valueColumnName = "next_hi", + pkColumnValue = "issue", + allocationSize = 1 + ) + public Integer id; + public String name; +} Modified: trunk/HibernateExt/metadata/src/test/org/hibernate/test/annotations/id/IdTest.java =================================================================== --- trunk/HibernateExt/metadata/src/test/org/hibernate/test/annotations/id/IdTest.java 2006-04-27 03:35:06 UTC (rev 9810) +++ trunk/HibernateExt/metadata/src/test/org/hibernate/test/annotations/id/IdTest.java 2006-04-27 13:01:46 UTC (rev 9811) @@ -226,6 +226,25 @@ assertEquals( "ball_id", idCol.getName() ); } + public void testLowAllocationSize() throws Exception { + Session s; + Transaction tx; + s = openSession(); + tx = s.beginTransaction(); + int size = 4; + BreakDance[] bds = new BreakDance[size]; + for (int i = 0 ; i < size ; i++) { + bds[i] = new BreakDance(); + s.persist( bds[i] ); + } + s.flush(); + for (int i = 0 ; i < size ; i++) { + assertEquals(i + 1, bds[i].id.intValue() ); + } + tx.rollback(); + s.close(); + } + /** * @see org.hibernate.test.annotations.TestCase#getMappings() */ @@ -244,7 +263,8 @@ Footballer.class, SoundSystem.class, Furniture.class, - GoalKeeper.class + GoalKeeper.class, + BreakDance.class }; } |
From: <hib...@li...> - 2006-04-27 03:35:17
|
Author: epbernard Date: 2006-04-26 23:35:06 -0400 (Wed, 26 Apr 2006) New Revision: 9810 Added: tags/entitymanager_v31beta8/HibernateExt/ Log: tag release Copied: tags/entitymanager_v31beta8/HibernateExt (from rev 9809, trunk/HibernateExt) |