如何正确管理jpa双向关系?

时间:2015-04-06 13:31:19

标签: jpa ejb

我正在使用EJB3.2和JPA 2.1。 在我的应用程序中,我有这些实体(简而言之):

@Entity
public class Festival
{
    int Id;
    String name;
    ...
    @ManyToOne
    @JoinColumn(name = "merchant", referencedColumnName = "Id")
    Merchant merchant;
}

@Entity
public class Merchant
{
    int Id;
    String name;

    ...

    @ManyToOne
    @JoinColumn(name = "category", referencedColumnName = "Id")
    Category category;

    @ManyToOne
    @JoinColumn(name = "city", referencedColumnName = "Id")
    City city;

    @OneToMany(cascade = CascadeType.ALL, mappedBy = "festival")
    List<Festival> festivalList;
}

@Entity
public class Category
{
    int Id;
    String name;
    ...
    @OneToMany(cascade = CascadeType.ALL, mappedBy = "merchant")
    List<Merchant> merchantList;
}

@Entity
public class City
{
    int Id;
    String name;

    @OneToMany(cascade = CascadeType.ALL, mappedBy = "merchant")
    List<Merchant> merchantList;
}
因此,(Festival,Merchant)具有双向关系,如(商人,类别)和(商人,城市)

问题是当我删除或更改商家时,仍然在类别merchantList和cities merchantList中有一个未更改的副本!等等..

我该如何管理这些变化?!为什么JPA不会自行更改其他副本?它不会增加错误的副本风险吗?!

3 个答案:

答案 0 :(得分:1)

我认为Christian Bauer和Gavin King对“Java Persistence With Hibernate”(第261页)的引用可能对你有用:

  

与EJB 2.0 CMR相反,Hibernate和JPA关联都是如此   本质上是单向的。

因此,从商家到类别的关联与从类别到商家的关联不同,您需要单独管理它们。

编辑: 我调整了你的初始bean配置,看起来应该: (当然,您将使用适当的主键生成策略。)

@Entity
public class Festival
{
    @Id
    @GeneratedValue(strategy=GenerationType.IDENTITY)
    int Id;
    String name;

    @ManyToOne(cascade=CascadeType.ALL)
    @JoinColumn(name = "merchant")
    Merchant merchant;
}
@Entity
public class Merchant
{
    @Id
    @GeneratedValue(strategy=GenerationType.IDENTITY)
    int Id;
    String name;

    @ManyToOne
    @JoinColumn(name = "category")
    Category category;

    @ManyToOne
    @JoinColumn(name = "city")
    City city;

    @OneToMany(cascade = CascadeType.ALL, mappedBy = "merchant")
    List<Festival> festivalList;
}
@Entity
public class Category
{
    @Id
    @GeneratedValue(strategy=GenerationType.IDENTITY)
    int Id;
    String name;

    @OneToMany(cascade = CascadeType.ALL, mappedBy = "category")
    List<Merchant> merchantList;
}
@Entity
public class City
{
    @Id
    @GeneratedValue(strategy=GenerationType.IDENTITY)
    int Id;
    String name;

    @OneToMany(cascade = CascadeType.ALL, mappedBy = "city")
    List<Merchant> merchantList;
}

答案 1 :(得分:1)

确保在调用categories.getMerchantList()之前保持(商家)。

答案 2 :(得分:1)

JPA将您的实体视为常规Java对象,并且不为您维护关系 - 应用程序负责确保在更改一侧时双向关系的双方保持同步。因此,当您从商家取消引用某个城市时,您必须从该城市的商家列表中删除对该商家的引用,然后在必要时进行合并。

否则,通过java对象查看数据将与数据库不同步,直到从数据库刷新对象为止。您可以权衡在需要时保持双方同步或刷新的价值和成本,甚至不映射非拥有方,并确定在逐个实体的基础上更适合您的应用程序。