首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何使用JPA和Hibernate对子实体执行级联合并

如何使用JPA和Hibernate对子实体执行级联合并
EN

Stack Overflow用户
提问于 2017-04-28 08:58:58
回答 1查看 365关注 0票数 0

这个问题与管理id号有关,以确保我不会在person的表上出现重复的身份。这是一个使用MySQL数据库的springboot项目。

一些背景知识:

我有一个提交“插曲”的HTML表单。每一集都包含"persons“,并与ManyToMany的"persons”有关系。

“剧集”由外地工作人员输入并提交到数据库(db1)中。几个小时后,BackOffice工作人员将这一集手动输入到第二个数据库(db2)中。

在我的弹簧连接数据库(db1)上,我有一个persons表,它有一个本机自动生成的id字段。db1还有一个id2字段-它记录了来自db2的人员的唯一id。

现场工作人员在进入剧集时并不总是可以访问id2,但BackOffice工作人员可以。

当我保存一个新的“剧集”时,我需要save方法来检查person id2是否存在于数据库中,并对person执行更新(而不是create new)。

然后删除重复的人员。

剧集实体:

代码语言:javascript
复制
@Entity
public class Episode {

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
...
@Column(name="start_date")
@DateTimeFormat (pattern="dd/MM/yyyy HH:mm")
private Date start_date;
@ManyToMany(cascade = {CascadeType.PERSIST, CascadeType.MERGE})
@JoinTable(name = "episode_person", joinColumns = @JoinColumn(name = "episode_id", referencedColumnName = "id"), inverseJoinColumns = @JoinColumn(name = "person_id", referencedColumnName = "id"))
private List<Person> persons;
@OneToOne(cascade=CascadeType.ALL)
//@JoinColumn(name = "id")
private Address address;

人员实体

代码语言:javascript
复制
@Entity
public class Person {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private Long id2;
private String surname;
private String firstname;
private String phoneHome;
@DateTimeFormat(pattern = "dd/mm/yyyy")
private Date dob;
@ManyToMany(mappedBy = "persons", cascade = {CascadeType.PERSIST, CascadeType.MERGE})
private List<Episode> episodes;

EpisodeServiceImpl

代码语言:javascript
复制
@Override
@Transactional
public Episode saveEpisode(Episode episode) {
    List mergedPeople = personService.mergeDetachedWithAttached( episode.getPersons() );
    episode.setPersons( mergedPeople );
    return episodeRepository.save(episode);
}

PersonServiceImpl

代码语言:javascript
复制
    @Transactional
@Override
public List mergeDetachedWithAttached(List<Person> people) {
    final List<Person> results = new ArrayList<>();
    if ( people != null && !people.isEmpty() ) {

        // loop over every person
        for (Person person : people) {

            // for current person try to retrieve from db via Id2
            Person db2Person = personRepository.findById2( person.getId2() );

            // if a person was retrieved use them instead of submitted person
            if (db2Person != null ) {
                System.out.println("A matching person was found in the db using id2 - this is the person that will be added");
                results.add(db2Person);
            } else {
                results.add(person);
            }
        }
    }
    return results;

每当有新的剧集提交时,我就会创建新的人,即使我使用id2成功地从db1中查找了他们并将他们添加到剧集中,也是如此。

我该如何处理这一点,以便:

我可以通过比较id2来合并重复的身份。在合并后删除id的位置,也需要更新包含episode_id和person_id的连接表。

EN

回答 1

Stack Overflow用户

发布于 2017-04-29 01:40:05

如果您将@ManyToMany关联替换为2个双向@OneToMany关联,这会容易得多,这意味着您也可以映射关联表。

这样,考虑到您有那些重复的EpisodePerson实体,您可以通过简单地调整关联实体上的@ManyToOne关联来轻松地移动加入的关联。对于重复的EpisodePerson,您可以使用UPSERT,如下所述,或者在批处理将条目添加到数据库后进行手动合并。

通常,当多个节点同时运行时,可以使用数据库UPSERT或合并操作。

您可以将UPSERT与Hibernate @SqlInsert annotation结合使用。

要处理FK更新,您需要使用FK ON DELETE级联策略。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/43670268

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档