Eclipselink с JTA не намира нововмъкнатия обект и хвърля изключение за дублиран ключ

Искам да запазя списък с JPA обекти в MySQL база данни, използвайки JTA (транзакции, управлявани от контейнери) с EclipseLink на сървър за приложения Glassfish 3.1.2.

Списъкът идва през JMS едно по едно като съобщения, всеки път, когато дойде съобщение, използвайки фасада без състояние, търся дали този обект съществува, ако да, тогава извиквам от същата фасада актуализацията, в противен случай метода за вмъкване.

Въпреки това след вмъкването на един обект, ако получа същото от съобщението, съществуващият метод не извлича нововмъкнатия и следователно фасадата се опитва да го вмъкне отново с произтичащо дублиращ се ключ изключение.

Как мога да кажа на EntityManager (или някой друг :-) ), че нововмъкнатите обекти трябва да бъдат налични незабавно?

Всяка помощ се оценява...

МОЯТА СУЩНОСТ

пакет clearquest.crud.domain; импортиране на java.io.Serializable;

импортиране на javax.ejb.Lock; импортиране на javax.ejb.LockType; импортиране на javax.persistence.*;

импортиране на java.util.List;

@Entity @Table(name="eom") @NamedQueries ({ @NamedQuery(name="Eom.findAll", query="SELECT e FROM Eom e")), @NamedQuery(name="getEomByProjectName", query="SELECT e FROM Eom e WHERE e.projectname = :projectname") }) public class Eom implements Serializable { private static final long serialVersionUID = 1L; private String име на проект; дефекти в частния списък;

public Eom() {
}


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

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

Моят DAO

пакет clearquest.crud.domain; импортиране на java.io.Serializable;

импортиране на javax.ejb.Lock; импортиране на javax.ejb.LockType; импортиране на javax.persistence.*;

импортиране на 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; импортиране на java.io.Serializable;

импортиране на javax.ejb.Lock; импортиране на javax.ejb.LockType; импортиране на javax.persistence.*;

импортиране на 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());
    }
}

След като направих казаното от Крис, разбрах какво се случва. Това е вид състезателно състояние.

[#|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 -- ВМЪКНАТО 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 -- ВМЪКНАТО 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 Persistence Services - 2.3.2.v20111125-r10461): org.eclipse.persistence.exceptions.DatabaseException Вътрешно изключение: com.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraint ViolationException: Дублиран запис „PRJ-00359“ за ключ „PRIMARY“ Код на грешка: 1062 Обаждане: INSERT INTO eom (PROJECTNAME) VALUES (?) bind => [1 параметър обвързан]

Има 2 JMS съобщения, които идват едно до друго с едно и също EOM име (първичен ключ) и нишката номер 2605 вмъква EOM първо. Но има друга нишка с номер 2603, която също вмъква същия първичен ключ точно след първото вмъкване. Така или иначе втората нишка не е наясно с първата вмъкната.

Сега е въпросът как мога да заключа, че второто вмъкване изчаква първото да завърши?


person i-developer    schedule 26.03.2014    source източник
comment
Задайте регистрирането на eclipselink на фино или най-фино, за да видите транзакцията, SQL и други съобщения, които може да показват какво се случва. Ако обектът съществува в db, така че дублираното вмъкване причинява изключение, тогава заявка трябва да го намери. Кодът, който използвате, обаче изглежда странен, като например инжектиране на entityManagerFactory вместо директно инжектиране на EntityManager и използване на заявка за id в транзакция вместо използване на em.find(Eom.classs, projectName) извън транзакция.   -  person Chris    schedule 27.03.2014
comment
Благодаря много, чрез регистриране разбрах какво се случва.   -  person i-developer    schedule 27.03.2014


Отговори (1)


Ако искате те да ги направят достъпни, означава, че искате всички операции в кеша да достигнат до DB. За да направите това, обадете се на EntityManager.flush().

person Andrei I    schedule 27.03.2014