【问题标题】:Symmetric composite key in jpa/hibernatejpa/hibernate中的对称复合键
【发布时间】:2012-01-06 12:16:09
【问题描述】:

我试图确保一个模型不会在数据库中保存两次,并且它的 id 是对称的。在对称复合 id 下,我的意思是:

@Entity
public class Item {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "item_id", unique = true, nullable = false)
    public Long id;

    // other properties ...
}

@Entity
public class Pair {
    @EmbeddedId
    public PairId id;   

    // other properties...

    @Embeddable
    public static class PairId implements Serializable {

        @ManyToOne(cascade={CascadeType.MERGE, CascadeType.REFRESH, CascadeType.DETACH})
        @JoinColumn(name="source_item_id")
        public Item source;

        @ManyToOne(cascade={CascadeType.MERGE, CascadeType.REFRESH, CascadeType.DETACH})
        @JoinColumn(name="target_item_id")
        public Item target;

        @Override
        public boolean equals(Object o) {
             if(this == o){
               return true;
             }
             if (o instanceof PairId == false){
               return false;
             }

             PairId other = (PairId) o;
             return (this.source.equals(other.source) && this.target.equals(other.target)) ||
                    (this.source.equals(other.target) && this.target.equals(other.source));
    }

        @Override
        public int hashCode() { //probably not the best approach
             return source.hashCode() + target.hashCode();
        }
    }
}

例子:

Item i1 = new Item();
Item i2 = new Item();
//persist items into the database ...
PairId pId1 = new PairId(i1, i2);
PairId pId2 = new PairId(i2, i1);
Pair p1 = new Pair(pId1);
//persist p1 into the database
Pair p2 = new Pair(pId2);
//calling persist should not add new entry to the database, since p2 is symmetrical to p1 and already exists in the database
Pair p3 = findById(pId2); 
//p3 should now contain p1 also

您知道如何实现这种行为吗?提前致谢!

编辑: 在这两个类上添加了 cmets,以显示这些类可以具有(并且它们具有)除上面列出的 id 之外的其他属性。但为了简单起见,我只是将他们的 ID 保留为单独的常设财产。

【问题讨论】:

    标签: java hibernate jpa duplicates composite-key


    【解决方案1】:

    首先,我不会使用复合 ID。使用自动生成的代理键,并将这两个项目存储为常规属性。

    然后,当成对存放物品时,我会确保始终以相同的顺序存放它们。例如,源 ID 应始终小于目标 ID。这可以通过封装来确保:

    public void setItems(Item i1, Item i2) {
        if (i1.getId().compareTo(i2.getId()) < 0) {
            this.source = i1;
            this.target = i2;
        }
        else {
            this.source = i2;
            this.target = i1;
        }
    }
    

    【讨论】:

      【解决方案2】:

      也许,只是也许你可以放弃Pair 的想法并在Item 中使用自我引用。这样您的表格更少、代码更简洁且没有复合键。

      代码:

      @Entity
      public class Item
      {
          @Id
          @GeneratedValue(strategy = GenerationType.IDENTITY)
          @Column(name = "id")
          private Long id;
      
          @OneToOne
          @JoinColumn(name = "source_id", referencedColumnName = "id")
          private Item source;
      
          @OneToOne(mappedBy = "source")
          private Item target;
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2017-12-19
        • 2011-03-20
        • 2021-10-14
        • 2018-02-02
        • 2016-09-18
        • 2011-05-12
        • 2016-06-05
        相关资源
        最近更新 更多