Reputation: 7760
My code look like this:
@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;
}
I want two table: T_FILE_META,T_FILE_META_SHA,The relationship is N:1
T_FILE_META( pk(id),filename, fk(sha1))
T_FILE_META_SHA( pk(sha1), md5, type)
Use this code will get Unable to find column with logical name: sha1 in org.hibernate.mapping.Table(t_file_meta) and its related supertables and secondary tables
About the SecondaryTable
I learn from wiki:Tables#Multiple_tables.
How to define this entity ? BTW, T_FILE_META_SHA only cascade update
.
EDITED
So,SecondaryTable is only for 1:1,I changed the entity to
/**
* 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;
}
}
This looks like more sensible,REF:META is N:1
.REF delegate some field of META.But is this ok ? FileMeta
is not updateable.
When I change the sha1 of Reference, is it possible to auto load the FileMeta if exists ?
Upvotes: 1
Views: 1489
Reputation: 154000
The @SecondaryTable allows you to join two tables together in a one-to-one relation, as if you have split the same row into two separate tables.
For a one-to-many relation, you need to use a @OneToMany
association instead.
The problem with your mapping is that you specified a joining column that doesn't exist in the T_FILE_META
table:
pkJoinColumns = @PrimaryKeyJoinColumn(name = "sha1", referencedColumnName = "sha1")
So, you need to add the two sha1 fields to the FileMeta
entity:
@Column(name = "sha1")
private String sha1Fk;
@Column(name = "sha1", table = "T_FILE_META_SHA")
private String sha1Pk;
Upvotes: 1