简体   繁体   中英

Ternary relationship hibernate saved in extra table

I have 3 entities that can have a relationship with each other. So a good step to solve this problem is to use another table to store the 3 ID's of the 3 entities. Lets say the entities are X, Y and Z.

@Entity
public class XYZ {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Integer id;

    @ManyToOne
    @JoinColumn(name = "X_ID")
    private X x;

    @ManyToOne
    @JoinColumn(name = "Y_ID")
    private Y y ;

    @ManyToOne
    @JoinColumn(name = "Z_ID")
    private Z z;

    public XYZ(){

    }

}

Entities X, Y and Z have:

  • Their own attributes and primary key
  • @OneToMany to the X, Y and Z entities on the attribute private XYZ xyz; to make it bidirectional

Entity XYZ has have normal getters and setters for the entities X, Y and Z. I'm giving the whole entity.

Entities X, Y and Z are the parents and XYZ is the child. So deleting X, Y, or Z should delete XYZ.

From a relationship between two entities I know that you have to save the child on the parent side. Example: parent.addChild(c); parent.save();

How can I save X, Y, Z in the new XYZ with the cascade working? I don't want to save it 3 times (on the X, Y and Z). Sorry if this is an obvious question, but I haven't found good examples on this yet and my knowledge isn't enough.

I have this but dont know if it is right:

XYZ test = new XYZ();
test.setX(new X());
test.setY(new Y());
test.setZ(new Z());
test.save();

Now if i delete the X entity, is the XYZ entity that contains the X entity automatically deleted?

I have this but dont know if it is right

I'm not sure what test.save() does, but if it calls EntityManager.persist(test) , then that's the correct way of doing it.

Now if i delete the X entity, is the XYZ entity that contains the X entity automatically deleted?

Not by default. You will need cascade = REMOVE with the @OneToMany mappings, otherwise deleting X will fail. Note that this introduces a performance overhead compared to deleting the relevant XYZ in a bulk remove query. However, if the number of associations for a single X/Y/Z entity is small, you should be fine.

By the way, if the sole purpose of XYZ is to represent the ternary association, I'd consider:

  • adding optional=false to @ManyToOne
  • making the many-to-one associations into a composite primary key (this way will automatically prevent duplicates) and dropping the artificial id
  • if you still want an artificial id, you should, at the very least, define a @UniqueConstraint involving all of the join columns (declaring the join columns as updatable=false, nullable=false is probably a good idea as well, just to be on the safe side)

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