请教一个JPA多对多级联保存的问题

实体类

// 标签类
@Entity
public class Label {
    @Id
    @Column(name = "lid",unique = true,nullable = false)
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Integer lid;
    private String tag;
    @ManyToMany(fetch = FetchType.EAGER)
    @Cascade(value = {CascadeType.ALL}) // 设置级联关系
    @JoinTable(name = "song_label",// 指定第三张表
            joinColumns = {@JoinColumn(name = "label_id")},//本表与中间表的外键对应
            inverseJoinColumns = {@JoinColumn(name = "song_id")}
        )
    private Set<Song> songs = new HashSet<>();
    // setter and getter
 }

// 歌曲类
@Entity
public class Song {
    @Id
    @Column(name = "sid",unique = true,nullable = false)
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Integer sid;
    private String title;
    private String special;
    @ManyToMany(fetch = FetchType.EAGER)
    @Cascade(value = { CascadeType.ALL})
    @JoinTable(
            name = "song_label",
            joinColumns = {@JoinColumn(name = "song_id")},//本表与中间表的外键对应
            inverseJoinColumns = {@JoinColumn(name = "label_id")}
    )
    private Set<Label> labels = new HashSet<>();
     // setter and getter
  }

关联关系: 一首歌曲可以对应多个标签,一个标签可以对应多首歌曲

遇到的级联保存问题: 在添加已经存在的标签记录时保错org.hibernate.PersistentObjectException: detached entity passed to persist
测试代码

    @Test
    public void test1() {
        Song song = new Song();
        song.setSpecial("等你下课");
        song.setTitle("等你下课");

        Label label1 = new Label();
        label1.setTag("华语");
        Label label2 = new Label();
        label2.setTag("内地");
        song.getLabels().add(label1);
        song.getLabels().add(label2);

        this.songDao.save(song);//因设置级联关系CascadeType.ALL相应会在Label表添加记录
    }
    
        @Test
        public void test123(){
            Song song = new Song();
            song.setSpecial("流星花园");
            song.setTitle("北极星的眼泪");
            Label label1 = this.labelDao.findByTag("爱情");
            Label label2 = this.labelDao.findByTag("华语");
            if (label2 == null){
                label2 = new Label();
                label2.setTag("华语");
            }
            if(label1 == null){
                label1 = new Label();
                label1.setTag("爱情");
            }
    
            song.getLabels().add(label1);
            song.getLabels().add(label2);
    
            this.songDao.save(song);// 报错org.hibernate.PersistentObjectException: detached entity passed to persist: com.example.data.bean.Label
        }

test1()能够添加成功,到了test2时由于Label表存在"华语"这条记录,保存会出错
疑问:如何在Label表存在记录时执行更新而不是保存?

在此先感谢大神路过指点迷津哈哈

阅读 6.8k
1 个回答

只需要将CascadeType.ALL修改为CascadeType.MERGE
然后在新增数据时自己手动关联表即可

 @Test
 public void test123(){
     
        this.labelDao.save(label1);
        this.labelDao.save(label2);
        this.songDao.save(song);// 报错org.hibernate.PersistentObjectException: detached entity passed to persist: com.example.data.bean.Label
        }
撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题