【问题标题】:Hibernate merge parent with detached child休眠将父级与分离的子级合并
【发布时间】:2017-09-19 11:43:42
【问题描述】:

我遇到了将实体与其集合中的一个分离的子实体合并的问题。它抛出异常: org.hibernate.PersistentObjectException:分离的实体传递给持久化:com.adastragrp.cmsms.data.SeedNumber

您可以在这个“test()”方法中看到我从数据库中获取一些队列并获取它的孩子。当它们被发送到“saveQueue()”方法时,它们处于分离状态。在这种方法中,我将它们添加到其他队列。合并此队列时,hibernate 会抛出异常。

我怎样才能让它工作?感谢您的任何回答或解释。

    private void test() {
        List<SeedNumber> list = loadQueue();
        saveQueue(list);
    }

    @Transactional
    private List<SeedNumber> loadQueue() {
        return queueDAO.find("SECONDARY").getSeedNumbers();
    }

    @Transactional
    private void saveQueue(List<SeedNumber> detachedSeeds) {
        Queue q = queueDAO.find("DEFAULT");

        List<SeedNumber> seeds = new ArrayList<>();
        SeedNumber sn = new SeedNumber();
        sn.setPhoneNumber("123456");
        sn.setQueue(q);
        seeds.add(sn);
        for(SeedNumber s : detachedSeeds) {
            s.setQueue(q);
            seeds.add(s);
        }

        q.setSeedNumbers(seeds);            

        q = queueDAO.save(q);
    }

DAO 代码:

public Queue save(Queue entity) {
    if (entity == null) {
        LOG.info("queue is null");
        return null;
    }
    if (getEntityManager().contains(entity)) {
        return entity;
    }

    entity = getEntityManager().merge(entity);

    return entity;
}

这是父类:

@Entity
@Table(name = "CMSMS_QUEUE")
public class Queue {

    @Id
    @Column(name = "ID", length = 40)
    private String id;

    @OneToMany(mappedBy = "queue", cascade = CascadeType.ALL, fetch = FetchType.EAGER)
    private List<SeedNumber> seedNumbers;

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }   

    public List<SeedNumber> getSeedNumbers() {
        return seedNumbers;
    }

    public void setSeedNumbers(List<SeedNumber> seedNumbers) {
        this.seedNumbers = seedNumbers;
    }
}

这是子类:

@Entity
@Table(name = "CMSMS_SEED_NUMBER")
@SequenceGenerator(name = "SeedNumberSeq", sequenceName = "CMSMS_SEED_NUMBER_SEQ", allocationSize = 1)
public class SeedNumber {

    @Id
    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "SeedNumberSeq")
    @Column(name = "ID")
    private Long id;

    @Column(name = "PHONE_NUMBER")
    private String phoneNumber;

    @ManyToOne(cascade = CascadeType.ALL)
    @JoinColumn(name = "QUEUE_ID")
    private Queue queue;


    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public String getPhoneNumber() {
        return phoneNumber;
    }

    public void setPhoneNumber(String phoneNumber) {
        this.phoneNumber = phoneNumber;
    }

    public Queue getQueue() {
        return queue;
    }

    public void setQueue(Queue queue) {
        this.queue = queue;
    }


}

【问题讨论】:

    标签: java spring hibernate jpa


    【解决方案1】:

    我觉得下面这段代码有问题:

    if (getEntityManager().contains(entity)) {
        return entity;
    }
    
    entity = getEntityManager().merge(entity);
    
    return entity;
    

    如果您希望 cascade=MERGE 传播到种子编号列表,则不应跳过对 merge 的调用。

    恕我直言,一个更清晰的解决方案是像这样实现saveQueue

    private void saveQueue(List<SeedNumber> detachedSeeds) {
        Queue queue = queueDAO.find("DEFAULT");
    
        SeedNumber sn = new SeedNumber();
        sn.setPhoneNumber("123456");
        sn.setQueue(q);
        seedNumberDao.saveSeed(sn);
        for (SeedNumber seed : detachedSeeds) {
            seed.setQueue(queue);
            seedNumberDao.saveSeed(seed);
        }
    }
    

    附带说明,将@Transactional 放在私有方法上没有任何效果。

    【讨论】:

    • 是的,你是对的 :) 当对象已经在 PersistanceContext 中时,我没有意识到我跳过了合并。非常感谢!关于@Transactional 注解,我使用Maven AspectJ 插件,所以它也适用于私有方法。
    猜你喜欢
    • 1970-01-01
    • 2016-11-17
    • 1970-01-01
    • 1970-01-01
    • 2023-04-06
    • 1970-01-01
    • 1970-01-01
    • 2011-11-17
    • 1970-01-01
    相关资源
    最近更新 更多