我有一个使用单表继承的泛型类和其他子类:
文件,主要类
文件夹扩展文件
卡扩展文件
抽象FileLink扩展File:一个扩展File的FileLink抽象类
FolderLink扩展FileLink并由一个Folder组成。
CardLink扩展了FileLink并由Card组成。
在我的File类中,我具有一个具有oneToMany关系的文件集合,该文件集合可以包含任何类型的File,因此包含文件夹或文件夹链接或卡链接。
@DiscriminatorColumn(name = "file_type", discriminatorType = DiscriminatorType.INTEGER)
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
public class File{
@OneToMany(mappedBy = "parent", fetch = FetchType.LAZY)
List<File> subFiles = new Linkedlist()
@ManyToOne(fetch = FetchType.LAZY)
protected File parent;
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(length= 40)
private String name;
@Lob
private String description;
}
一个文件夹可以具有多个链接。
@Entity
@DiscriminatorValue(File.FOLDER + "")
public class Folder extends File {
@OneToMany(mappedBy = "linkedFolder", fetch = FetchType.LAZY, targetEntity = FolderLink.class)
protected Set<FolderLink> folderLinks = new HashSet<>();
private Object folderAttribute;
}
与卡相同
@Entity
@DiscriminatorValue(File.CARD+ "")
public class Card extends File {
@OneToMany(mappedBy = "linkedCard", fetch = FetchType.LAZY, targetEntity = CardLink.class)
protected Set<CardLink> cardLinks = new HashSet<>();
private Object cardAttribute;
}
Filelink类表示到文件的链接,没有使用太多特定的属性,只是父文件和链接的文件。
实际上,当我序列化子文件集合时,我希望我的链接(FolderLink或Cardlinks)返回链接文件的属性值。
因此,Folderlink类应该返回Folder属性值,CardLink Card属性值和FileLink File属性值。
我的实际建模方法是这样的:
@NoArgsConstructor
public abstract class FileLink extends File {
@Override
public String getName() {
return "Link to "+this.getLinkedFile().getName();
}
@Override
public String getDescription() {
return this.getLinkedFile().getDescription();
}
...
@JsonIgnore
public abstract File getLinkedFile();
}
@Entity
@DiscriminatorValue(File.FOLDER_LINK + "")
public class FolderLink extends FileLink {
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "folder_linked_id", insertable = false, updatable = false)
protected Folder linkedFolder;
@JsonIgnore
public File getLinkedFolder() {
return this.linkedFolder;
}
@Override
public String getFolderAttribute() {
return "Link to "+this.getLinkedFile().getFolderAttribute();
}
@Override
public File getLinkedFile() {
return this.getLinkedFolder();
}
}
@Entity
@DiscriminatorValue(File.CARD_LINK + "")
public class CardLink extends FileLink {
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "card_linked_id", insertable = false, updatable = false)
protected Card linkedCard;
@JsonIgnore
public File getLinkedCard() {
return this.linkedCard;
}
@Override
public String getCardAttribute() {
return "Link to "+this.getLinkedFile().getCardAttribute();
}
@Override
public File getLinkedFile() {
return this.getLinkedCard();
}
}
因此,当FolderLink序列化时,除了通过卡链接链接在其父类(文件)中声明的属性之外,我还可以检索链接的文件夹属性。
但是我想做的是仅在File和FileLink类中声明OneToMany关系:
@DiscriminatorColumn(name = "file_type", discriminatorType = DiscriminatorType.INTEGER)
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
public class File{
@OneToMany(mappedBy = "linkedFile", fetch = FetchType.LAZY, targetEntity = FileLink.class)
protected Set<FileLink> fileLinks = new HashSet<>();
}
Filelink类不再是抽象的。
@NoArgsConstructor
@Entity
@DiscriminatorValue(File.FILE_LINK + "")
public class FileLink extends File {
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "file_linked_id", insertable = false, updatable = false)
protected File linkedFile;
@Override
public String getName() {
return "Link to "+this.getLinkedFile().getName();
}
...
@JsonIgnore
public File getLinkedFile(){
return this.linkedfile;
}
}
@Entity
@DiscriminatorValue(File.FOLDER_LINK + "")
public class FolderLink extends FileLink {
@Override
public String getFolderAttribute() {
return "Link to "+((Folder)this.getLinkedFile()).getFolderAttribute();
}
}
@Entity
@DiscriminatorValue(File.CARD_LINK + "")
public class CardLink extends FileLink {
@Override
public String getCardrAttribute() {
return "Link to "+((Card)this.getLinkedFile()).getCardAttribute();
}
}
但是它不起作用。当我创建一个FolderLink时,我知道链接的文件是一个Folder,但是如果我从超类检索到该文件,则无法将其转换为Folder,休眠状态告诉我他不能将文件转换为Folder,这是正常的,因为文件不是文件夹。
有没有办法实现这个目标?我目前的实现方式对我来说足够方便,但是如果我能做更多的话,那就太好了。
答案 0 :(得分:2)
您正在寻找的是您提到的多态关联映射
休眠告诉我他不能将文件投射到文件夹中,这很正常,因为文件不是文件夹。
您可以通过添加另一列作为类型控件来定义所需的类型。
package com.example;
import javax.persistence.Entity;
import javax.persistence.JoinColumn;
import javax.persistence.Column;
import org.hibernate.annotations.Any;
import org.hibernate.annotations.AnyMetaDef;
import org.hibernate.annotations.Cascade;
import org.hibernate.annotations.MetaValue;
@Entity
@DiscriminatorValue(File.FILE_LINK + "")
public class FileLink extends File {
@Any (
metaColumn = @Column(name = "linkedFileType"),
fetch=FetchType.LAZY
)
@AnyMetaDef(idType = "long", metaType = "string", metaValues = {
@MetaValue(targetEntity = Folder.class, value = "folder"),
@MetaValue(targetEntity = Card.class, value = "card")
})
@Cascade({org.hibernate.annotations.CascadeType.ALL})
@JoinColumn(name = "file_linked_id")
protected File linkedFile;
@Override
public String getName() {
return "Link to "+this.getLinkedFile().getName();
}
...
@JsonIgnore
public File getLinkedFile(){
return this.linkedfile;
}
}