-1

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);
        }
    }

}
Adam
  • 186
  • 1
  • 4
  • 20
André
  • 172
  • 13

1 Answers1

0

I found the issue .. my ID Generation is based upon sequences and the incrementy by and the allocationsize of hibernate was not matching ... now it´s working fine see https://docs.oracle.com/javaee/5/api/javax/persistence/SequenceGenerator.html

André
  • 172
  • 13