Normally it is not advisable to map primary and foreign key columns (PK and FK) as Java class properties (ObjAttributes). When reverse engineering of the database is done using CayenneModeler, the produced mapping will reflect that – PKs and FKs will not be included in the Java class. However, sometimes an application requires access to these values.

| For a generic and easy API to obtain an object primary key or to find an object from a known PK, skip to the next chapter on DataObjectUtils class.

Cayenne provides a generic way to access primary and foreign keys by creating custom get* methods in the DataObject subclass. Lets take a Painting class as an example. The following code is generated by CayenneModeler:

    package org.apache.art;

    public class Painting extends org.apache.art.auto._Painting {

    }

    package org.apache.art.auto;

    /** Class _Painting was generated by Cayenne.
      * It is probably a good idea to avoid changing this class manually,
      * since it may be overwritten next time code is regenerated.
      * If you need to make any customizations, please use subclass.
      */
    public class _Painting extends org.apache.art.ArtDataObject {

        public static final String ESTIMATED_PRICE_PROPERTY = "estimatedPrice";
        public static final String PAINTING_TITLE_PROPERTY = "paintingTitle";
        public static final String TO_ARTIST_PROPERTY = "toArtist";
        public static final String TO_GALLERY_PROPERTY = "toGallery";
        public static final String TO_PAINTING_INFO_PROPERTY = "toPaintingInfo";

        public static final String PAINTING_ID_PK_COLUMN = "PAINTING_ID";

        public void setEstimatedPrice(java.math.BigDecimal estimatedPrice) {
            writeProperty("estimatedPrice", estimatedPrice);
        }
        public java.math.BigDecimal getEstimatedPrice() {
            return (java.math.BigDecimal)readProperty("estimatedPrice");
        }

        public void setPaintingTitle(String paintingTitle) {
            writeProperty("paintingTitle", paintingTitle);
        }
        public String getPaintingTitle() {
            return (String)readProperty("paintingTitle");
        }
    ...
    }

The following custom methods should be added to the Painting class to access the values of ARTIST_ID and PAINTING_ID:

| If you perform class generation using Ant, you can customize class generation templates to generate these methods for you. Eventually CayenneModeler will support this too as optional functionality.

    package org.apache.art;

    public class Painting extends org.apache.art.auto._Painting {
       /** Read-only access to PK */
       public Integer getPaintingId() {
          return (getObjectId() != null && !getObjectId().isTemporary())
                   ? (Integer)getObjectId().getIdSnapshot().get(PAINTING_ID_PK_COLUMN)
                   : null;
       }

       /** Read-only access to FK */
       public Integer getArtistId() {
          Artist artist = getArtist();
          return (artist != null)
                   ? (Integer)artist.getObjectId().getIdSnapshot().get(Artist.ARTIST_ID_PK_COLUMN)
                   : null;
       }
    }