【问题标题】:many to one association inserts instead of update多对一关联插入而不是更新
【发布时间】:2021-09-22 20:53:48
【问题描述】:

我的父类

@Entity
public class Trailer {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = “trailer_id", nullable = false)
    private Long trailerId;

    @OneToMany(mappedBy = “trailer”,cascade = CascadeType.ALL,fetch = FetchType.LAZY)
    private Set<Item> items;
}

儿童班

@Entity
public class Item {

    @Id
    @Column(name = “upc”, nullable = false)
    private Long upc;

    @ManyToOne(cascade = CascadeType.ALL)
    @JoinColumn(name = "trailer_id", referencedColumnName = "trailer_id")
    private Trailer trailer;
}

一个预告片可以有多个独特的物品,但同一个预告片以后可能会带来不同的独特物品集。

服务类

 public void addOrderToDB() {

        List<Trailer> trailer = new ArrayList<>();
        List<Item> items = new ArrayList<>();
        

        trailer = Trailer.builder().build();
        Item item1 = Item.builder().setTrailer(trailer).build();
        Item item2 = Item.builder().setTrailer(trailer).build();

        items.add(item1)
        items.add(item2)
       
        ItemRepository.saveAll(items);
}

我为什么要从多方面进行储蓄: 因为这里的唯一键是upc。

在我插入项目时,它正在为与同一对象的每个项目条目对应的预告片插入新条目。

预期输出:

Trailer table
trailer_id
1

Item table 
trailer_id  upc
  1         001
  1         002

实际输出:

Trailer table
trailer_id
1
2

Item table 
trailer_id  upc
  2         001
  2         002

【问题讨论】:

    标签: java spring-data-jpa hibernate-mapping


    【解决方案1】:

    您的问题是您没有正确同步关系:您让每个Item 都知道它的Trailer,但反之则不然。一个很好的方法是在你的父对象中有一个 add 和一个 remove 方法。

    @Entity
    public class Trailer {
        ...
    
        void addItem(Item item) {
            items.add(item);
            item.setTrailer(this);
        }
    
        void removeItem(Item item) {
            items.remove(item);
            item.setTrailer(null);
        }
    
        ...
    }
    

    然后使用addItem 方法将每个新的Item 添加到相应的Trailer。那么它可能与您从哪一侧保存无关。无论如何,密钥必须是唯一的,看看你如何为Item 生成密钥。

    trailer.addItem(item1);
    trailer.addItem(item2);
    repository.save(trailer);
    

    【讨论】:

    • 嘿菲利克斯,即使这样也没有解决我的问题。
    • @YASHIGUPTA Felix 给出的答案应该有效。您还可以调试并尝试检查为什么它被保存为单独的实体。您可以启用休眠日志来记录生成的 SQL 语句并检查
    【解决方案2】:
    @Entity
    public class Trailer {
    
        @Id
        @GeneratedValue(strategy = GenerationType.IDENTITY)
        @Column(name = “trailer_id", nullable = false)
        private Long trailerId;
    
        @OneToMany(mappedBy = “trailer”,cascade = CascadeType.ALL,fetch = FetchType.LAZY)
        private Set<Item> items = new HashSet<>();
    }
    

    删除redendent:

    @Entity
    public class Item {
    
        @Id
        @Column(name = “upc”, nullable = false)
        private Long upc;
    }
    

    那么,

    public void addOrderToDB() {
    
            List<Trailer> trailer = new ArrayList<>();
            List<Item> items = new ArrayList<>();
            
    
            trailer = Trailer.builder().build();
            Item item1 = Item.builder().build();
            Item item2 = Item.builder().build();
    
            trailer.add(item1);
            trailer.add(item2);
    
            items.add(item1);
            items.add(item2);
           
            ItemRepository.saveAll(items);
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-11-11
      • 1970-01-01
      • 2021-08-24
      • 1970-01-01
      • 1970-01-01
      • 2020-05-19
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多