如何在同一个表上使用@ManyToMany和两个列表

Bil*_*KAR 6 java many-to-many jpa

我有一种情况,一个实体可以使用另一个实体,它可以被另一个实体使用,所以我定义了一个引用同一实体的ManyToMany关系,所以我可以有listUse和listUsedBy,并且两者都保存在同一个表entity_usage中:

@ManyToMany
@JoinTable(name = "entity_usage",
        joinColumns = {
            @JoinColumn(name = "id_use", referencedColumnName = "id")},
        inverseJoinColumns = {
            @JoinColumn(name = "id_used_by", referencedColumnName = "id")})
private List<Entity> listUse;

@ManyToMany
@JoinTable(name = "entity_usage",
        joinColumns = {
            @JoinColumn(name = "id_use_by", referencedColumnName = "id")},
        inverseJoinColumns = {
            @JoinColumn(name = "id_use", referencedColumnName = "id")})
private List<Entity> listUsedBy;
Run Code Online (Sandbox Code Playgroud)

例子:实体A可以使用实体BC,因此实体BCA使用.现在我的问题是当我将b和C添加到listUse时,它们会持久保存在entity_usage中,但是当我尝试显示listUsedBy时我必须重新部署我的项目,否则listUsedBy仍然是空的,有没有办法刷新listUsedBy,当没有拥有我的实体时重新部署我的项目.

Mic*_*tti 6

这是一般方法:

@Entity
public class SomeEntity
{
    @ManyToMany
    @JoinTable(name = "entity_usage",
        joinColumns = @JoinColumn(name = "using_id"),
        inverseJoinColumns = @JoinColumn(name = "used_by_id"))
    private Set<SomeEntity> using = new LinkedHashSet<>();

    @ManyToMany(mappedBy = "using")
    private Set<SomeEntity> usedBy = new LinkedHashSet<>();

    public void addUsing(SomeEntity entity)
    {
        this.using.add(entity);
        entity.usedBy.add(this);
    }

    public void addUsedBy(SomeEntity entity)
    {
        this.usedBy.add(entity);
        entity.using.add(this);
    }
}
Run Code Online (Sandbox Code Playgroud)

它的用途是:

public void someMethod(long parentEntityId, long childEntityId)
{
    EntityManager em = getSomeEntityManager();

    SomeEntity parentEntity = em.find(SomeEntity.class, parentEntityId);
    SomeEntity childEntity = em.find(SomeEntity.class, childEntityId);

    parentEntity.addUsing(childEntity);
}
Run Code Online (Sandbox Code Playgroud)

通常,这是事务性 EJB 方法。
请注意,不需要做em.merge任何事情,因为实体已经由管理em.find。无论如何,无论您使用哪种方法来管理实体(查询、查找、持久、合并),请记住仅当两个实体都被管理时才调用/很重要addUsingaddUsedBy

这是 ORM 逻辑无法自行处理的主要不连贯性之一:您必须告知两个实体(父实体和子实体)它们的关系
仅在一侧设置关系是不够的 - 如果您只说 A 是 B 的父级,B 仍然不知道谁是其父级。

但是,存在替代方法,例如仅设置关系的拥有方 ( parent.getChildren().add(child))、刷新并刷新子项。

然而(正如我在皮肤上的亲身体验一样),在现实世界的复杂应用中,替代方案很难处理。

作为旁注,我会使用Set而不是List关系,除非您需要某种插入顺序。