2016-08-26 20 views
0

我有一个数据模型,其中Person可能被一个或多个Name所知(例如,她的名字结婚后)。该型号区分正在使用的单个Name如何在JPA中建立“一对多”关系中的“默认选择”

PersonName之间的一般关系被建模为通常:在Person实体的双向@OneToMany关系和在Name实体类相应@ManyToOne关系。

要指定“主动或主要名称”,我认为我可以将此模型设置为从PersonName的单向@OneToOne关系。在实体类的映射是这样的:

public class Person { 

    @Id @GeneratedValue(strategy = GenerationType.Identity) 
    private Long pers_id; 

    @OneToOne(fetch = FetchType.EAGER, optional = false) 
    @JoinColumn(name = "name_id", nullable = false) 
    private Name uniPrimaryName; 

     : 
     : 

    @OneToMany(mappedBy = "owningSidePerson", fetch = FetchType.LAZY, 
     cascade = CascadeType.ALL) 
    private List<Name> mappedSideNames; 

     : 
     : 
} 

而且Name实体类:

public class Name 

    @Id @GeneratedValue(strategy = GenerationType.Identity) 
    private Long name_id; 

    @ManyToOne(fetch = FetchType.LAZY, optional = false) 
    @JoinTable (name = "XREF_NAMES_PERSON", 
     joinColumns = @JoinColumn(name = "name_id", nullable = false), 
     inverseJoinColumns = @JoinColumn(name = "pers_id", nullable = false)) 
    private Person owningSidePerson; 

     : 
     : 
} 

这种模式的优点是,它让我访问主Name作为一个简单的属性访问从Person。它也应该更容易维护。不足之处在于序列化具有循环引用的实体Person,但是无论是否存在单向关系都存在此问题。

另一种模式是将active布尔型属性添加到Name实体,并用它来指示关系中哪个实体是活动实体。缺点是保持属性不那么简单,并且获得活动的Name将需要单独的数据库查询。

在我投入这个设计的时间之前,我想问问以前有没有人试过这个。我担心使用实体对象的对象模型会同时出现在单向和双向关系中。

+1

我已经使用了你的第一个想法。它的主要问题是循环依赖:你不能删除一个人,因为它被它的名字引用,你不能删除一个名字,因为它是被一个人引用的。但是,如果您确保按照正确顺序执行操作并刷新,或者如果使用延迟约束,则可以正常工作。 –

回答

0

我的建议是只留下该人的关系名(mappedSideNames)并删除由uniPrimaryName属性映射的关系以确定该名称是否为主要名称或不可以为此目的创建一个命名查询,但是您必须通过设置标志创建一种区分主要名称的方法。

+0

是的,正如问题中所讨论的那样,实现此目的的一种方法是通过在名称实体中创建一个布尔属性来指定主名称。维护这个属性并不简单。主名称也是一个频繁访问的属性。必须执行单独的查询才能获得它或使用应用程序逻辑来查找它似乎不是最佳解决方案 – scottb