简体   繁体   中英

Create a Tree using JPA

I am trying to create a tree using entities and JPA. I have a class with the following properties.

public class Dir
{

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

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

A node knows who its parent is, and if it doesnt have a parent, it is the root. Thats how I can easily build a tree out of this. But... I dont think the mapping is correct for this thought. I get the following error when I try to deploy:

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.

It talks about the cardinality. But this doesnt make sense, a node can only have one parent. This is why I chose @OneToOne

Can anyone shed some light on this? I guess another way of asking this would be, how do you map an entity to another instance of itself?

EDIT

Here is my table structure:

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)

You're pointing to the wrong column for the owning side of the mapping. Also your relationship is not OneToOne because a single Parent can have many Children.

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

The problem seems to be the property mappedBy , try to remove it. I think you don't need use something like that for your implementation.

@Entity
public class Dir {

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

@OneToOne(cascade=CascadeType.ALL )
private Dir parent;

    ....

}

You should do an implementation of the Composite Pattern . Simple to do with JPA:

  • Create an abstract base class, eg FileSystemItem.
  • Create a class called Folder, and one called File that both extend Node.
  • Choose an inheritance strategy. For this you could probably use a discriminator and have both types in one file.
  • Put the attribute name in the base class.
  • Make a collection in the folder class of, not Files, but FileSystemItems.

That's pretty much it. The other big decision is what to do with the add method. If you put it in the base class, you have to throw an unsupported operation exception if someone calls it on a File.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM