I have a NO Interface View bean (Stateless) which has an asyncronous method. This method is performing persistence access via a Container Managed EntityManager. Unfortunately, it generates Constraint Violation Exceptions when inserting into the Db (Primary Key violation ) the JPA Entity is using a Sequence as the ID generator. Hibernate seems to use the same ID's on different entities, how can I synchronize the access upon the contained managed entity manager without loosing the container managed transactions?
@Singleton
@Startup
public class Loeschung {
private static Logger log = LoggerFactory.getLogger(Loeschung.class);
@Resource
TimerService timerService;
@Resource
private String configMandanten;
private ConcurrentMap<String, Map.Entry<String, Long>> servicesderMandanten;
@PostConstruct
public void initialize() {
// init timer
}
}
private Loeschlauf lookupService(String serviceName) {
try {
return InitialContext.<Loeschlauf>doLookup(serviceName);
} catch (NamingException e) {
// wenn dies auftritt ist der JNDI Name falsch !!
if (log.isErrorEnabled()) {
log.error(LogUtil.UNHANDLED, LogUtil.createUnhandledMessageArgs(e));
}
}
return null;
}
@Timeout
public void LoeschlaufInitiieren(Timer timer) {
Loeschlauf service = null;
try {
service = InitialContext.<Loeschlauf>doLookup(this.servicesderMandanten.get(timer.getInfo().toString()).getKey());
} catch (NamingException e) {
}
return;
}
service.run();
}
}
@Stateless
public class Loeschlauf {
private static Logger log = LoggerFactory.getLogger(Loeschlauf.class);
@PersistenceContext
protected EntityManager entityManager;
@Asynchronous
public void run() {
LoeschProtokoll protokoll = LoeschProtokoll.erstelleLeeresProtokoll();
// vormerken der zu löschenden Protokolle
// ermittle Gesamtanzahl
Long anzahlElemente = markiereProtokolleAlsgeloescht();
protokoll.setAnzahlGeloescht(anzahlElemente);
Long anzahlGeperrteElemente = getAnzahlGesperrterElemente();
protokoll.setAnzahlGesperrt(anzahlGeperrteElemente);
// Aktualisierung des Personen index
aktualisierePersonenIndex();
// Löschung der Protokolle
loescheAbgelaufeneProtokolle();
// Fortschreiben des Löschprotokolls
protokoll.setEnde(LocalDateTime.now());
speichereLoeschProtokoll(protokoll);
}
public Long markiereProtokolleAlsgeloescht() {
return Long.valueOf(entityManager.createNamedQuery(TransaktionsProtokoll.MARKIERE_ALS_GELOESCHT).executeUpdate()) ;
}
public Long getAnzahlGesperrterElemente() {
return (Long) entityManager.createNamedQuery(TransaktionsProtokoll.ERMITTLE_ANZAHL_GESPERRTE_ELEMENTE)
.getSingleResult();
}
public Long getAnzahlZuBearbeitenderPersonenIndexe() {
return (Long) entityManager.createNamedQuery(PersonenIndex.COUNT_GELOESCHTE_PROTOKOLLE).getSingleResult();
}
public void aktualisierePersonenIndex() {
Long gesamtAnzahl= getAnzahlZuBearbeitenderPersonenIndexe();
int seitenGroeße = 10;
int letzeSeite = (int) ((gesamtAnzahl / seitenGroeße) + 1);
TypedQuery<PersonenIndex> query = entityManager.createNamedQuery(PersonenIndex.FIND_BY_GELOESCHTE_PROTOKOLLE, PersonenIndex.class);
int pageNumber = 1;
for (int i = pageNumber; i <= letzeSeite; i++) {
query.setFirstResult((pageNumber-1) * seitenGroeße);
query.setMaxResults(seitenGroeße);
List<PersonenIndex> indexe = query.getResultList();
indexe.stream().forEach( index -> this.behandeleIndex(index));
}
}
private void behandeleIndex(PersonenIndex index) {
index.getTransaktionen().clear();
entityManager.persist(index);
PersonenIndex kompletteVersion = entityManager.find(PersonenIndex.class, index.getId());
if (kompletteVersion.IsLeer()) {
entityManager.remove(kompletteVersion);
}
}
public void loescheAbgelaufeneProtokolle() {
entityManager.createNamedQuery(TransaktionsProtokoll.LOESCHE_GELOESCHTE_ELEMENTE).executeUpdate();
}
public void speichereLoeschProtokoll(LoeschProtokoll protokoll) {
entityManager.persist(protokoll);
entityManager.flush();
}
public LocalDateTime ermittleStartzeitpunkt() {
Optional<LoeschProtokoll> eintrag = entityManager.createNamedQuery(LoeschProtokoll.FINDE_JUENGSTEN_EINTRAG, LoeschProtokoll.class).getResultStream().findFirst();
if (eintrag.isPresent()) {
return eintrag.get().getBeginn();
}else {
return LocalDateTime.of(1970, 1, 1, 2, 0);
}
}
}