Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/hibernate/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 如何使用与hibernate的多通关系将泛型类型用于超类_Java_Hibernate_Jpa_Data Modeling_Hibernate Onetomany - Fatal编程技术网

Java 如何使用与hibernate的多通关系将泛型类型用于超类

Java 如何使用与hibernate的多通关系将泛型类型用于超类,java,hibernate,jpa,data-modeling,hibernate-onetomany,Java,Hibernate,Jpa,Data Modeling,Hibernate Onetomany,我有一个使用单表继承和其他子类的泛型类: 文件,主类 文件夹扩展文件 卡扩展文件 抽象文件链接扩展文件:一个文件链接抽象类扩展文件 FolderLink扩展了FileLink并由一个文件夹组成 CardLink扩展了FileLink并由一张卡组成 在我的File类中,我有一个具有oneToMany关系的文件集合,它可以包含任何类型的文件,例如文件夹、文件夹链接或卡片链接 @DiscriminatorColumn(name = "file_type", discriminato

我有一个使用单表继承和其他子类的泛型类:

文件,主类

文件夹扩展文件

卡扩展文件

抽象文件链接扩展文件:一个文件链接抽象类扩展文件

FolderLink扩展了FileLink并由一个文件夹组成

CardLink扩展了FileLink并由一张卡组成

在我的File类中,我有一个具有oneToMany关系的文件集合,它可以包含任何类型的文件,例如文件夹、文件夹链接或卡片链接

@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;
}
因此,当一个FolderLink被序列化时,除了通过FileLink类在其父类(文件)中声明的属性外,我还可以检索链接的文件夹属性,对于卡片链接也是如此

但我想做的是在文件和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<>();

}
但它不起作用。当我创建FolderLink时,我知道链接的文件是一个文件夹,但如果我从超类检索它,我无法将其转换为文件夹,hibernate告诉我他无法将文件转换为文件夹,这是正常的,因为文件不是文件夹


有没有办法实现这个目标?我目前的实现对我来说很方便,但如果我能做得更多,那就太好了。

正如您所提到的,您正在寻找的是多态关联映射

hibernate告诉我他不能将文件强制转换到文件夹中,这很正常,因为文件不是文件夹

可以通过添加另一列作为类型控件来定义所需的类型

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;
    }
}

在设计继承层次结构时,无论何时键入
B扩展A
,您都应该问自己这样一个问题:“
B
可以在需要
A
的地方使用吗?”。从这个角度来看,
FolderLink
是多余的,因为您可以将
文件夹
分配给
FileLink.linkedFile
(因为
文件夹
扩展了
文件
)。另外,
文件夹
文件
继承
文件链接
属性@crizzis是的,但是linkedFile链接一个文件,因此如果我序列化一个文件链接,我只能获取文件属性,而不能获取文件夹属性,这就是为什么我需要一个FolderLink类来这样做。我想序列化FolderLink或CardLink(卡片扩展文件也有自己的属性),就像它是文件夹或卡片一样。在这种情况下,您可能只需要一个轻量级的界面来表达
FolderLink
Folder
(即
PhysicalFolder实现文件夹
FolderLink实现文件夹
;不确定命名),不需要继承。请注意,在您的设置中,
FolderLink
继承它从不使用的
文件夹的物理属性,因为getter委托给
linkedFolder
FileLink
都可以从
文件继承,或者更好的是,从父超链接继承lass(例如,
AbstractFilesystemItem
)不声明不需要的物理属性FolderLink不会从文件夹继承属性,它不是文件夹,而是文件,它由文件夹组成。是的,文件夹和FolderLink应该共享同一个接口,但这不是问题所在(实际上Jackson只需要相同的属性名称…)***链接类从文件继承,因为我使用单表继承类型。感谢您的帮助,它工作得很好。我不明白的是,我不必创建任何“linkedFileType”列,但它似乎没有。您的配置中的hibernate.hbm2ddl模式是什么?我猜它会自动更新您的表。嗯,ddl auto处于更新模式,但尚未创建列,并且在没有列的情况下运行良好,这非常奇怪。经过几次测试后,似乎这些注释@Any etc甚至都不是必需的,因为在我的文件类中,我已经为文件的不同子类使用了鉴别器值。因此,如果将linkedFile声明为文件,hibernate可以使用ri填充它ght子类。我不知道它以前为什么不起作用,真是个大谜团!
@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();
    }
}
@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<>();

}
@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();
    }

}
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;
    }
}