Re: PK Velocity Template Problem

From: Mike Kienenberger (mkienen..laska.net)
Date: Mon Jun 13 2005 - 17:09:13 EDT

  • Next message: Gentry, Michael \(Contractor\): "Cayenne Enumerations"

    Note: It's really best to send your messages directly to the cayenne-user
    mailing list.
    I have a bad habit of giving out incorrect information, and I need the other
    cayenne users to keep me honest.

    "McDaniel, Joe R." <mcdanij..igr.org> wrote:
    > As you said, the objects referenced are different but trying to follow
    > the hierarchy (as I said) is next-to-impossible.

    I agree it can be confusing.

    The thing to remember for the v1.1 cgen task is that classGen.Entity returns
    an ObjEntity.

    >From there, you can just use the API docs to traverse through the
    relationships.

    ie, ObjEntity.getDbEntity() takes you to the DbEntity,
    DbEntity.getPrimaryKey() returns a list of DbAttributes, etc.

    v1.2, -- now in cvs -- attempts to clean this up a bit, both by providing
    the objEntity as a distinct object as well as providing other accessors,
    such as a reference to a EntityResolver for the datamap.

    > Here is what is
    > generated:
    >
    > public static final String AMPLICON_QC_TYP_CD_PK_COLUMN =
    > "amplicon_qc_typ_cd";
    > public void
    > setAmplicon_qc_typ_cd($classGen.formatJavaType(${idAttr.Type})
    > amplicon_qc_typ_cd) {
    > writeProperty("amplicon_qc_typ_cd", amplicon_qc_typ_cd);
    > }
    > public $classGen.formatJavaType(${idAttr.Type})
    > getAmplicon_qc_typ_cd() {
    > return
    > ($classGen.formatJavaType(${idAttr.Type}))readProperty("amplicon_qc_typ_
    > cd");
    > }
    >
    >
    > This is what it should look like:
    >
    > public static final String AMPLICON_QC_TYP_CD_PK_COLUMN =
    > "amplicon_qc_typ_cd";
    > public void setAmpliconQcTypCd(String ampliconQcTypCd) {
    > writeProperty("ampliconQcTypCd", ampliconQcTypCd);
    > }
    > public String getAmpliconQcTypCd() {
    > return (String)readProperty("ampliconQcTypCd");
    > }

    Again, your biggest problems are knowing that idAttr.Type for
    AMPLICON_QC_TYP_CD_PK_COLUMN should be "String". This is ObjAttribute
    stuff, and raw DbAttributes (like your primary keys) don't have any java
    class mappings.

    You either have to define them as ObjAttributes or you have to determine the
    proper java types yourself.

    Equally problematic is that "writeProperty/readPropery" only work for
    ObjAttributes.
    You have to use dataObject.getObjectId() as a data source instead of
    "readProperty" and that's what DataObjectUtils already does for you. Then
    you'd need to read the named key attribute out of the map.

        /**
         * Returns a map of id components. Keys in the map are DbAttribute
    names, values are
         * database values of corresponding columns.
         */
        public Map getIdSnapshot() {
            return objectIdKeys;
        }

    So

         public String getAmpliconQcTypCd() {
             java.util.Map primaryKeyMap = compoundPKForObject(this);
             return (String)primaryKeyMap.get("ampliconQcTypCd");
         }

    > There may be a problem with generating this -- the mapping of
    > ampliconQcTypCd to amplicon_qc_typ_cd is not done in Velocity and
    > probably does not exist.

    Yeah, there's no conversion function provided from underscore constant
    format to java variable name format.

    Again, the name "ampliconQcTypCd" is normally information provided by the
    ObjAttribute and keyed in manually (or computed by the modeler application)
    rather than computed from the DbAttribute in the template.

    But it could be made automatic by adding a velocity tool to the context that
    is a wrapper for
    org.objectstyle.cayenne.util.NameConverter.undescoredToJava() under cgen
    v1.2.

    > I suspect that unless Andrus is willing to put
    > this mapping option down a few layers in the reverse engineering process
    > that this cannot work this way but I guess it could be mapped to using
    > the DataObjectUtils approach.

    If you're willing to use cgen 1.2 to generate your classes, you have
    enormous flexibility to add data into the template generation process. You
    can extend it however you like, even to the point of manually providing the
    java type for a class.

            <context>
                            <tool key="myNameConverterWrapper"
    className="foo.bar.myNameConverterWrapper" />
                <property key="Type_AMPLICON_QC_TYP_CD" value="String" />
            </context>

    myNameConverterWrapper would be

    public class myNameConverterWrapper {
       public String undescoredToJava(String name) {
           boolean capitalize = false;
           return
    org.objectstyle.cayenne.util.NameConverter.undescoredToJava(name,
    capitalize);
       }

    Note that you can use Cayenne 1.2 just to generate classes -- you can still
    use Cayenne 1.x for your actual application.

    > It is just a huge pain to do this for many
    > tables and then to have to redo it if you repeat the reverse engineering
    > to pick up changes in the database from other sources....

    I don't follow this line of thought. It's all automatic. There shouldn't
    be anything more to it than rerunning the cgen task after you update your
    data model.

    -Mike



    This archive was generated by hypermail 2.0.0 : Mon Jun 13 2005 - 17:06:45 EDT