View Javadoc
1   package ejava.examples.orm.rel.annotated;
2   
3   import javax.persistence.*;
4   
5   import org.slf4j.Logger;
6   import org.slf4j.LoggerFactory;
7   
8   import ejava.examples.orm.rel.MediaCopyPK;
9   
10  /**
11   * This class provides an example of a ManyToOne mapping. The media copy owns
12   * the relationship to the media. Therefore the foreign key to media is within
13   * the media copy database table.<p/>
14   * 
15   * This class has an unrelated technical issue worth mentioning. 
16   * Everything would have worked out fine if we created a simple primary key
17   * field for the media copy and a separate foreign key to the media. Instead, 
18   * we pretended to encounter a composite primary key where one of the values
19   * doubled as the foreign key to the media.<p/>
20   * 
21   * <pre>
22   * MediaCopy (pk=MEDIACOPY_MID + COPYNO)
23   *     MEDIACOPY_MID (fk to Media.MEDIA_ID) 
24   *     COPYNO
25   *     ...
26   * Media (pk=MEDIA_ID)
27   *     MEDIA_ID
28   *     ...
29   * </pre>
30   * 
31   * The MediaCopy now has two uses for the MEDIACOPY_MID column. One as a primary
32   * key (part of a compound primary key) and the other as the foreign key to the Media.
33   * We need to make sure the provider preserves the semantics of the primary key while
34   * reusing it from the foreign key.
35   * 
36   * This implementation will use the JPA 1.0 technique of mapping both the 
37   * primary and foreign key properties to the same column and then mark the 
38   * foreign key as READ-ONLY using the insertable and updatable properties
39   * of the @Column.
40   */
41  
42  @Entity @Table(name="ORMREL_MEDIACOPY")
43  @IdClass(MediaCopyPK.class)
44  public class MediaCopy {
45      private static final Logger log = LoggerFactory.getLogger(MediaCopy.class);
46      @Id //mapped to COPY_NO by IdClass
47      private int copyNo;    
48      @Id //mapped to MEDIACOPY_MID by IdClass
49      private long mediaId;    
50      @ManyToOne
51      @JoinColumn(name="MEDIACOPY_MID", //mapped same as mediaId property
52              insertable=false, updatable=false) //makes column read-only
53      private Media media;
54      
55      protected MediaCopy() { log.debug(super.toString() + ": ctor()"); }
56      public MediaCopy(Media media, int copyNo) {
57          log.debug(super.toString() + ": ctor() mediaId="
58                  + media.getId() + ", copyNo=" + copyNo);
59          setMedia(media);
60          setMediaId(media.getId());
61          setCopyNo(copyNo);
62      }    
63  
64      public int getCopyNo()                { return copyNo; }    
65      private void setCopyNo(int copyNo)    { this.copyNo = copyNo; }
66      
67      public long getMediaId()              { return mediaId; }
68      private void setMediaId(long mediaId) { this.mediaId = mediaId; }
69      
70      public Media getMedia()               { return media; }    
71      private void setMedia(Media media)    { this.media = media; }
72  
73      private String myInstance() {
74          String s=super.toString();
75          s = s.substring(s.lastIndexOf('.')+1);
76          return s;
77      }
78  
79      public String toString() {
80          return myInstance() +
81              ", mediaId=" + mediaId +
82              ", copyNo=" + copyNo +
83              ", media=" + media;
84      }
85  }