2015-03-08 50 views
1

我的代碼如下所示:保存在JPA SecondaryTable有N相同的列:1間的關係

@Data 
@Accessors(chain = true, fluent = true) 
@Entity 
@Table(name = "T_FILE_META", indexes = {@Index(columnList = "filename")} 
) 
@SecondaryTable(name = "T_FILE_META_SHA", 
     pkJoinColumns = @PrimaryKeyJoinColumn(name = "sha1", referencedColumnName = "sha1") 
     , indexes = {@Index(columnList = "sha1", unique = true), @Index(columnList = "md5", unique = true)} 
) 
public class FileMeta 
{ 
    @Id 
    @GeneratedValue 
    private Long id; 

    private String filename; 

    @Column(length = 40, table = "T_FILE_META_SHA") 
    private String type; 
    @Column(length = 40, table = "T_FILE_META_SHA") 
    private String sha1; 
    @Column(length = 32, table = "T_FILE_META_SHA") 
    private String md5; 
} 

我要兩張表:T_FILE_META,T_FILE_META_SHA,關係是N:1

T_FILE_META(pk(id),filename, fk(sha1)) 
T_FILE_META_SHA(pk(sha1), md5, type) 

使用此代碼將得到Unable to find column with logical name: sha1 in org.hibernate.mapping.Table(t_file_meta) and its related supertables and secondary tables

關於SecondaryTable我從wiki:Tables#Multiple_tables瞭解到。

如何定義這個實體? BTW,T_FILE_META_SHA只能級聯update

EDITED

所以,SecondaryTable僅用於1:1,我改變了實體

/** 
* Different filename can reference to a same file meta 
*/ 
@Data 
@Accessors(chain = true, fluent = true) 
@Entity 
@Table(name = "T_FILE_REF", 
     indexes = {@Index(columnList = "filename"), @Index(columnList = "owner")} 
) 
public class FileReference 
{ 
    @Id 
    @GeneratedValue 
    private Long id; 

    private String filename; 
    private String owner; 

    /** 
    * The sha1 reference may change 
    * <p/> 
    * This field only used for FK 
    */ 
    @Setter(AccessLevel.NONE) 
    @Getter(AccessLevel.NONE) 
    private String sha1; 
    @Column(columnDefinition = "default now()") 
    private Date lastModificationDate; 
    @Column(columnDefinition = "default now()") 
    private Date uploadDate; 


    @Getter(AccessLevel.NONE) 
    @ManyToOne(cascade = CascadeType.PERSIST, optional = false) 
    @JoinColumn(name = "sha1", 
      referencedColumnName = "sha1", 
      updatable = false, 
      nullable = false) 
    private FileMeta meta; 


    public FileMeta meta() 
    { 
     if (meta == null) 
     { 
      meta = new FileMeta(); 
     } 
     return meta; 
    } 

    public String md5() 
    { 
     return meta().md5(); 
    } 

    public String type() 
    { 
     return meta().type(); 
    } 

    public String sha1() 
    { 
     return meta().sha1(); 
    } 


    @Data 
    @Accessors(chain = true, fluent = true) 
    @Entity 
    @Table(name = "T_FILE_META", indexes = {@Index(columnList = "md5")}) 
    public static class FileMeta 
    { 
     @Id 
     @Column(length = 40, 
       unique = true, 
       updatable = false, 
       nullable = false) 
     private String sha1; 

     @Column(length = 32, updatable = false, nullable = false) 
     private String md5; 

     /** 
     * File size 
     */ 
     @Column(precision = 32, nullable = false) 
     private Long length; 

     /** 
     * Mime type 
     */ 
     @Column(length = 40) 
     private String type; 
    } 
} 

這看起來更明智,REF:META是N:1 .REF委託一些領域META.But可以嗎? FileMeta不可更新。

當我更改引用的sha1時,是否可以自動加載FileMeta(如果存在)?

回答

1

@SecondaryTable允許您以一對一的關係一起連接到表,就好像您將同一行分割爲兩個單獨的表一樣。

對於一對多關係,您需要改爲使用@OneToMany關聯。

你映射的問題是,您所指定的連接柱不會在T_FILE_META表存在:

pkJoinColumns = @PrimaryKeyJoinColumn(name = "sha1", referencedColumnName = "sha1") 
  • :指T_FILE_META列(其中不存在)
  • referencedColumnName:指T_FILE_META_SHA柱

所以,你需要兩個SHA1字段添加到FileMeta實體:

@Column(name = "sha1") 
private String sha1Fk; 

@Column(name = "sha1", table = "T_FILE_META_SHA") 
private String sha1Pk; 
+0

感謝您點出了1:1,我更新的問題。 – wener 2015-03-09 01:36:50

+0

多對一是更好的選擇。您需要從該關聯中刪除可更新,並創建FileMeta @Immutable。 – 2015-03-09 03:20:43

+0

只能在'javax.annotation.concurrent'下看到@Immutable,而不是'javax.persistence'.Dose JPA認識到這一點? – wener 2015-03-09 05:00:13