【问题标题】:Hibernate ManyToMany save休眠多对多保存
【发布时间】:2017-07-07 15:17:49
【问题描述】:

我有两个具有多对多关系的类,我想创建受众并稍后将它们添加到事件中,但它会引发“分离”异常。

class Event {
    @ManyToMany(
            fetch = FetchType.LAZY,
            targetEntity = Audience.class,
            cascade = {CascadeType.PERSIST, CascadeType.MERGE})
    @JoinTable(name = "UC_EVENT_AUDIENCE",
            joinColumns = @JoinColumn(name = "event_id"),
            inverseJoinColumns = @JoinColumn(name = "audience_id"))    
    private List<Audience> targetAudiences = new ArrayList<>();
}

clsas Audience {
    @ManyToMany(fetch = FetchType.LAZY, mappedBy = "targetAudiences")
    private List<Event> events = new ArrayList<>();
}

public void run(ApplicationArguments args) throws Exception {
    //Generate audience data
    List<Audience> audiences = dataGenerator.createAudiences();
    //Save to db
    audienceRepository.save(audiences);

    Event event = new Event();
    event.setTargetAudiences(audiences);    
    eventRepository.save(events);
}

【问题讨论】:

    标签: java hibernate spring-data-jpa


    【解决方案1】:

    您首先保存观众,但在您的代码中定义的关系:

    事件将处理观众的持久性,因为:

     @ManyToMany(
                fetch = FetchType.LAZY,
                targetEntity = Audience.class,
                cascade = {CascadeType.PERSIST, CascadeType.MERGE})
    

    所以你首先创建受众,然后创建事件,然后将受众列表附加到事件,最后将事件对象保存到数据库中。

    【讨论】:

    • 你的意思是,如果我评论“audienceRepository.save(audiences)”然后保存“Event”,它会保存我的 Audience?我忽略了“audienceRepository.save(audiences)”,看起来 Event 没有保存它,因为当我“findAll”Audiences 时什么都没有。
    • 你是通过事件对象找观众还是直接找观众?
    • 您还必须在保存活动之前为观众设置活动。因为它是双向的关系
    • 谢谢,我会这样做的。所有这些休眠绑定都令人困惑。
    • 是的,绑定令人困惑,但请尝试使用用例以获得更好的理解。 howtoprogramwithjava.com/… 试试这个链接,它可能有助于理解双向关系。
    【解决方案2】:

    我这样做了,它对我有用:

    public class Event {
    
        @ManyToMany(fetch = FetchType.EAGER)
        @JoinTable(name = "event_audience",
                joinColumns = @JoinColumn(name = "event_id"),
                inverseJoinColumns = @JoinColumn(name = "audience_id"),
                uniqueConstraints = @UniqueConstraint(columnNames = {"event_id", "audience_id"}))
        private List<Audience> audiences = new ArrayList<>();
    }
    
    public class Audience {
    
        @Column(name = "audience_name", nullable = false, unique = true)
        private String name;
    }
    

    我还有两个存储库,用于保存扩展 spring 的 JpaRepository 的 Audience 和 Events。

    现在我可以像这样创建受众:

    audienceRepository.save(new Audience("Name"));
    

    然后像这样将它们添加到我的事件中:

    Event eventFirst = new Event();
    eventFirst.getAudiences().add(audiences.get(0));
    eventRepository.save(eventFirst);
    

    【讨论】:

      【解决方案3】:

      作为一种变体,您可以使用像这样的“PrePersist”实用程序方法来“链接”事件和受众:

      @Entity
      public class Event {
      
          @ManyToMany(cascade = {CascadeType.PERSIST, CascadeType.MERGE})
          private final Set<Audience> audiences = new HashSet<>();
      
          @PrePersist
          public void addAudiences() {
              audiences.forEach(audience -> audience.getEvents().add(this));
          }
      }
      
      @Entity
      public class Audience {
      
          @ManyToMany(mappedBy = "audiences")
          private final Set<Event> events = new HashSet<>();
      
          //...
          public Set<Event> getEvents() {
              return events;
          }
      }
      

      有关多对多关联和“实用程序方法”的更多信息:Hibernate User Guide

      我的exampletests

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2018-01-11
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多