Java JPA分离实体传递到持久化

Java JPA分离实体传递到持久化,java,spring,jpa,Java,Spring,Jpa,我有一个带有@Transactional注释和EntityManager内部的DAO 我还有一个IOC管理的bean,它内部有一个事务方法 并且有2个实体具有单向MANYOne- @Entity @Table(name = "AU_EVENT") public class AuEvent { @ManyToOne(fetch= FetchType.LAZY, cascade = {CascadeType.PERSIST, CascadeType.MERGE}) @JoinColumn(

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

我还有一个IOC管理的bean,它内部有一个事务方法

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

@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]
}
当我阅读时,我试着这样做

@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请不要建议我这样写刀法-

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中

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

我希望这会有所帮助。

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


我希望这有帮助。

在第二个示例中,您不应该调用
auevendao.persist(auEvent)最后<代码>auEvent
已附加,因此您的交易仅需结束即可。
另外,您不应该对allready persistent对象调用
persist()
。您应该只在新对象上调用它。这也是您第一个示例中的问题

auEvent
上只调用一次
persist()。但有时存在与此
auEvent
关联的现有(已持久化,在DB中找到)的
auModule
。您将此关联标记为
CascadeType.PERSIST
。因此,
persist()
也被级联到现有的
auModule
->抛出的异常

类似这样的方法应该会奏效:
一,


2.


在第二个示例中,您不应该调用
auevendao.persist(auEvent)最后<代码>auEvent
已附加,因此您的交易仅需结束即可。
另外,您不应该对allready persistent对象调用
persist()
。您应该只在新对象上调用它。这也是您第一个示例中的问题

auEvent
上只调用一次
persist()。但有时存在与此
auEvent
关联的现有(已持久化,在DB中找到)的
auModule
。您将此关联标记为
CascadeType.PERSIST
。因此,
persist()
也被级联到现有的
auModule
->抛出的异常

类似这样的方法应该会奏效:
一,


2.


很抱歉,这是我的错误-我没有写它,因为我必须调整我的代码-这是一个商业项目。我再次道歉。我很抱歉这是我的错误-我没有写它,因为我必须调整我的代码-这是一个商业项目。我再次道歉,谢谢你的帮助!但是我在1和2之间看到的唯一区别是对DAO.merge()的调用。。。我不敢相信,若我并没有调用merge(第二个变体),auModule会被保存到DB中……它应该可以工作,auEvent实体附在这里,请参见-。我更喜欢第一个选项,显式调用merge。@OndrejBozek如果提供程序足够聪明,可以执行持久化,然后执行合并,那就太好了。谢谢您的帮助!但是我在1和2之间看到的唯一区别是对DAO.merge()的调用。。。我不敢相信,若我并没有调用merge(第二个变体),auModule会被保存到DB中……它应该可以工作,auEvent实体附在这里,请参见-。我更喜欢第一个选项,显式调用merge。@OndrejBozek如果提供程序足够聪明,可以执行persist,然后执行merge,那就好了。
@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);
}
@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); 
}