我想在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的線程,它也在第一次插入後插入相同的主鍵。無論如何,第二個線程不知道第一個插入。
現在是問題,我該如何鎖定第二個插入等待第一個完成?
將eclipselink日誌記錄設置爲罰款或罰款,以查看可能顯示正在發生的事務,SQL和其他消息。如果實體存在於db中,以致重複插入導致異常,則查詢應該找到它。你使用的代碼看起來很奇怪,例如注入一個entityManagerFactory而不是直接注入一個EntityManager,並且在一個事務中使用對id的查詢,而不是在事務外使用em.find(Eom.classs,projectName)。 – Chris
Thx很多,通過日誌記錄我發現會發生什麼。 –