【问题标题】:Eliminate duplicate entries in Hibernate tables of one-to-many relationship reference消除一对多关系引用的Hibernate表中的重复条目
【发布时间】:2017-01-21 00:21:37
【问题描述】:

我目前正在使用的程序在您每次运行该程序时都会接收三个数值(companyName、groupName、hostName)。每次收到这三个值时,我都会将它们分组到一个对象(Datas)中,并将它们存储在一个列表(List)中。

我的目标是将所有值存储到包含三个表(公司、组、主机)的数据库中。

三个表是相连的:Company 和 Group 是一对多的,Group 和 Host 是一对多的。

所以我创建了三个类(Company.java、Group.java、Host.java),它们将采用适当的值并使用构造函数创建该类的新实例。

然后我会使用休眠会话将类的每个实例存储到数据库中。

我的代码是这样的:

for (Datas data:Datas){
     Company company = new Company(data.getCompanyName);
     Group group = new Group(company, data.getGroupName);
     Host host = new Host(group, data.getHostName);

     session.save(company);
     session.save(group);
     session.save(host);     
}

虽然上面的代码允许我使用正确的一对多关系将所有数据保存到我的表中,但它不允许我防止重复条目。

例如,现在我的表在保存 5 个数据后以这种方式存储内容:

Company
id (auto-increment)  Name
1                    Google
2                    Google
3                    Google
4                    Yahoo
5                    Yahoo

Group
id (auto-increment)  Company_id  Name
1                    1           HR
2                    2           HR
3                    3           OP
4                    4           HR
5                    5           PR

Host
id (auto-increment)  Group_id  Name
1                    1         Jane
2                    2         Harry
3                    3         Molly
4                    4         Garry
5                    5         Neo   

虽然上面的表格在技术上是正确的,但我真的想消除重复项。现在,在 Company 表中,所有“Google”和“Yahoo”条目都是完全相同的。在 Group 表中,第 1 项和第 2 项是相同的,因为它们都具有名称“HR”,并且都引用了公司“Google”。

这样,我们只创建 1 个,而不是创建 3 个公司条目“Google”。组表上的所有条目都只会引用该条目。 Host 表的逻辑相同。

正确的表格应如下所示:

Company
id (auto-increment)  Name
1                    Google
2                    Yahoo

Group
id (auto-increment)  Company_id  Name
1                    1           HR
2                    1           OP
3                    2           HR
4                    2           PR

Host
id (auto-increment)  Group_id  Name
1                    1         Jane
2                    1         Harry
3                    3         Molly
4                    4         Garry
5                    5         Neo   

如何在我的代码中进行此类调整?在实例化三个类之前我应该​​对数据做些什么吗?或者我应该在使用类构造函数实例化时做些什么?或者有没有我可以用来防止这种重复的 Hibernate 注释?

非常感谢您的帮助。

【问题讨论】:

    标签: java mysql postgresql hibernate one-to-many


    【解决方案1】:

    您的 for 循环基本上应该根据业务自然键值查询数据库,并根据该事实确定记录是否存在并分支。

    for ( Datas data : datas ) {
      Company company = companyRepository.findByName( data.getCompanyName() );
      if ( company == null ) {
        // new company implies everything else is also new
        company = new Company( data.getCompanyName() );
        group = new Group( company, data.getGroupName() );
        host = new Host( group, data.getHostName() );
        session.save( company );
        session.save( group );
        session.save( host );
      }
      else {
        // since company exists, we need to check whether group/host exist
        Group group = groupRepository.findByName( data.getGroupName() );
        if ( group == null ) {
          // since group doesn't exist, neither will host
          group = new Group( company, data.getGroupName() );
          host = new Host( group, data.getHostName() );
          session.save( group );
          session.save( host );
          // depending on relationships, you may need to link group to company
          // followed by updating company.
        }
        else {
          // group exists, check if host does
          Host host = hostRepository.findByName( data.getHostName() );
          if ( host == null ) {
            // host doesn't, create it.
            host = new Host( group, data.getHostName() );
            session.save( host );
            // depending on relationships, you may need to link host to group
            // followed by updating group.
          }
        }
      }
    }
    

    公开#findByName(String) 方法的各种存储库类仅用于说明您使用谓词执行的查询,该谓词查找实体的指定名称。

    显然,如果您的 Datas 结构包含更多的细节,而不仅仅是一个名称值,也需要与现有记录合并,您需要向循环添加逻辑以将任何修改应用于获取的持久对象通过#findByName(String 方法。

    // Simplified example for the Host
    Host host = hostRepository.findByName( data.getHostName() );
    if ( host == null ) {
      host = new Host( group, data.getHostName() );
      host.setSomeOtherAttribute( data.getHostSomeOtherAttribute() );
      session.save( host );
    }
    else {
      host.setsomeOtherAttribute( data.getHostSomeOtherAttribute() );
      session.update( host );
    }
    

    【讨论】:

    • 感谢您的精彩回答!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多