1

我有一个带有@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 中的事件和模块

谢谢

4

2 回答 2

1

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

persist()只打电话一次就auEvent对了。auModule但有时存在与 this 关联的现有(已经持久化,在 DB 中找到)auEvent。您将此关联标记为CascadeType.PERSIST。所以persist()也级联到现有的auModule-> exception throwed

这样的事情应该有效:
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); 
}
于 2013-06-28T12:51:47.180 回答
0

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

我希望这有帮助。

于 2013-06-28T12:12:45.440 回答