From: Vance K. <va...@us...> - 2007-06-30 03:53:47
|
User: vancek Date: 07/06/29 20:53:48 Modified: andromda-ejb3/src/site changes.xml andromda-ejb3/src/main/java/org/andromda/cartridges/ejb3/metafacades EJB3AssociationFacadeLogicImpl.java EJB3MetafacadeUtils.java andromda-ejb3/src/test/expected cartridge-output.zip andromda-ejb3/src/test/uml EJB3CartridgeTestModel.xml.zip andromda-ejb3/src/main/resources/templates/ejb3 EntityEmbeddable.vsl andromda-ejb3/src/site/axdoc howto.xml howto2.xml Log: ejb-50 - add join table for one-to-many unidirectional associations Revision Changes Path 1.24 +17 -1 cartridges/andromda-ejb3/src/site/changes.xml Index: changes.xml =================================================================== RCS file: /cvsroot/andromdaplugins/cartridges/andromda-ejb3/src/site/changes.xml,v retrieving revision 1.23 retrieving revision 1.24 diff -u -w -r1.23 -r1.24 --- changes.xml 23 Jun 2007 09:07:35 -0000 1.23 +++ changes.xml 30 Jun 2007 03:53:47 -0000 1.24 @@ -484,11 +484,27 @@ <action dev="vancek" due-to="heapifyman" type="add"> JIRA EJB-56 - Add support for multiplicity on enumeration types. </action> - <action dev="vancek" tue-to="mrkanban" type="fix"> + <action dev="vancek" due-to="mrkanban" type="fix"> When a child entity inherits from a mapped superclass and the child entity has an implementation, the child mapped superclass did not extend the parent mapped superclass correctly. This was a side-effect of applying EJB-53. </action> + <action dev="vancek" due-to="darquerus " type="add"> + JIRA EJB-59 - Add support for setting the join table for unidirectional one-to-many associations. Currently, + this exists for many-to-many associations using the JoinTable annotation. + Existing users must be aware that this will change the default behaviour of the cartridge for the join + table name. The EJB 3.0 spec defines the join table name with the owning side first and underscore + separated. AndroMDA (not the EJB3 cartridge) defines the inverse end first with a digit two (2) as the + separater and truncates the name by the specified length in the andromda.xml namespace property + maxSqlNameLength. Prior to this change (lack of a JoinTable annotation), the EJB 3.0 default name was + used for one-to-many associations and the AndroMDA naming convention was used for many-to-many associations. + We are now adopting the the EJB 3.0 naming convention for join table names for both association types. + To avoid recreation of join tables for existing many-to-many associations, you have the choice of specifying + the @andromda.persistence.table tagged value on the specific associations or setting the association name + to correspond to the join table. You should also define the namespace property + relationNameSeparator in the andromda.xml within the ejb3 namespace with a value of underscore (_) if you + wish to adopt this separator. The default separator will remain the AndroMDA default digit two. + </action> </release> </body> </document> \ No newline at end of file 1.5 +96 -4 cartridges/andromda-ejb3/src/main/java/org/andromda/cartridges/ejb3/metafacades/EJB3AssociationFacadeLogicImpl.java Index: EJB3AssociationFacadeLogicImpl.java =================================================================== RCS file: /cvsroot/andromdaplugins/cartridges/andromda-ejb3/src/main/java/org/andromda/cartridges/ejb3/metafacades/EJB3AssociationFacadeLogicImpl.java,v retrieving revision 1.4 retrieving revision 1.5 diff -u -w -r1.4 -r1.5 --- EJB3AssociationFacadeLogicImpl.java 17 Jan 2007 00:50:55 -0000 1.4 +++ EJB3AssociationFacadeLogicImpl.java 30 Jun 2007 03:53:47 -0000 1.5 @@ -1,5 +1,18 @@ package org.andromda.cartridges.ejb3.metafacades; +import java.util.Collection; +import java.util.Iterator; + +import org.andromda.metafacades.uml.AssociationEndFacade; +import org.andromda.metafacades.uml.Entity; +import org.andromda.metafacades.uml.EntityMetafacadeUtils; +import org.andromda.metafacades.uml.MetafacadeUtils; +import org.andromda.metafacades.uml.ModelElementFacade; +import org.andromda.metafacades.uml.UMLMetafacadeProperties; +import org.andromda.metafacades.uml.UMLProfile; +import org.apache.commons.lang.ObjectUtils; +import org.apache.commons.lang.StringUtils; + /** * MetafacadeLogic implementation for org.andromda.cartridges.ejb3.metafacades.EJB3AssociationFacade. * @@ -19,15 +32,94 @@ // --------------- methods --------------------- /** + * Override to provide support for One-2-Many unidirectional associations as well as Many-2-Many. + * * Returns the EJB3 cartridge specific table name for the association */ public String getTableName() { - String tableName = super.getTableName(); - if (getName().toLowerCase().startsWith(tableName.toLowerCase())) + String tableName = null; + final Collection ends = this.getAssociationEnds(); + if (ends != null && !ends.isEmpty()) + { + for (Iterator iterator = ends.iterator(); iterator.hasNext();) { - tableName = getRelationName().replaceAll("-", "_").toUpperCase(); + final EJB3AssociationEndFacade end = (EJB3AssociationEndFacade)iterator.next(); + if ((end.isMany2Many() && end.isOwning()) || + (end.isOne2Many() && !end.isNavigable() && end.getOtherEnd().isNavigable())) + { + // prevent ClassCastException if the association isn't an + // Entity + if (Entity.class.isAssignableFrom(end.getType().getClass())) + { + final String prefixProperty = UMLMetafacadeProperties.TABLE_NAME_PREFIX; + final String tableNamePrefix = + this.isConfiguredProperty(prefixProperty) + ? ObjectUtils.toString(this.getConfiguredProperty(prefixProperty)) : null; + tableName = + EJB3MetafacadeUtils.getSqlNameFromTaggedValue( + tableNamePrefix, + this, + UMLProfile.TAGGEDVALUE_PERSISTENCE_TABLE, + ((Entity)end.getType()).getMaxSqlNameLength(), + null, + this.getConfiguredProperty(UMLMetafacadeProperties.SQL_NAME_SEPARATOR)); + } + break; + } } + } + +// if (StringUtils.isNotBlank(tableName) && getName().toLowerCase().startsWith(tableName.toLowerCase())) +// { +// tableName = getRelationName().replaceAll("-", "_").toUpperCase(); +// } + return tableName; } + + /** + * Override the default implementation to use the current getRelationName implementation + */ + public String getName() + { + String name = (super.getName().equalsIgnoreCase(super.getRelationName()) ? null : super.getName()); + + // if the name isn't defined, use the this implementation of relation name + if (StringUtils.isEmpty(name)) + { + name = this.getRelationName(); + } + return name; + } + + /** + * Override the default implementation to set the owning side name first followed by inverse side. + * If there is no owning side defined, then adopt the default logic of using alphabetical ordering. + */ + public String getRelationName() + { + final Collection ends = this.getAssociationEnds(); + final Iterator endIt = ends.iterator(); + final EJB3AssociationEndFacade firstEnd = (EJB3AssociationEndFacade)endIt.next(); + final EJB3AssociationEndFacade secondEnd = (EJB3AssociationEndFacade)endIt.next(); + final String separator = String.valueOf( + this.getConfiguredProperty(UMLMetafacadeProperties.RELATION_NAME_SEPARATOR)); + + if (secondEnd.isOwning()) + { + return secondEnd.getName() + separator + firstEnd.getName(); + } + else if (firstEnd.isOwning()) + { + return firstEnd.getName() + separator + secondEnd.getName(); + } + else + { + return MetafacadeUtils.toRelationName( + firstEnd.getName(), + secondEnd.getName(), + separator); + } + } } \ No newline at end of file 1.11 +65 -0 cartridges/andromda-ejb3/src/main/java/org/andromda/cartridges/ejb3/metafacades/EJB3MetafacadeUtils.java Index: EJB3MetafacadeUtils.java =================================================================== RCS file: /cvsroot/andromdaplugins/cartridges/andromda-ejb3/src/main/java/org/andromda/cartridges/ejb3/metafacades/EJB3MetafacadeUtils.java,v retrieving revision 1.10 retrieving revision 1.11 diff -u -w -r1.10 -r1.11 --- EJB3MetafacadeUtils.java 16 Apr 2007 14:09:41 -0000 1.10 +++ EJB3MetafacadeUtils.java 30 Jun 2007 03:53:47 -0000 1.11 @@ -5,6 +5,7 @@ import org.andromda.core.common.ExceptionUtils; import org.andromda.metafacades.uml.AttributeFacade; import org.andromda.metafacades.uml.ClassifierFacade; +import org.andromda.metafacades.uml.EntityMetafacadeUtils; import org.andromda.metafacades.uml.ModelElementFacade; import org.andromda.metafacades.uml.OperationFacade; import org.andromda.metafacades.uml.UMLProfile; @@ -504,4 +505,68 @@ return buf.toString(); } } + + /** + * Gets the SQL name. (i.e. column name, table name, etc.). If it can't find + * the corresponding tagged value with the specified <code>name</code>, + * then it uses the element name by default and just returns that. + * + * @param prefix the optional prefix to add to the sql name (i.e. table name + * prefix, etc.). + * @param element from which to retrieve the SQL name. + * @param name the name of the tagged value. + * @param nameMaxLength if this is not null, then the name returned will be + * trimmed to this length (if it happens to be longer). + * @param suffix the optional suffix to add to the sql name (i.e. foreign + * key suffix, etc.) + * @param separator character used to separate words + * @return the SQL name as a String. + */ + public static String getSqlNameFromTaggedValue( + String prefix, + final EJB3AssociationFacade element, + String name, + final Short nameMaxLength, + String suffix, + final Object separator) + { + if (element != null) + { + Object value = element.findTaggedValue(name); + StringBuffer buffer = new StringBuffer(StringUtils.trimToEmpty((String)value)); + if (StringUtils.isEmpty(buffer.toString())) + { + // if we can't find the tagValue then use the + // element name for the name + buffer = new StringBuffer( + EntityMetafacadeUtils.toSqlName( + element.getName(), + separator)); + + suffix = StringUtils.trimToEmpty(suffix); + prefix = StringUtils.trimToEmpty(prefix); + if (nameMaxLength != null) + { + final short maxLength = (short)(nameMaxLength.shortValue() - suffix.length() - prefix.length()); + buffer = + new StringBuffer( + EntityMetafacadeUtils.ensureMaximumNameLength( + buffer.toString(), + new Short(maxLength))); + } + if (StringUtils.isNotBlank(prefix)) + { + buffer.insert( + 0, + prefix); + } + if (StringUtils.isNotBlank(suffix)) + { + buffer.append(suffix); + } + } + name = buffer.toString(); + } + return name; + } } \ No newline at end of file 1.14 +499 -492 cartridges/andromda-ejb3/src/test/expected/cartridge-output.zip <<Binary file>> 1.9 +249 -258 cartridges/andromda-ejb3/src/test/uml/EJB3CartridgeTestModel.xml.zip <<Binary file>> 1.54 +7 -0 cartridges/andromda-ejb3/src/main/resources/templates/ejb3/EntityEmbeddable.vsl Index: EntityEmbeddable.vsl =================================================================== RCS file: /cvsroot/andromdaplugins/cartridges/andromda-ejb3/src/main/resources/templates/ejb3/EntityEmbeddable.vsl,v retrieving revision 1.53 retrieving revision 1.54 diff -u -w -r1.53 -r1.54 --- EntityEmbeddable.vsl 23 Jun 2007 09:07:36 -0000 1.53 +++ EntityEmbeddable.vsl 30 Jun 2007 03:53:48 -0000 1.54 @@ -628,6 +628,13 @@ #* *##else @javax.persistence.OneToMany(#if ($target.cascadeType)cascade = {${target.cascadeType}}#set ($argExists = true)#end#if ($associationEnd.navigable)#if ($argExists) ,#end#**#mappedBy = "${associationEnd.name}"#set ($argExists = true)#end#if ($target.eager)#if ($argExists), #end#**#fetch = javax.persistence.FetchType.EAGER#end) #* *##end +## +## Set the JointTable annotation to limit the association table name length. +## This is only set if the relationship is unidirectional. +## +#* *##if (!$associationEnd.navigable && $target.navigable) + @javax.persistence.JoinTable(name = "${associationEnd.association.tableName}") +#* *##end #* *##if ($target.map) @javax.persistence.MapKey#if ($target.hasTaggedValue("@andromda.persistence.collection.index"))(name = "${target.collectionIndexName}")#end 1.5 +1 -1 cartridges/andromda-ejb3/src/site/axdoc/howto.xml Index: howto.xml =================================================================== RCS file: /cvsroot/andromdaplugins/cartridges/andromda-ejb3/src/site/axdoc/howto.xml,v retrieving revision 1.4 retrieving revision 1.5 diff -u -w -r1.4 -r1.5 --- howto.xml 4 Feb 2007 04:18:18 -0000 1.4 +++ howto.xml 30 Jun 2007 03:53:48 -0000 1.5 @@ -67,7 +67,7 @@ <li><a href="howto2.html#Cascading">Cascading</a></li> <li><a href="howto2.html#Fetch_Type">Fetch Type</a></li> <li><a href="howto2.html#Ordering_Collection_Valued_Association">Ordering Collection Valued Association</a></li> - <li><a href="howto2.html#Join_Table_Many_To_Many">Join Table for Many-To-Many Relationship</a></li> + <li><a href="howto2.html#Join_Table_Many_To_Many_And_One_To_Many">Join Table for Many-To-Many and One-To-Many Relationships</a></li> <li><a href="howto2.html#Aggregation_Composition">Aggregation and Composition</a></li> <li><a href="howto2.html#Transient_Relationships">Transient Relationships</a></li> <li><a href="howto2.html#Tips">Tips</a></li> 1.4 +20 -7 cartridges/andromda-ejb3/src/site/axdoc/howto2.xml Index: howto2.xml =================================================================== RCS file: /cvsroot/andromdaplugins/cartridges/andromda-ejb3/src/site/axdoc/howto2.xml,v retrieving revision 1.3 retrieving revision 1.4 diff -u -w -r1.3 -r1.4 --- howto2.xml 7 May 2007 13:50:26 -0000 1.3 +++ howto2.xml 30 Jun 2007 03:53:48 -0000 1.4 @@ -264,18 +264,31 @@ </ul> </p> </subsection> - <a name="Join_Table_Many_To_Many"/> - <subsection name="Join Table for Many-To-Many Relationship"> + <a name="Join_Table_Many_To_Many_And_One_To_Many"/> + <subsection name="Join Table for Many-To-Many and One-To-Many Relationship"> <p> - For a Many-To-Many association, the <code>@javax.persistence.JoinTable</code> annotation - is specified on the OWNING side of the association. This is determined by modelling the + For a Many-To-Many and now One-To-Many association, the <code>@javax.persistence.JoinTable</code> + annotation is specified on the OWNING side of the association. This is determined by modeling the <code>owning</code> side as an aggregation or composition. </p> <p> - The join table name is defined by default to be the table name of the primary table of owning + If there is no owning side defined, then the AndroMDA default convention of + an alphabetical name ordering is adopted. + </p> + <p> + The join table name is defined by default to be the table name of the primary table of the owning side concatenated with the table name of the primary table of the inverse side. - You can override the <code>name</code> property by modelling the - <code>@andromda.persistence.table</code> tagged value on the assocation. + You can override the <code>name</code> property by modeling the + <code>@andromda.persistence.table</code> tagged value on the assocation or alternatively, + specify a name for the association. + </p> + <p> + The default relation name separator is adopted from the AndroMDA metafacade namespace layer. + You can simply change this in your application's andromda.xml by specifying the following + property in the <b>ejb3</b> namespace. +<source language="java"><![CDATA[ + <property name="relationNameSeparator">_</property> +]]></source> </p> </subsection> <a name="Aggregation_Composition"/> |
From: Vance K. <va...@us...> - 2007-08-21 14:27:18
|
User: vancek Date: 07/08/21 07:27:20 Modified: andromda-ejb3/src/site/fml faq.fml andromda-ejb3/src/site changes.xml andromda-ejb3 pom.xml andromda-ejb3/src/main/java/org/andromda/cartridges/ejb3/metafacades EJB3AssociationEndFacadeLogicImpl.java andromda-ejb3/src/test/expected cartridge-output.zip andromda-ejb3/src/test/uml EJB3CartridgeTestModel.xml.zip andromda-ejb3/src/main/resources/templates/ejb3 EntityEmbeddable.vsl andromda-ejb3/src/main/uml EJB3MetafacadeModel.xml.zip andromda-ejb3/src/site/axdoc howto.xml howto2.xml Log: fix ejb-67, 68, 69 - allowing foreign key column names and constraint names to be explicitly defined Revision Changes Path 1.9 +11 -1 cartridges/andromda-ejb3/src/site/fml/faq.fml Index: faq.fml =================================================================== RCS file: /cvsroot/andromdaplugins/cartridges/andromda-ejb3/src/site/fml/faq.fml,v retrieving revision 1.8 retrieving revision 1.9 diff -u -w -r1.8 -r1.9 --- faq.fml 2 Jul 2007 14:25:12 -0000 1.8 +++ faq.fml 21 Aug 2007 14:27:09 -0000 1.9 @@ -144,5 +144,15 @@ </p> </answer> </faq> + <faq id="Inheritance_strategy_differences_between_hibernate_ejb3_cartridges"> + <question>I used to use the subclass strategy with the Hibernate cartridge. Home come I get "Cannot use identity column key generation with union-subclass mapping for" when I use the TABLE_PER_CLASS strategy with the EJB3 cartridge?</question> + <answer> + <p> + The EJB3 cartridge equivalent of the subclass inheritance strategy for the Hibernate cartridge is the + JOINED inheritance strategy. Read more about it in + <a href="http://galaxy.andromda.org/forum/viewtopic.php?t=4825">forum thread</a>. + </p> + </answer> + </faq> </part> </faqs> 1.26 +9 -0 cartridges/andromda-ejb3/src/site/changes.xml Index: changes.xml =================================================================== RCS file: /cvsroot/andromdaplugins/cartridges/andromda-ejb3/src/site/changes.xml,v retrieving revision 1.25 retrieving revision 1.26 diff -u -w -r1.25 -r1.26 --- changes.xml 21 Jul 2007 13:31:51 -0000 1.25 +++ changes.xml 21 Aug 2007 14:27:12 -0000 1.26 @@ -514,6 +514,15 @@ this is now supported with EJb 3.0. An abstract parent entity can have a relationship with any other entity and this should be available to the child inheriting entities. Add test cases to support this. </action> + <action dev="vancek" due-to="hermida" type="fix"> + JIRA EJB-67, EJB-68, EJB-69 - Improved generation of JoinColumn and JoinTable annotations for all apprpriate + associations. By default, foreign key column names have the _FK suffix. You can explicitly overwrite + FK column names by defining the @andromda.persistence.column tagged value. You can also explicitly overwrite + the foreign key constraint names by enabling hibernate extensions and modeling the + @andromda.persistence.foreignkey.constraint tagged value. Refer to the relationshipts howto for further + details. You should be aware that this patch will change the way the cartridge generates your foreign keys. + Previously, it appended the _C suffix. + </action> </release> </body> </document> \ No newline at end of file 1.20 +1 -1 cartridges/andromda-ejb3/pom.xml Index: pom.xml =================================================================== RCS file: /cvsroot/andromdaplugins/cartridges/andromda-ejb3/pom.xml,v retrieving revision 1.19 retrieving revision 1.20 diff -u -w -r1.19 -r1.20 --- pom.xml 13 Jun 2007 16:32:11 -0000 1.19 +++ pom.xml 21 Aug 2007 14:27:13 -0000 1.20 @@ -290,7 +290,7 @@ </plugins> </reporting> <properties> - <!--maven.test.skip>false</maven.test.skip--> + <!-- maven.test.skip>true</maven.test.skip--> <model.uri>jar:file:${pom.basedir}/src/main/uml/EJB3MetafacadeModel.xml.zip!/EJB3MetafacadeModel.xml</model.uri> <test.model.uri>jar:file:${pom.basedir}/src/test/uml/EJB3CartridgeTestModel.xml.zip!/EJB3CartridgeTestModel.xml</test.model.uri> </properties> 1.19 +84 -26 cartridges/andromda-ejb3/src/main/java/org/andromda/cartridges/ejb3/metafacades/EJB3AssociationEndFacadeLogicImpl.java Index: EJB3AssociationEndFacadeLogicImpl.java =================================================================== RCS file: /cvsroot/andromdaplugins/cartridges/andromda-ejb3/src/main/java/org/andromda/cartridges/ejb3/metafacades/EJB3AssociationEndFacadeLogicImpl.java,v retrieving revision 1.18 retrieving revision 1.19 diff -u -w -r1.18 -r1.19 --- EJB3AssociationEndFacadeLogicImpl.java 29 Apr 2007 13:45:06 -0000 1.18 +++ EJB3AssociationEndFacadeLogicImpl.java 21 Aug 2007 14:27:13 -0000 1.19 @@ -8,6 +8,7 @@ import org.andromda.cartridges.ejb3.EJB3Globals; import org.andromda.cartridges.ejb3.EJB3Profile; +import org.andromda.metafacades.uml.AssociationEndFacade; import org.andromda.metafacades.uml.ClassifierFacade; import org.andromda.metafacades.uml.Entity; import org.andromda.metafacades.uml.EntityMetafacadeUtils; @@ -887,6 +888,20 @@ return BooleanUtils.toBoolean(String.valueOf(this.getConfiguredProperty(HIBERNATE_ASSOCIATION_ENABLE_CACHE))); } + + /** + * @see org.andromda.cartridges.ejb3.metafacades.EJB3AssociationEndFacadeLogic#handleIsForeignKeyConstraintDefined() + */ + protected boolean handleIsForeignKeyConstraintDefined() + { + boolean fkConstraintDefined = false; + if (findTaggedValue(UMLProfile.TAGGEDVALUE_PERSISTENCE_FOREIGN_KEY_CONSTRAINT_NAME) != null) + { + fkConstraintDefined = true; + } + return fkConstraintDefined; + } + /** * @see org.andromda.cartridges.ejb3.metafacades.EJB3AssociationEndFacadeLogic#handleGetForeignKeyConstraintName(java.lang.String) */ @@ -904,23 +919,22 @@ if (taggedValueObject == null) { - final ClassifierFacade type = getOtherEnd().getType(); + final ClassifierFacade type = this.getOtherEnd().getType(); if (type instanceof Entity) { - Entity entity = (Entity)type; - buffer.append(entity.getTableName()); + //Entity entity = (Entity)type; + //Instead of using the entity name, use the association end name to avoid duplication of + //FK constraint names which causes failures during table creation for some DBs (MySQL) + buffer.append( + EntityMetafacadeUtils.toSqlName( + this.getOtherEnd().getName(), + this.getConfiguredProperty(UMLMetafacadeProperties.SQL_NAME_SEPARATOR))); } else { // should not happen buffer.append(type.getName().toUpperCase()); } - } - else - { - // use the tagged value - buffer.append(taggedValueObject.toString()); - } buffer.append(this.getConfiguredProperty(UMLMetafacadeProperties.SQL_NAME_SEPARATOR)); @@ -949,9 +963,53 @@ buffer = new StringBuffer( EntityMetafacadeUtils.ensureMaximumNameLength(constraintName, new Short(maxLength))); buffer.append(constraintSuffix); + } + else + { + // use the tagged value + buffer.append(taggedValueObject.toString()); + } + return buffer.toString(); } + + /** + * @see org.andromda.cartridges.ejb3.metafacades.EJB3AssociationEndFacadeLogic#handleGetForeignKeyName(java.lang.String) + */ + protected String handleGetForeignKeyName(String suffix) + { + if (StringUtils.isNotBlank(suffix)) + { + suffix = new String( + this.getConfiguredProperty(UMLMetafacadeProperties.SQL_NAME_SEPARATOR) + + suffix + + this.getForeignKeySuffix()); + } + else + { + suffix = this.getForeignKeySuffix(); + } + + String columnName = null; + // prevent ClassCastException if the association isn't an Entity + if (this.getType() instanceof Entity) + { + final String columnNamePrefix = + this.isConfiguredProperty(UMLMetafacadeProperties.COLUMN_NAME_PREFIX) + ? ObjectUtils.toString(this.getConfiguredProperty(UMLMetafacadeProperties.COLUMN_NAME_PREFIX)) : null; + columnName = + EntityMetafacadeUtils.getSqlNameFromTaggedValue( + columnNamePrefix, + this, + UMLProfile.TAGGEDVALUE_PERSISTENCE_COLUMN, + ((Entity)this.getType()).getMaxSqlNameLength(), + suffix, + this.getConfiguredProperty(UMLMetafacadeProperties.SQL_NAME_SEPARATOR)); + } + return columnName; + } + /** * @see org.andromda.cartridges.ejb3.metafacades.EJB3AssociationEndFacadeLogic#handleGetDefaultCollectionInterface() */ 1.16 +712 -646 cartridges/andromda-ejb3/src/test/expected/cartridge-output.zip <<Binary file>> 1.11 +295 -300 cartridges/andromda-ejb3/src/test/uml/EJB3CartridgeTestModel.xml.zip <<Binary file>> 1.55 +55 -12 cartridges/andromda-ejb3/src/main/resources/templates/ejb3/EntityEmbeddable.vsl Index: EntityEmbeddable.vsl =================================================================== RCS file: /cvsroot/andromdaplugins/cartridges/andromda-ejb3/src/main/resources/templates/ejb3/EntityEmbeddable.vsl,v retrieving revision 1.54 retrieving revision 1.55 diff -u -w -r1.54 -r1.55 --- EntityEmbeddable.vsl 30 Jun 2007 03:53:48 -0000 1.54 +++ EntityEmbeddable.vsl 21 Aug 2007 14:27:17 -0000 1.55 @@ -562,13 +562,13 @@ ## Otherwise add the JoinColumn annotation. ## #* *##if (!$target.type.compositePrimaryKeyPresent) - @javax.persistence.JoinColumn(name = "$stringUtils.upperCase(${target.name})"#if ($associationEnd.columnDefinition), columnDefinition = "${associationEnd.columnDefinition}"#end) + @javax.persistence.JoinColumn(name = "${target.columnName}"#if ($associationEnd.columnDefinition), columnDefinition = "${associationEnd.columnDefinition}"#end) #* *##else #* *##set ($identifiers = $target.type.getIdentifiers()) @javax.persistence.JoinColumns ({ #* *##foreach ($attribute in $identifiers) - @javax.persistence.JoinColumn(name = "$stringUtils.upperCase(${target.name})_${attribute.columnName}", referencedColumnName = "${attribute.columnName}")#if($velocityCount != $identifiers.size()),#end + @javax.persistence.JoinColumn(name = "$associationEnd.getForeignKeyName(${attribute.columnName})", referencedColumnName = "${attribute.columnName}")#if($velocityCount != $identifiers.size()),#end #* *##end }) @@ -580,6 +580,13 @@ ## @org.hibernate.annotations.Cascade({${target.hibernateCascadeType}}) #* *##end +#* *##if ($target.foreignKeyConstraintDefined) +## +## Override the Hibernate foreign key constraint name +## Currently does not support composite PKs +## + @org.hibernate.annotations.ForeignKey(name = "$target.getForeignKeyConstraintName(${target.type.identifier.columnName})") +#* *##end #* *##end #* *##end public $target.getterSetterTypeName ${target.getterName}() @@ -621,10 +628,13 @@ #* *##set ($argExists = false) ## ## When the target entity is a mapped superclass AND Hibernate extensions is enabled -## then instead of the @OneToMany annotations, add the @CollectionOfElements instead +## then instead of the @OneToMany annotations, add the @CollectionOfElements instead. +## This is only applied when the target entity in the association is NOT and entity. +## In this situation, the target entity is a mapped superclass. ## #* *##if ($target.type.embeddableSuperclass && $hibernateExtensionEnabled) - @org.hibernate.annotations.CollectionOfElements + @org.hibernate.annotations.CollectionOfElements#if ($target.eager)(fetch = javax.persistence.FetchType.EAGER)#end + #* *##else @javax.persistence.OneToMany(#if ($target.cascadeType)cascade = {${target.cascadeType}}#set ($argExists = true)#end#if ($associationEnd.navigable)#if ($argExists) ,#end#**#mappedBy = "${associationEnd.name}"#set ($argExists = true)#end#if ($target.eager)#if ($argExists), #end#**#fetch = javax.persistence.FetchType.EAGER#end) #* *##end @@ -633,7 +643,12 @@ ## This is only set if the relationship is unidirectional. ## #* *##if (!$associationEnd.navigable && $target.navigable) - @javax.persistence.JoinTable(name = "${associationEnd.association.tableName}") + @javax.persistence.JoinTable + ( + name = "${associationEnd.association.tableName}", + joinColumns = {#set ($identifiers = $entity.getIdentifiers())#foreach ($attribute in $identifiers)@javax.persistence.JoinColumn(name = "$associationEnd.getForeignKeyName(${attribute.columnName})", referencedColumnName = "${attribute.columnName}")#if($velocityCount != $identifiers.size()), #end#end#**#}, + inverseJoinColumns = {#set ($identifiers = $target.type.getIdentifiers())#foreach ($attribute in $identifiers)@javax.persistence.JoinColumn(name = "$target.getForeignKeyName(${attribute.columnName})", referencedColumnName = "${attribute.columnName}")#if($velocityCount != $identifiers.size()), #end#end#**#} + ) #* *##end #* *##if ($target.map) @javax.persistence.MapKey#if ($target.hasTaggedValue("@andromda.persistence.collection.index"))(name = "${target.collectionIndexName}")#end @@ -646,6 +661,16 @@ @javax.persistence.OrderBy #* *##end #* *##elseif ($hibernateExtensionEnabled) +## +## Override the Hibernate foreign key constraint name +## Must define the name property. If the constraint on the entity itself is not defined, then dont +## render the annotation at all. +## +#* *##if ($associationEnd.owning) +#* *##if ($associationEnd.foreignKeyConstraintDefined) + @org.hibernate.annotations.ForeignKey(#if ($associationEnd.foreignKeyConstraintDefined)name = "$associationEnd.getForeignKeyConstraintName(${associationEnd.type.identifier.columnName})"#end#if ($target.foreignKeyConstraintDefined)#if ($associationEnd.foreignKeyConstraintDefined), #end#**#inverseName = "$target.getForeignKeyConstraintName(${target.type.identifier.columnName})"#end#**#) +#* *##end +#* *##end #* *##if ($target.list) ## ## Only add the IndexColumn annotation if Hibernate extensions is enabled @@ -719,13 +744,13 @@ ## Otherwise add the JoinColumn annotation. ## #* *##if (!$target.type.compositePrimaryKeyPresent) - @javax.persistence.JoinColumn(name = "$stringUtils.upperCase(${target.name})"#if ($associationEnd.columnDefinition), columnDefinition = "${associationEnd.columnDefinition}"#end) + @javax.persistence.JoinColumn(name = "${target.columnName}"#if ($associationEnd.columnDefinition), columnDefinition = "${associationEnd.columnDefinition}"#end) #* *##else #* *##set ($identifiers = $target.type.getIdentifiers()) @javax.persistence.JoinColumns ({ #* *##foreach ($attribute in $identifiers) - @javax.persistence.JoinColumn(name = "$stringUtils.upperCase(${target.name})_${attribute.columnName}", referencedColumnName = "${attribute.columnName}")#if($velocityCount != $identifiers.size()),#end + @javax.persistence.JoinColumn(name = "$associationEnd.getForeignKeyName(${attribute.columnName})", referencedColumnName = "${attribute.columnName}")#if($velocityCount != $identifiers.size()),#end #* *##end }) @@ -738,9 +763,14 @@ ## @org.hibernate.annotations.Cascade({${target.hibernateCascadeType}}) #* *##end +#* *##if($associationEnd.owning && $target.foreignKeyConstraintDefined) +## +## Override the Hibernate foreign key constraint name +## + @org.hibernate.annotations.ForeignKey(name = "$target.getForeignKeyConstraintName(${target.type.identifier.columnName})") +#* *##end #* *##end #* *##end - public $target.getterSetterTypeName ${target.getterName}() { return this.${target.name}; @@ -778,10 +808,13 @@ #* *##set ($argExists = false) ## ## When the target entity is a mapped superclass AND Hibernate extensions is enabled -## then instead of the @ManyToMany annotations, add the @CollectionOfElements +## then instead of the @OneToMany annotations, add the @CollectionOfElements instead. +## This is only applied when the target entity in the association is NOT and entity. +## In this situation, the target entity is a mapped superclass. ## #* *##if ($target.type.embeddableSuperclass && $hibernateExtensionEnabled) - @org.hibernate.annotations.CollectionOfElements + @org.hibernate.annotations.CollectionOfElements#if ($target.eager)(fetch = javax.persistence.FetchType.EAGER)#end + #* *##else @javax.persistence.ManyToMany(#if ($target.cascadeType)cascade = {${target.cascadeType}}#set ($argExists = true)#end#if(!$associationEnd.owning)#if ($argExists), #end#**#mappedBy = "${associationEnd.name}"#set ($argExists = true)#end#if ($target.eager)#if ($argExists), #end#**#fetch = javax.persistence.FetchType.EAGER#end) #* *##end @@ -794,8 +827,8 @@ @javax.persistence.JoinTable ( name = "${associationEnd.association.tableName}", - joinColumns = {#set ($identifiers = $entity.getIdentifiers())#foreach ($attribute in $identifiers)@javax.persistence.JoinColumn(name = "$target.getForeignKeyConstraintName(${attribute.columnName})", referencedColumnName = "${attribute.columnName}")#if($velocityCount != $identifiers.size()), #end#end#**#}, - inverseJoinColumns = {#set ($identifiers = $target.type.getIdentifiers())#foreach ($attribute in $identifiers)@javax.persistence.JoinColumn(name = "$associationEnd.getForeignKeyConstraintName(${attribute.columnName})", referencedColumnName = "${attribute.columnName}")#if($velocityCount != $identifiers.size()), #end#end#**#} + joinColumns = {#set ($identifiers = $entity.getIdentifiers())#foreach ($attribute in $identifiers)@javax.persistence.JoinColumn(name = "$associationEnd.getForeignKeyName(${attribute.columnName})", referencedColumnName = "${attribute.columnName}")#if($velocityCount != $identifiers.size()), #end#end#**#}, + inverseJoinColumns = {#set ($identifiers = $target.type.getIdentifiers())#foreach ($attribute in $identifiers)@javax.persistence.JoinColumn(name = "$target.getForeignKeyName(${attribute.columnName})", referencedColumnName = "${attribute.columnName}")#if($velocityCount != $identifiers.size()), #end#end#**#} ) #* *##end #* *##end @@ -819,6 +852,16 @@ #* *##end #* *##end #* *##if ($hibernateExtensionEnabled) +## +## Override the Hibernate foreign key constraint name +## Only generate the ForeignKey annotation if the constraint on the entity end is defined. The +## inverseName property cannot be defined without the name property. +## +#* *##if($associationEnd.owning) +#* *##if($associationEnd.foreignKeyConstraintDefined) + @org.hibernate.annotations.ForeignKey(#if ($associationEnd.foreignKeyConstraintDefined)name = "$associationEnd.getForeignKeyConstraintName(${associationEnd.type.identifier.columnName})"#end#if ($target.foreignKeyConstraintDefined)#if ($associationEnd.foreignKeyConstraintDefined), #end#**#inverseName = "$target.getForeignKeyConstraintName(${target.type.identifier.columnName})"#end#**#) +#* *##end +#* *##end #* *##if ($target.associationCacheEnabled) ## ## Only add the Cache annotation if assocation cache and Hibernate extensions are both enabled 1.58 +238 -236 cartridges/andromda-ejb3/src/main/uml/EJB3MetafacadeModel.xml.zip <<Binary file>> 1.6 +1 -0 cartridges/andromda-ejb3/src/site/axdoc/howto.xml Index: howto.xml =================================================================== RCS file: /cvsroot/andromdaplugins/cartridges/andromda-ejb3/src/site/axdoc/howto.xml,v retrieving revision 1.5 retrieving revision 1.6 diff -u -w -r1.5 -r1.6 --- howto.xml 30 Jun 2007 03:53:48 -0000 1.5 +++ howto.xml 21 Aug 2007 14:27:19 -0000 1.6 @@ -70,6 +70,7 @@ <li><a href="howto2.html#Join_Table_Many_To_Many_And_One_To_Many">Join Table for Many-To-Many and One-To-Many Relationships</a></li> <li><a href="howto2.html#Aggregation_Composition">Aggregation and Composition</a></li> <li><a href="howto2.html#Transient_Relationships">Transient Relationships</a></li> + <li><a href="howto2.html#Foreign_Key_Column_Names_And_Foreign_Key_Constraint_Names">Foreign Key Column Names and Foreign Key Constraint Names</a></li> <li><a href="howto2.html#Tips">Tips</a></li> </ul> </li> 1.5 +58 -0 cartridges/andromda-ejb3/src/site/axdoc/howto2.xml Index: howto2.xml =================================================================== RCS file: /cvsroot/andromdaplugins/cartridges/andromda-ejb3/src/site/axdoc/howto2.xml,v retrieving revision 1.4 retrieving revision 1.5 diff -u -w -r1.4 -r1.5 --- howto2.xml 30 Jun 2007 03:53:48 -0000 1.4 +++ howto2.xml 21 Aug 2007 14:27:19 -0000 1.5 @@ -347,6 +347,64 @@ <code>@javax.persistence.Transient</code> annotation to the relationship getter. </p> </subsection> + <a name="Foreign_Key_Column_Names_And_Foreign_Key_Constraint_Names"/> + <subsection name="Foreign Key Column Names and Foreign Key Constraint Names"> + <p> + By default, the foreign key column names are defined by the cartridge and foreign key constraint + names are defined by your database on creation. This way, we don't impose any complexity + on any project. However, there are always certain environments and projects which require a + strict architecture. This is where you may need the flexibility to control the foreign key + names and foreign key constraint names. + </p> + <p> + Controlling foreign key names is relatively simple as long as you know where to model the right + tagged value. In all four association types, you can use the + <code>@andromda.persistence.column</code> tagged value on an association end to explicitly + define the foreign key name. + </p> + <p> + In a <b>many-to-one</b> or <b>one-to-one</b> association, model the + <code>@andromda.persistence.column</code> tagged value on the target association ends. In a + <b>one-to-many</b> unidirection or <b>many-to-many</b> association, you can model the + <code>@andromda.persistence.column</code> tagged value on either one or both ends of the + association. + </p> + <p> + Remember that you don't have to explicitly define the foreign key column names. The cartridge + will create a suitable name for you using either the <b>JoinColumn</b> + annotation. Using the above solution, you are effectively overwriting the auto-generated + foreign key column names. + </p> + <p> + Explicitly defining foreign key constraint names are slightly more tricky. There is no + EJB 3.0 defined solution to setting the foreign key constraint names. Hibernate has provided + an extension to the EJB 3.0 annotations which solves this limitation. This is convenient if you + are using a JEE container with Hibernate as your persistence provider. If not, you need to + check with your provider and determine a corresponding annotation. Fortunately, the EJB3 + cartridge currently works well with JBoss and since JBoss uses Hibernate, we are almost home free. + </p> + <p> + The first thing you need to do to be able to explicitly define your foreign key constraint + names is to set the value of the <b>persistenceProviderExtensions</b> namespace property + to <b>hibernate</b> in your andromda.xml. You can then model the + <code>@andromda.persistence.foreignkey.constraint</code> tagged value on the appropriate + association ends to explicitly define your foreign key constraint names. + </p> + <p> + For <b>many-to-one</b> and <b>one-to-one</b> associations, you model the + <code>@andromda.persistence.foreignkey.constraint</code> tagged value on the target association + ends. For <b>one-to-many unidirectional</b> and <b>many-to-many</b> associations, you + can model the <code>@andromda.persistence.foreignkey.constraint</code> tagged value on either + end or both ends of the association depending on what you want. + </p> + <p class="highlight"> + Keep in mind that for <b>one-to-many unidirectional</b> and <b>many-to-many</b> associations, + you must model the foreign key constraint name on the source association end if you want + to define the foreign key constraint name on the target association end. If you don't, then + neither one will be considered during generation. You can however only define the foreign key + constraint name on the source end and not the target end. + </p> + </subsection> <a name="Tips"/> <subsection name="Tips" > <p> |