以 N:1 关系在 JPA SecondaryTable 中保存同一列
Posted
技术标签:
【中文标题】以 N:1 关系在 JPA SecondaryTable 中保存同一列【英文标题】:Save same column in JPA SecondaryTable with N:1 relationship 【发布时间】:2015-03-08 18:04:46 【问题描述】:我的代码如下所示:
@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学习。
如何定义这个实体?顺便说一句,T_FILE_META_SHA 仅级联 update
。
已编辑
所以,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 的某些字段。但这可以吗? FileMeta
不可更新。
当我更改 Reference 的 sha1 时,是否可以自动加载 FileMeta 如果存在?
【问题讨论】:
【参考方案1】:@SecondaryTable 允许您以一对一的关系将两个表连接在一起,就像您将同一行拆分为两个单独的表一样。
对于一对多关系,您需要改用@OneToMany
关联。
您的映射问题在于您指定的连接列在 T_FILE_META
表中不存在:
pkJoinColumns = @PrimaryKeyJoinColumn(name = "sha1", referencedColumnName = "sha1")
name:引用一个 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;
【讨论】:
多对一是更好的选择。您需要从该关联中删除可更新的内容并使 FileMeta @Immutable。 只在javax.annotation.concurrent
下看到@Immutable,而不是javax.persistence
。Dose JPA 能识别这个吗?
这是一个 Hibernate 特定的注解,JPA 没有等价物。以上是关于以 N:1 关系在 JPA SecondaryTable 中保存同一列的主要内容,如果未能解决你的问题,请参考以下文章
在JPA SecondaryTable中以N:1关系保存相同的列