【问题标题】:Create a Tree using JPA使用 JPA 创建树
【发布时间】:2013-01-17 21:01:29
【问题描述】:

我正在尝试使用实体和 JPA 创建树。我有一个具有以下属性的类。

public class Dir
{

@Id
@Basic(optional = false)
@NotNull
@Column(name = "dirId")
private Integer dirId;

@OneToOne(mappedBy="dirId", cascade= CascadeType.ALL)
private Dir parent;
...

一个节点知道它的父节点是谁,如果它没有父节点,它就是根节点。这就是我可以轻松构建一棵树的方法。但... 我不认为映射对于这个想法是正确的。尝试部署时出现以下错误:

An incompatible mapping has been encountered between [class com.dv.oa.model.entity.dir.Dir] and [class com.dv.oa.model.entity.dir.Dir]. This usually occurs when the cardinality of a mapping does not correspond with the cardinality of its backpointer.

它谈到了基数。但这没有意义,一个节点只能有一个父节点。这就是我选择@OneToOne的原因

任何人都可以对此有所了解吗?我想问这个问题的另一种方式是,你如何将一个实体映射到它自己的另一个实例?

编辑

这是我的表结构:

mysql> describe dir;
+--------------+--------------+------+-----+---------+-------+
| Field        | Type         | Null | Key | Default | Extra |
+--------------+--------------+------+-----+---------+-------+
| dirId        | int(11)      | NO   | PRI | NULL    |       |
| DTYPE        | varchar(31)  | YES  |     | NULL    |       |
| dirName      | varchar(255) | YES  |     | NULL    |       |
| companyOwner | int(11)      | YES  | MUL | NULL    |       |
| userOwner    | int(11)      | YES  | MUL | NULL    |       |
| parent       | int(11)      | YES  |     | NULL    |       |
+--------------+--------------+------+-----+---------+-------+
6 rows in set (0.00 sec)

【问题讨论】:

    标签: java database jpa tree


    【解决方案1】:

    您指向映射拥有方的错误列。此外,您的关系不是 OneToOne,因为一个父母可以有很多孩子。

    @Entity
    public class Dir
    {
    
      //This field is a table column
      //It uniquely identifies a row on the DIR table
      @Id
      private int dirId;
    
      //This field is a table column
      // It identifies the parent of the current row
      // It it will be written as the type of dirId
      // By default this relationship will be eagerly fetched
      // , which you may or may not want
      @ManyToOne(fetch=FetchType.LAZY, cascade={CascadeType.PERSIST, CascadeType.MERGE})
      private Dir parent;
    
      //This field is not a table column
      // It is a collection of those Dir rows that have this row as a parent. 
      // This is the other side of the relationship defined by the parent field.
      @OneToMany(mappedBy="parent")
      private Set<Dir> children;
    }
    

    【讨论】:

    • 有趣,这是有道理的。我还需要一个子列的 getter/setter 吗?
    • 不一定。 (你必须考虑哪一方应该拥有这种关系,保存应该如何级联,延迟获取、更新和刷新,你想从 JPA 模型中向你的 Java 代码的其余部分公开什么,等等)。根据您的 JPA 实现,不一定严格要求子端...关键是 ManyToOne - OneToMany 基数。
    • 我一直在尝试这个,但仍然不断收到同样的错误。不知道为什么会这样
    • 你的表结构是什么样的?
    • 我看到还有其他字段(companyOwner、userOwner)似乎是关系,这些字段中的任何一个是否意外映射到 Dir 实体?还在寻找其他可能存在问题的东西,我看到您有一个鉴别器列 (DTYPE),是否有任何子类定义了不正确的关系?
    【解决方案2】:

    问题似乎是属性ma​​ppedBy,尝试删除它。我认为你不需要使用类似的东西来实现。

    @Entity
    public class Dir {
    
    @Id
    @Basic(optional = false)
    @NotNull
    @Column(name = "dirId")
    private Integer dirId;
    
    @OneToOne(cascade=CascadeType.ALL )
    private Dir parent;
    
        ....
    
    }
    

    【讨论】:

    • 谢谢,现在试一试
    • 当我尝试仅使用 @OneToOne 进行部署时,我似乎仍然可以得到它
    • 我对上面的类没有问题,你把“@Entity”放在Dir类上了吗?
    【解决方案3】:

    您应该实现Composite Pattern。使用 JPA 很简单:

    • 创建一个抽象基类,例如文件系统项。
    • 创建一个名为 Folder 的类和一个名为 File 的类,它们都扩展了 Node。
    • 选择继承策略。为此,您可以使用鉴别器并将两种类型都放在一个文件中。
    • 把属性名放到基类中。
    • 在文件夹类中创建一个集合,而不是 Files,而是 FileSystemItems。

    差不多就是这样。另一个重大决定是如何处理 add 方法。如果你把它放在基类中,如果有人在 File 上调用它,你必须抛出一个不受支持的操作异常。

    【讨论】:

    • 这与 JPA 托管关系的基数无关。
    • -1 OP 要求对树进行简单映射,您的回答对新手来说非常具有误导性。
    猜你喜欢
    • 2019-07-09
    • 1970-01-01
    • 1970-01-01
    • 2016-01-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多