【发布时间】:2020-11-08 08:17:14
【问题描述】:
我有一个使用单表继承和其他子类的通用类:
文件,主类
文件夹扩展文件
卡片扩展文件
Abstract FileLink extends File : 扩展 File 的 FileLink 抽象类
FolderLink 扩展了 FileLink 并由一个文件夹组成。
CardLink 扩展了 FileLink 并由 Card 组成。
在我的 File 类中,我有一个具有 oneToMany 关系的 File 集合,它可以包含任何类型的 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 被序列化时,我可以通过 FileLink 类检索链接的文件夹属性以及在其父类(文件)中声明的属性,对于卡片链接也是如此。
但我想做的只是将 OneToMany 关系声明到 File 和 FileLink 类中:
@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 时,我知道链接的文件是一个文件夹,但是如果我从超类中检索它,我无法将其转换为文件夹,休眠告诉我他不能将文件转换为文件夹,这很正常,因为文件不是文件夹。
有没有办法实现这个目标?我目前的实现对我来说已经足够方便了,但如果我能做得更多,那就太好了。
【问题讨论】:
-
在设计继承层次结构时,无论何时键入
B extends A,您都应该问自己一个问题:“B可以在任何需要A的地方使用吗?”。从这个角度来看,FolderLink是多余的,因为您可以将Folder分配给FileLink.linkedFile(因为Folder扩展了File)。此外,Folder从File继承fileLinks属性 -
@crizzis 是的,但是linkedFile 链接了一个文件,所以如果我序列化一个 FileLink,我只能获取 File 属性而不是 Folder 属性,这就是为什么我需要一个 FolderLink 类来这样做。我想序列化 FolderLink 或 CardLink(Card 扩展 File 也具有自己的属性),就像它是 Folder 或 Card。
-
在这种情况下,也许您只需要一个轻量级接口来表达
FolderLink和Folder的功能(即PhysicalFolder implements Folder和FolderLink implements Folder;不是确定命名),不需要继承。请注意,在您的设置中,FolderLink从Folder继承它从未使用过的物理属性,因为 getters 委托给linkedFolder -
FolderLink和FileLink都可以继承自File,或者更好的是,继承自未声明它们不需要的物理属性的父超类(例如AbstractFilesystemItem) -
FolderLink 不继承Folder 的属性,它不是Folder 而只是一个File,它是由一个Folder 组成的。是的,Folder 和 FolderLink 应该共享相同的接口,但这不是问题(实际上 Jackson 只需要相同的属性名称......) ***Link 类从 File 继承,因为我使用单表继承类型。
标签: java hibernate jpa data-modeling hibernate-onetomany