【问题标题】:JPA detached entity passed to persistJPA 分离实体传递给持久化
【发布时间】:2013-06-26 02:28:13
【问题描述】:

我有一个带有@Transactional 注释和EntityManager 内部的DAO。

我还有一个 IOC 托管 bean,里面有一个事务方法。

并且有2个实体具有单向many2one -

@Entity
@Table(name = "AU_EVENT")
public class AuEvent { 
    @ManyToOne(fetch= FetchType.LAZY, cascade = {CascadeType.PERSIST, CascadeType.MERGE})
@JoinColumn(name = "MODULE_ID")
private AuModule auModule;
}

AuModule 在AuEvents 上没有参考

我正在尝试这样做

@Async
@Transactional(propagation = Propagation.REQUIRED)
public void onEvent(String moduleName, String instanceName){
        AuModule auModule = auModuleDao.findModule(moduleName, instanceName);
        if (auModule == null) {
            auModule = new AuModule();
            auModule.setInstance(instanceName);
            auModule.setName(moduleName);
        }
//doesnt help
//auModule = auModuleDao.getEntityManager().merge(auModule);

AuEvent auEvent = new AuEvent();
auEvent.setAuModule(auModule);
auEventDao.persist(auEvent); // error here [AuModule detached]
}

正如我在https://stackoverflow.com/questions/14057333/detached-entity-passed-to-persist-error-with-onetomany-relation 中读到的那样,我试图这样做

@Async
@Transactional(propagation = Propagation.REQUIRED)
public void onEvent(String moduleName, String instanceName){

    AuEvent auEvent = new AuEvent();
    auEventDao.persist(auEvent);

    AuModule auModule = auModuleDao.findModule(moduleName, instanceName);
    if (auModule == null) {
        auModule = new AuModule();
        auModule.setInstance(instanceName);
        auModule.setName(moduleName);
    }
    auEvent.setAuModule(auModule);
    auEventDao.persist(auEvent); // error here [AuEvent detached]
}

所以,有谁知道我怎样才能避免这种情况? PS 请不要建议我写这样的 DAO 方法 -

public void saveEvent(AuEvent auEvent, String moduleName, String instanceName){
    log.info("saveEvent({}) called...", auEvent);
    AuModule auModule = auModuleDao.findModule(moduleName, instanceName);
    if (auModule == null) {
        auModule = new AuModule();
        auModule.setInstance(instanceName);
        auModule.setName(moduleName);
    }
    auEvent.setAuModule(auModule);
    persist(auEvent);
}

我确实想保存不在任何 DAO 中的事件和模块

谢谢

【问题讨论】:

    标签: java spring jpa


    【解决方案1】:

    在第二个例子中,最后你不应该调用auEventDao.persist(auEvent);auEvent附加,因此您的交易刚刚结束。
    此外,您不应该在已经持久化的对象上调用 persist()。您应该只在新对象上调用它。这也是您的第一个示例中的问题。

    你在auEvent 上只给persist() 打过一次电话,没错。但有时存在与此 auEvent 相关联的现有(已持久化,在 DB 中找到)auModule。你用CascadeType.PERSIST 标记了这个关联。所以persist() 也被级联到现有的auModule -> 异常抛出

    这样的事情应该可以工作:
    1.

    @Async
    @Transactional(propagation = Propagation.REQUIRED)
    public void onEvent(String moduleName, String instanceName){
            AuModule auModule = auModuleDao.findModule(moduleName, instanceName);
            if (auModule == null) {
                auModule = new AuModule();
                auModule.setInstance(instanceName);
                auModule.setName(moduleName);
            }
           AuEvent auEvent = new AuEvent();
           auEventDao.persist(auEvent); 
    
           auEvent.setAuModule(auModule);
           auEventDao.merge(auEvent);
    }
    


    2.

    @Async
    @Transactional(propagation = Propagation.REQUIRED)
    public void onEvent(String moduleName, String instanceName){
    
        AuEvent auEvent = new AuEvent();
        auEventDao.persist(auEvent);
    
        AuModule auModule = auModuleDao.findModule(moduleName, instanceName);
        if (auModule == null) {
            auModule = new AuModule();
            auModule.setInstance(instanceName);
            auModule.setName(moduleName);
        }
        auEvent.setAuModule(auModule);
        // optioanlly you can call here - auEventDao.merge(auEvent); 
    }
    

    【讨论】:

    • 感谢您的帮助!但我在 1 和 2 之间看到的唯一区别是调用 DAO.merge()...我不敢相信如果我不调用合并(第二个变体)auModule 会被保存到数据库中...
    • 它应该可以工作,auEvent 实体是 attached 见 - stackoverflow.com/questions/1069992/… 。我更喜欢第一个选项,明确调用合并。
    • @OndrejBozek 如果提供者足够聪明地进行持久化然后进行合并,那就太好了。
    【解决方案2】:

    在 onEvent() 方法中,您没有像在 saveEvent() 方法中那样在 if 之后设置 AuEvent 中的 AuModule。

    我希望这会有所帮助。

    【讨论】:

    • 很抱歉这是我的错误——我没有写它是因为我必须调整我的代码——它是一个商业项目。我再次道歉。
    猜你喜欢
    • 2017-10-21
    • 1970-01-01
    • 2015-12-26
    • 1970-01-01
    • 2020-12-27
    • 1970-01-01
    • 1970-01-01
    • 2018-01-05
    • 2017-04-01
    相关资源
    最近更新 更多