繁体   English   中英

在JPA中将实体添加到大型多对多关系中

[英]Adding an entity into an large Many-To-Many relationship in JPA

我有一个Group实体,它具有多对多关系中的User实体列表。 它由包含两个ID的典型连接表映射。 此列表可能非常大,一组中有一百万或更多用户。

我需要向该组添加一个新用户,通常会是这样的

group.getUsers().add(user);
user.getGroups().add(group);

em.merge(group);
em.merge(user);

如果我了解典型的JPA操作,是否需要将100万+用户的整个列表下拉到集合中以添加新用户然后保存? 这对我来说听起来不太可扩展。

我不应该在JPA中定义这种关系吗? 我应该直接在这样的情况下操纵连接表条目吗?

请原谅松散的语法,我实际上是在使用Spring Data JPA,所以我不经常直接使用实体管理器,但问题似乎是JPA的一般问题所以我想这样做。

像这样设计模型并使用UserGroup进行关联。

@Entity
public class User {

   @OneToMany(cascade = CascadeType.ALL, mappedBy = "user",fetch = FetchType.LAZY)
    @OnDelete(action = OnDeleteAction.CASCADE)
    private Set<UserGroup> userGroups = new HashSet<UserGroup>();

}


@Entity
@Table(name="user_group", 
    uniqueConstraints = {@UniqueConstraint(columnNames = {"user_id", "group_id"})})
public class UserGroup {


    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "user_id", nullable = false)
    @ForeignKey(name = "usergroup_user_fkey")
    private User user;

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "group_id", nullable = false)
    @ForeignKey(name = "usergroup_group_fkey")  
    private Group group;

}


@Entity
public class Group {

    @OneToMany(cascade = CascadeType.ALL, mappedBy="group", fetch = FetchType.LAZY )
    @OnDelete(action = OnDeleteAction.CASCADE)      
    private Set<UserGroup>  userGroups  = new HashSet<UserGroup>();

}

这样做。

     User user =     findUserId(id); //All groups wont be loaded they are marked lazy
     Group group =  findGroupId(id);  //All users wont be loaded they are marked lazy

     UserGroup  userGroup = new UserGroup();
     userGroup.setUser(user);
     userGroup.setGroup(group);

     em.save(userGroup);

有效地使用ManyToMany映射是在实体中缓存​​集合,因此您可能不希望对大型集合执行此操作,因为显示它或通过触发它来传递实体会破坏性能。

相反,您可以删除双方的映射,并为关系表创建一个实体,当您需要访问该关系时,可以在查询中使用该实体。 使用中间实体将允许您使用分页和游标,以便您可以限制可能带回可用块的数据,并且您可以插入新实体以轻松地表示新关系。

EclipseLink的属性更改跟踪确实允许添加到集合而无需触发关系,以及其他性能增强。 这是通过编织实现的,并且可用于不维护订单的集合类型。

getUsers()getGroups()返回的集合类不必将其内容驻留在内存中,如果启用了延迟提取,正如我假设您为这么大的关系做的那样,持久性提供程序应该是智能的足以让你意识到你并没有尝试阅读内容而只是添加一个值。 (类似地,在集合上调用size()通常会导致SQL COUNT查询,而不是实际加载和计算元素。)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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