JPA分离实体传递给持久化

时间:2013-06-28 10:27:26

标签: java spring jpa

我有一个带有@Transactional注释且里面有EntityManager的DAO。

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

并且有2个实体具有单向多数2 -

@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中的事件和模块

由于

2 个答案:

答案 0 :(得分:1)

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

您只能在persist()上拨打auEvent一次,这是正确的。但有时存在(已在数据库中保留,已在数据库中找到)auModule与此auEvent相关联。并且您将此关联标记为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 :(得分:0)

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

我希望这会有所帮助。