2014-03-26 11 views
1

我想在Glassfish 3.1.2應用程序服務器上使用JLink(容器管理事務)和EclipseLink將JPA實體列表保存到MySQL數據庫中。帶JTA的Eclipselink沒有找到新插入的實體並拋出重複鍵異常

這個列表通過JMS一個接一個地作爲消息,每當消息出現時,使用無狀態的外觀,我正在查看這個實體是否存在,如果是的話,比我從同一個外觀調用更新,否則插入方法。

但是在插入一個實體之後,如果我從消息中得到相同的結果,那麼exists方法不會檢索新插入的實體,因此facade會嘗試再次插入並生成重複鍵異常。

我該如何告訴EntityManager(或其他人:-))新插入的實體應該立即可用?

理解任何幫助...

我的實體

包clearquest.crud.domain; import java.io.Serializable;

import javax.ejb.Lock; import javax.ejb.LockType; import javax.persistence。*;

import java.util.List;

@Entity @Table(名稱= 「EOM」) @NamedQueries({ @NamedQuery(名稱= 「Eom.findAll」,查詢= 「選擇E從嚴E」), @NamedQuery(名稱= 「getEomByProjectName」,query =「SELECT e FROM Eom e WHERE e.projectname =:projectname」) }) public class Eom implements Serializable {private static final long serialVersionUID = 1L; private String projectname; 私人列表缺陷;

public Eom() { 
} 


@Id 
@Column(unique=true, nullable=false, length=150) 
public String getProjectname() { 
    return this.projectname; 
} 

public void setProjectname(String projectname) { 
    this.projectname = projectname; 
} 

吾道

包clearquest.crud.domain; import java.io.Serializable;

import javax.ejb.Lock; import javax.ejb.LockType; import javax.persistence。*;

import java.util.List;

@Stateless @Singleton 公共類EomDao實現EomDaoLocal {

private @PersistenceContext(unitName = "emiClearQuestAdapterPersistancy") 
EntityManager em; 

@Override 
public void storeEom(Eom eom) { 
    em.persist(eom); 
} 

@Override 
public void updateEom(Eom eom) { 
    em.merge(eom); 
} 

@Override 
public void deleteEom(Eom eom) { 
    em.remove(eom); 
} 

@Override 
public Eom getEomByProjectName(String projectName) throws NotFoundException { 
    em.getEntityManagerFactory().getCache().evictAll(); 
    return em.find(Eom.class, projectName); 
} 

@Override 
public boolean existsEom(String projectName) { 
    try { 
     if (this.getEomByProjectName(projectName) != null) { 
      return true; 
     } else { 
      return false; 
     } 
    } 
    catch (NotFoundException e) { 
     return false; 
    } 
} 

}

與門面

包clearquest.crud.domain; import java.io.Serializable;

import javax.ejb.Lock; import javax.ejb.LockType; import javax.persistence。*;

import java.util.List;

@Stateless @Singleton 公共類DefectListFacade實現DefectListFacadeLocal {

private @EJB 
DefectDaoLocal defectdao; 
private @EJB 
EomDaoLocal eomdao; 

@Override 
public void insertdefect(CQDefect defect) { 

    String projectName = defect.getFehlerprojektnummer().getLabel(); 

    Eom eom = new Eom(); 
    eom.setProjectname(projectName); 

    Defect domaindefect = new Defect(); 
    List<Defect> defectlist = new ArrayList<Defect>(); 

    transferJsonToDomain(domaindefect, defect); 
    domaindefect.setEom(eom); 
    defectlist.add(domaindefect); 
    eom.setDefects(defectlist); 

    eomdao.storeEom(eom); 

    Logger.getLogger(DefectListFacade.class.getName()).info(
      "EOM -- INSERTED " + eom.getProjectname()); 
} 

@Override 
public void updatedefect(CQDefect defect) { 

    String projectName = defect.getFehlerprojektnummer().getLabel(); 

    Logger.getLogger(DefectListFacade.class.getName()).info(
       "EOM -- UPDATED " + projectName); 
} 

和本我的信息

@Override 
public void receiveMessage(BaseMessage message) { 
    if (message instanceof FehlerMessage) { 
     FehlerMessage fehlermsg = (FehlerMessage) message; 
     if (eomdao.existsEom(fehlermsg.getEom())) { 
      defectlistfacade.updatedefect(fehlermsg.getFehler()); 
     } else { 
      defectlistfacade.insertdefect(fehlermsg.getFehler()); 
     } 
     Logger.getLogger(FehlerMessageReceiver.class.getName()).fine(
       fehlermsg.getEom() + " - " 
         + fehlermsg.getFehler().getFehler_Titel()); 
     monitoring.notifyEMDBMessageReceive(BusType.Base, 
       message.getTypeIdentifier(), message.getSize()); 
    } 
} 

做什麼克里斯說,我發現了什麼事情後。這是一種Race Condition。

[#| 2014-03-27T11:22:39.051 + 0100 | INFO | glassfish3.1.2 | com.generali.tools.myemi.components.clearquest.crud.facade.DefectListFacade | _ThreadID = 2605; _ThreadName = Thread -10; | EOM-INSERTED PRJ-00359 |#]

[#| 2014-03-27T11:22:39.051 + 0100 | INFO | glassfish3.1.2 | com.generali.tools.myemi.components.clearquest .crud.facade.DefectListFacade | _ThreadID = 2603; _ThreadName = Thread-10; | EOM-INSERTED PRJ-00359 |#]

[#| 2014-03-27T11:22:39.051 + 0100 |警告| glassfish3 .1.2 | javax.enterprise.system.core.transaction.com.sun.jts.jta | _ThreadID = 2605; _ThreadName = Thread-10; | JTS5054:完成後出現意外錯誤

本地異常堆棧: 異常[EclipseLink的-4002(Eclipse持久服務 - 2.3.2.v20111125-r10461):org.eclipse.persistence.exceptions.DatabaseException 內部異常:com.mysql.jdbc.exceptions.jdbc4 .MySQLIntegrityConstraintViolationException:重複條目 'PRJ-00359' 的鍵 '主要' 錯誤代碼:1062 呼叫:(?)INSERT INTO EOM(PROJECTNAME)VALUES 綁定=> [約束1參數]

有2個JMS使用相同的EOM名稱(主鍵)並且線程號2605彼此相鄰的消息將首先插入EOM。但是還有另一個Number 2603的線程,它也在第一次插入後插入相同的主鍵。無論如何,第二個線程不知道第一個插入。

現在是問題,我該如何鎖定第二個插入等待第一個完成?

+1

將eclipselink日誌記錄設置爲罰款或罰款,以查看可能顯示正在發生的事務,SQL和其他消息。如果實體存在於db中,以致重複插入導致異常,則查詢應該找到它。你使用的代碼看起來很奇怪,例如注入一個entityManagerFactory而不是直接注入一個EntityManager,並且在一個事務中使用對id的查詢,而不是在事務外使用em.find(Eom.classs,projectName)。 – Chris

+0

Thx很多,通過日誌記錄我發現會發生什麼。 –

回答

1

如果您希望它們使它們可用,意味着您希望緩存中的所有操作都可以訪問數據庫。爲此,請撥打EntityManager.flush()