package org.cryptocoinpartners.schema.dao;
import java.util.List;
import java.util.UUID;
import javax.persistence.EntityManager;
import javax.persistence.EntityNotFoundException;
import javax.persistence.NoResultException;
import javax.persistence.OptimisticLockException;
import javax.persistence.Query;
import javax.persistence.TypedQuery;
import org.cryptocoinpartners.enumeration.PersistanceAction;
import org.cryptocoinpartners.module.ApplicationInitializer;
import org.cryptocoinpartners.schema.EntityBase;
import org.cryptocoinpartners.util.ConfigUtil;
import org.cryptocoinpartners.util.Visitor;
import org.hibernate.PersistentObjectException;
import org.hibernate.PropertyAccessException;
import org.hibernate.StaleObjectStateException;
import org.hibernate.TransientObjectException;
import org.hibernate.TransientPropertyValueException;
import org.hibernate.exception.ConstraintViolationException;
import org.hibernate.exception.LockTimeoutException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.google.inject.Inject;
import com.google.inject.Provider;
import com.google.inject.persist.Transactional;
import com.google.inject.persist.UnitOfWork;
public abstract class DaoJpa implements Dao {
protected Class entityClass;
protected static Logger log = LoggerFactory.getLogger("org.cryptocoinpartners.persist");
private static final int defaultBatchSize = 20;
private static int retry;
static {
retry = ConfigUtil.combined().getInt("db.persist.retry");
}
@Inject
protected Provider<EntityManager> entityManager;
@Inject
protected ApplicationInitializer application;
@Inject
private UnitOfWork unitOfWork;
//protected EntityManager entityManager;
public DaoJpa() {
// ParameterizedType genericSuperclass = (ParameterizedType) getClass().getGenericSuperclass();
//this.entityClass = (Class) genericSuperclass.getActualTypeArguments()[1];
}
@Override
public void queryEach(Visitor<Object[]> handler, String queryStr, Object... params) {
try {
queryEach(handler, defaultBatchSize, queryStr, params);
} catch (Exception | Error ex) {
log.error("Unable to perform request in " + this.getClass().getSimpleName() + ":queryEach, full stack trace follows:", ex);
throw ex;
}
}
@Override
@Transactional
public void queryEach(Visitor<Object[]> handler, int batchSize, String queryStr, Object... params) {
try {
Query query = entityManager.get().createQuery(queryStr);
if (params != null) {
for (int i = 0; i < params.length; i++) {
Object param = params[i];
query.setParameter(i + 1, param); // JPA uses 1-based indexes
}
}
query.setMaxResults(batchSize);
for (int start = 0;; start += batchSize) {
query.setFirstResult(start);
List list = query.getResultList();
if (list.isEmpty())
return;
for (Object row : list) {
if (row.getClass().isArray() && !handler.handleItem((Object[]) row) || !row.getClass().isArray()
&& !handler.handleItem(new Object[] { row }))
return;
}
}
} catch (Exception | Error ex) {
log.error("Unable to perform request in " + this.getClass().getSimpleName() + ":queryEach, full stack trace follows:", ex);
throw ex;
// log.error("Unable to perform request in " + this.getClass().getSimpleName() + ":queryEach, full stack trace follows:", ex);
// ex.printStackTrace();
}
}
@Override
public <T> void queryEach(Class<T> resultType, Visitor<T> handler, String queryStr, Object... params) {
queryEach(resultType, handler, defaultBatchSize, queryStr, params);
}
@Override
@Transactional
public <T> void queryEach(Class<T> resultType, Visitor<T> handler, int batchSize, String queryStr, Object... params) {
try {
TypedQuery<T> query = entityManager.get().createQuery(queryStr, resultType);
if (params != null) {
for (int i = 0; i < params.length; i++) {
Object param = params[i];
query.setParameter(i + 1, param); // JPA uses 1-based indexes
}
}
query.setMaxResults(batchSize);
for (int start = 0;; start += batchSize) {
query.setFirstResult(start);
List<T> list = query.getResultList();
if (list.isEmpty())
return;
for (T row : list) {
if (!handler.handleItem(row))
return;
}
}
} catch (Exception | Error ex) {
log.error("Unable to perform request in " + this.getClass().getSimpleName() + ":queryEach, full stack trace follows:", ex);
throw ex;
}
}
@Override
@Transactional
public <T> T namedQueryOne(Class<T> resultType, String namedQuery, Object... params) throws NoResultException {
try {
TypedQuery<T> query = entityManager.get().createNamedQuery(namedQuery, resultType);
if (params != null) {
for (int i = 0; i < params.length; i++) {
Object param = params[i];
query.setParameter(i + 1, param); // JPA uses 1-based indexes
}
}
return query.getSingleResult();
} catch (Exception | Error ex) {
log.error("Unable to perform request in " + this.getClass().getSimpleName() + ":namedQueryOne, full stack trace follows:", ex);
throw ex;
}
}
@Override
@Transactional
public <T> T queryZeroOne(Class<T> resultType, String queryStr, Object... params) {
try {
TypedQuery<T> query = entityManager.get().createQuery(queryStr, resultType);
if (params != null) {
for (int i = 0; i < params.length; i++) {
Object param = params[i];
query.setParameter(i + 1, param); // JPA uses 1-based indexes
}
}
return query.getSingleResult();
} catch (NoResultException x) {
return null;
} catch (Error | Exception ex) {
log.error("Unable to perform request in " + this.getClass().getSimpleName() + ":queryZeroOne, full stack trace follows:", ex);
throw ex;
}
}
@Transactional
public <T> T queryOne(Class<T> resultType, String queryStr, Object... params) {
try {
TypedQuery<T> query = entityManager.get().createQuery(queryStr, resultType);
if (params != null) {
for (int i = 0; i < params.length; i++) {
Object param = params[i];
query.setParameter(i + 1, param); // JPA uses 1-based indexes
}
}
return query.getSingleResult();
} catch (NoResultException x) {
return null;
} catch (Error | Exception ex) {
log.error("Unable to perform request in " + this.getClass().getSimpleName() + ":queryOne, full stack trace follows:", ex);
throw ex;
}
}
@Override
@Transactional
public <T> List<T> queryList(Class<T> resultType, String queryStr, Object... params) {
EntityManager em = null;
try {
TypedQuery<T> query = entityManager.get().createQuery(queryStr, resultType);
if (params != null) {
for (int i = 0; i < params.length; i++) {
Object param = params[i];
query.setParameter(i + 1, param); // JPA uses 1-based indexes
}
}
return query.getResultList();
} catch (TransientObjectException toe) {
return null;
} catch (Error | Exception ex) {
log.error("Unable to perform request in " + this.getClass().getSimpleName() + ":queryList, full stack trace follows:", ex);
throw ex;
}
}
@Override
// @Transactional
// @com.google.inject.persist.Transactional
public void detach(EntityBase... entities) {
for (EntityBase entity : entities)
try {
// EntityBase existingEntity = entityManager.get().find(entity.getClass(), entity.getId());
//if (existingEntity != null) {
//entityManager.get().merge(entity);
//entityManager.get().flush();
/// } else
// update(entity);
evict(entity);
// entityManager.get().detach(entity);
// entityManager.get().detach(entity);
//entityManager.get().flush();
// log.debug("persisting entity " + entity.getClass().getSimpleName() + " " + entity);
// entityManager.get().getTransaction().commit();
}
catch (Exception | Error ex) {
log.error("Unable to perform request in " + this.getClass().getSimpleName() + ":detach, full stack trace follows:", ex);
//
throw ex;
//ex.printStackTrace();
}
}
@Override
public EntityBase refresh(EntityBase... entities) {
EntityBase localEntity = null;
for (EntityBase entity : entities)
try {
// EntityBase existingEntity = entityManager.get().find(entity.getClass(), entity.getId());
//if (existingEntity != null) {
//entityManager.get().merge(entity);
//entityManager.get().flush();
/// } else
// update(entity);
localEntity = restore(entity);
// entityManager.get().detach(entity);
// entityManager.get().detach(entity);
//entityManager.get().flush();
// log.debug("persisting entity " + entity.getClass().getSimpleName() + " " + entity);
// entityManager.get().getTransaction().commit();
}
catch (Exception | Error ex) {
log.error("Unable to perform request in " + this.getClass().getSimpleName() + ":detach, full stack trace follows:", ex);
//
throw ex;
//ex.printStackTrace();
}
return localEntity;
}
@Transactional
@Override
public <T> T find(Class<T> resultType, UUID id) {
try {
return entityManager.get().find(resultType, id);
} catch (Error | Exception ex) {
log.error("Unable to perform request in " + this.getClass().getSimpleName() + ":find, full stack trace follows:", ex);
throw ex;
}
}
@Override
@Transactional
public boolean contains(EntityBase entity) {
try {
return entityManager.get().contains(entity);
} catch (Error | Exception ex) {
log.error("Unable to perform request in " + this.getClass().getSimpleName() + ":contains, full stack trace follows:", ex);
throw ex;
}
}
@Transactional
public <T> T getReference(Class<T> resultType, UUID id) {
try {
return entityManager.get().getReference(resultType, id);
} catch (Error | Exception ex) {
log.error("Unable to perform request in " + this.getClass().getSimpleName() + ":getReference, full stack trace follows:", ex);
throw ex;
}
}
// @Override
// @Transactional
// @com.google.inject.persist.Transactional
// @Transactional
// @Inject
@Override
public void persistEntities(EntityBase... entities) {
int attempt = 0;
boolean persisted = false;
for (EntityBase entity : entities) {
try {
long revision = entity.findRevisionById();
if (entity.getRevision() > revision) {
insert(entity);
persisted = true;
}
} catch (OptimisticLockException | StaleObjectStateException ole) {
attempt = entity.getAttempt() + 1;
entity.setAttempt(attempt);
if (attempt >= retry) {
log.error(" " + this.getClass().getSimpleName() + ":persist, full stack trace follows:", ole);
entity.setAttempt(0);
throw ole;
} else {
log.debug("Later version of " + entity.getClass().getSimpleName() + " id: " + entity.getId() + " already persisted. Persist attempt "
+ entity.getAttempt() + " of " + retry);
entity.setAttempt(0);
}
} catch (LockTimeoutException lte) {
attempt = entity.getAttempt() + 1;
entity.setAttempt(attempt);
if (attempt >= retry) {
log.error(" " + this.getClass().getSimpleName() + ":persist, full stack trace follows:", lte);
entity.setAttempt(0);
throw lte;
} else {
log.error("Record locked version of " + entity.getClass().getSimpleName() + " id: " + entity.getId()
+ " already persisted. Persist attempt " + entity.getAttempt() + " of " + retry);
// entity.setRevision(0);
persist(false, entity);
}
} catch (Exception | Error ex) {
if (ex.getCause() != null && (ex.getCause() instanceof TransientPropertyValueException || ex.getCause() instanceof IllegalStateException)) {
//.setVersion(entity.getVersion() + 1);
attempt = entity.getAttempt() + 1;
entity.setAttempt(attempt);
// entity.setStartTime(entity.getDelay() * 2);
if (attempt >= retry) {
//log.error(" " + this.getClass().getSimpleName() + ":persist, Parent object not persisted for, attempting last ditch merge.");
log.error(" " + this.getClass().getSimpleName() + ":persist, full stack trace follows:", ex);
entity.setAttempt(0);
// merge(entities);
throw ex;
} else {
log.error("Parent object not persisted for " + entity.getClass().getSimpleName() + " id: " + entity.getId() + ". Persist attempt "
+ entity.getAttempt() + " of " + retry);
// entity.setRevision(0);
persist(false, entity);
// attempt++;
// continue;
}
} else if (ex.getCause() != null && ex.getCause().getCause() instanceof ConstraintViolationException) {
attempt = entity.getAttempt() + 1;
entity.setAttempt(attempt);
// entity.setStartTime(entity.getDelay() * 2);
// EntityBase dbEntity = entity.refresh();
//dbEntity = entity;
if (attempt >= retry) {
log.error(" " + this.getClass().getSimpleName() + ":persist, full stack trace follows:", ex);
entity.setAttempt(0);
throw ex;
} else {
log.debug(" " + this.getClass().getSimpleName() + " " + entity.getClass().getSimpleName() + ":" + entity.getId()
+ " :persist, primary key for version " + entity.getVersion() + " already present in db. Persist attempt "
+ entity.getAttempt() + " of " + retry);
// entity.setAttempt(0);
// entity.setRevision(0);
merge(false, entity);
}
} else if (ex.getCause() != null && ex.getCause() instanceof PersistentObjectException) {
attempt = entity.getAttempt() + 1;
entity.setAttempt(attempt);
// entity.setStartTime(entity.getDelay() * 2);
// entity.setStartTime(entity.getDelay() * 2);
// update(entity);
if (attempt >= retry) {
log.error(" " + this.getClass().getSimpleName() + ":persist, full stack trace follows:", ex);
entity.setAttempt(0);
throw ex;
} else {
log.debug(" " + this.getClass().getSimpleName() + " " + entity.getClass().getSimpleName() + ":" + entity.getId()
+ " :persist, presistent object expection, will attmpt to merge. Persist attempt " + entity.getAttempt() + " of " + retry);
// for (EntityBase entity : entities)
// entity.setAttempt(0);
// entity.setAttempt(0);
// entity.setRevision(0);
merge(false, entities);
}
} else if (ex.getCause() != null && ex.getCause() instanceof OptimisticLockException) {
attempt = entity.getAttempt() + 1;
entity.setAttempt(attempt);
// entity.setStartTime(entity.getDelay() * 2);
EntityBase dbEntity = entity.refresh();
//dbEntity = entity;
if (attempt >= retry) {
log.error(" " + this.getClass().getSimpleName() + ":persist attempt:" + entity.getAttempt() + " of " + retry
+ ", full stack trace follows:", ex);
entity.setAttempt(0);
throw ex;
} else {
log.debug(" " + this.getClass().getSimpleName() + " " + entity.getClass().getSimpleName() + ":" + entity.getId()
+ " :persist, primary key for version " + entity.getVersion() + " already present in db with version " + dbEntity.getVersion()
+ ". Persist attempt " + entity.getAttempt() + " of " + retry);
}
//for (EntityBase entity : entities)
// merge(entities);
}
else {
log.error(" " + this.getClass().getSimpleName() + ":persist, full stack trace follows:", ex);
entity.setAttempt(0);
throw ex;
}
//break;
} finally {
if (persisted) {
entity.setAttempt(0);
log.trace(" " + this.getClass().getSimpleName() + ":persist. Succefully persisted " + entity.getClass().getSimpleName() + " " + entity);
}
}
// break;
// }
}
}
// unitOfWork.end();
// break;
// }
// @Override
@Override
public void persist(EntityBase... entities) {
persist(true, entities);
}
private void persist(boolean increment, EntityBase... entities) {
try {
for (EntityBase entity : entities) {
// entity.getDao().persistEntities(entity);
if (entity != null) {
entity.setPeristanceAction(PersistanceAction.NEW);
if (increment)
entity.setRevision(entity.getRevision() + 1);
application.getInsertQueue().put(entity);
// } else {
// application.getInsertQueue().addFirst(entity);
//}
log.trace("persisting " + entity.getClass().getSimpleName() + " id:" + entity.getId());
}
}
} catch (Error | Exception e) {
log.error("Unable to resubmit insert request in " + this.getClass().getSimpleName() + "insert, full stack trace follows:", e);
// e.printStackTrace();
} finally {
}
}
@Override
public void delete(EntityBase... entities) {
delete(true, entities);
}
private void delete(boolean increment, EntityBase... entities) {
try {
for (EntityBase entity : entities) {
// entity.getDao().persistEntities(entity);
if (entity != null) {
entity.setPeristanceAction(PersistanceAction.DELETE);
if (increment)
entity.setRevision(entity.getRevision() + 1);
entity.setStartTime(entity.getDelay());
application.getInsertQueue().put(entity);
log.debug("deleting " + entity.getClass().getSimpleName() + " id:" + entity.getId());
}
}
} catch (Error | Exception e) {
log.error("Unable to resubmit delete request in " + this.getClass().getSimpleName() + "delete, full stack trace follows:", e);
// e.printStackTrace();
} finally {
}
}
/* public class persistRunnable implements Runnable {
@Override
public void run() {
while (true) {
try {
EntityBase[] entities = insertQueue.take();
persistEntities(entities);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
return; // supposing there is no cleanup or other stuff to be done
}
}
}
public persistRunnable() {
}
}*/
/* public class mergeRunnable implements Runnable {
@Override
public void run() {
while (true) {
try {
EntityBase[] entities = mergeQueue.take();
mergeEntities(entities);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
return; // supposing there is no cleanup or other stuff to be done
}
}
}
public mergeRunnable() {
}
}
*/
// @Nullable
// @ManyToOne(optional = true)
//, cascade = { CascadeType.PERSIST, CascadeType.MERGE })
//cascade = { CascadeType.ALL })
// @JoinColumn(name = "position")
// @Override
// public BlockingQueue<EntityBase[]> getInsertQueue() {
//
// return insertQueue;
// }
//
// @Override
// public BlockingQueue<EntityBase[]> getMergeQueue() {
//
// return mergeQueue;
// }
@Override
public void merge(EntityBase... entities) {
merge(true, entities);
}
// @Override
private void merge(boolean increment, EntityBase... entities) {
try {
for (EntityBase entity : entities) {
if (entity != null) {
entity.setPeristanceAction(PersistanceAction.MERGE);
if (increment)
entity.setRevision(entity.getRevision() + 1);
// entity.getDao().mergeEntities(entity);
application.getInsertQueue().put(entity);
// }
// else {
// application.getInsertQueue().addFirst(entity);
//}
log.debug("merging " + entity.getClass().getSimpleName() + " id:" + entity.getId());
}
}
} catch (Error | Exception e) {
log.error("Unable to resubmit merge request in " + this.getClass().getSimpleName() + " merge, full stack trace follows:", e);
// e.printStackTrace();
} finally {
}
}
@Transactional
public void insert(EntityBase entity) {
// try {
//entityManager.get().lock(entity, LockModeType.PESSIMISTIC_WRITE);
entityManager.get().persist(entity);
//entityManager.get().flush();
//} catch (Error | Exception ex) {
// log.error("Unable to perform request in " + this.getClass().getSimpleName() + ":getReference, full stack trace follows:", ex);
// throw ex;
// }
// entityManager.get().getTransaction().commit();
// entityManager.get().flush();
// TODO Auto-generated method stub
}
@Transactional
public EntityBase restore(EntityBase entity) {
EntityBase localEntity = null;
// try {
// localEntity = entity;
Object dBEntity;
if (!entityManager.get().contains(entity))
// try {
localEntity = entityManager.get().find(entity.getClass(), entity.getId());
if (localEntity != null)
entityManager.get().merge(entity);
// localEntity = entityManager.get().merge(entity);
//return null;
// localEntity = entityManager.get().find(entity.getClass(), entity.getId());
// entityManager.get().refresh(localEntity);
if (localEntity != null)
return localEntity;
else
return entity;
//} catch (Error | Exception ex) {
// throw ex;
// }
// TODO Auto-generated method stub
}
@Transactional
public void update(EntityBase entity) {
// try {
// entityManager.get().lock(entity, LockModeType.PESSIMISTIC_WRITE);
entityManager.get().merge(entity);
// } catch (Error | Exception ex) {
// throw ex;
// }
// TODO Auto-generated method stub
}
@Transactional
public void evict(EntityBase entity) {
try {
// entityManager.get().(entity);
entityManager.get().detach(entity);
} catch (Error | Exception ex) {
throw ex;
}
// TODO Auto-generated method stub
}
// @Override
// @Transactional
// @Override
// @Transactional
// @Inject
@Override
public void deleteEntities(EntityBase... entities) {
int attempt = 0;
boolean deleted = false;
try {
for (EntityBase entity : entities) {
long revision = entity.findRevisionById();
if (entity.getRevision() >= revision) {
attempt = entity.getAttempt();
remove(entity);
deleted = true;
}
}
} catch (EntityNotFoundException | LockTimeoutException enf) {
for (EntityBase entity : entities) {
attempt = entity.getAttempt() + 1;
entity.setAttempt(attempt);
entity.merge();
log.error("Entity " + entity.getClass().getSimpleName() + " id: " + entity.getId() + " not found in database to delete. Delete attempt "
+ entity.getAttempt() + " of " + retry);
if (attempt >= retry) {
// log.error(
// " " + this.getClass().getSimpleName() + ":delete attempt:" + entity.getAttempt() + " of " + retry + ", full stack trace follows:",
// enf);
entity.setAttempt(0);
//throw enf;
} else {
entity.setStartTime(entity.getDelay());
delete(false, entity);
}
}
} catch (OptimisticLockException | StaleObjectStateException ole) {
// unitOfWork.end();
for (EntityBase entity : entities) {
attempt = entity.getAttempt() + 1;
entity.setAttempt(attempt);
if (attempt >= retry) {
log.error(
" " + this.getClass().getSimpleName() + ":delete attempt:" + entity.getAttempt() + " of " + retry + ", full stack trace follows:",
ole);
entity.setAttempt(0);
throw ole;
}
}
for (EntityBase entity : entities) {
entity.setVersion(entity.getVersion() + 1);
entity.setStartTime(entity.getDelay());
log.error("Later version of " + entity.getClass().getSimpleName() + " id: " + entity.getId() + " already in database. Delete attempt "
+ entity.getAttempt() + " of " + retry);
}
delete(false, entities);
} catch (Exception | Error ex) {
/* if (ex.getMessage().equals("Entity not managed")) {
for (EntityBase entity : entities)
try {
//entityManager.get().persist(entity);
// restore(entity);
update(entity);
remove(entity);
// entityManager.get().refresh(entity);
//entityManager.get().remove(entity);
} catch (Exception | Error ex1) {
throw ex1;
}
// entity.refresh();
delete(entities);
}*/
if (ex.getCause() != null && ex.getCause().getCause() instanceof TransientPropertyValueException) {
for (EntityBase entity : entities) {
// entity.setVersion(entity.getVersion() + 1);
attempt = entity.getAttempt() + 1;
entity.setAttempt(attempt);
log.error("Parent object not persisted for " + entity.getClass().getSimpleName() + " id: " + entity.getId() + ". Delete attempt "
+ entity.getAttempt() + " of " + retry);
}
if (attempt >= retry) {
log.error(" " + this.getClass().getSimpleName() + ":delete, full stack trace follows:", ex);
for (EntityBase entity : entities) {
entity.setAttempt(0);
}
throw ex;
} else {
for (EntityBase entity : entities) {
// entity.setAttempt(entity.getAttempt() + 1);
entity.setStartTime(entity.getDelay());
}
delete(false, entities);
// attempt++;
//continue;
}
} else if (ex.getCause() != null && ex.getCause().getCause() instanceof ConstraintViolationException) {
for (EntityBase entity : entities) {
attempt = entity.getAttempt() + 1;
entity.setAttempt(attempt);
log.debug(" " + this.getClass().getSimpleName() + " " + entity.getClass().getSimpleName() + ":" + entity.getId()
+ " :delete, duplicate primary key already in db. Delete attempt " + entity.getAttempt() + " of " + retry);
}
if (attempt >= retry) {
log.error(" " + this.getClass().getSimpleName() + ":merge, full stack trace follows:", ex);
for (EntityBase entity : entities) {
entity.setAttempt(0);
}
throw ex;
} else {
for (EntityBase entity : entities) {
// entity.setAttempt(entity.getAttempt() + 1);
entity.setStartTime(entity.getDelay());
}
delete(false, entities);
}
} else if (ex.getCause() != null && ex.getCause() instanceof PropertyAccessException) {
for (EntityBase entity : entities) {
attempt = entity.getAttempt() + 1;
entity.setAttempt(attempt);
log.debug(" " + this.getClass().getSimpleName() + " " + entity.getClass().getSimpleName() + ":" + entity.getId()
+ " :delete issue with accessing proerpties, retrying delete. Delete attempt " + entity.getAttempt() + " of " + retry);
// entity.setStartTime(entity.getDelay() * 2);
}
if (attempt >= retry) {
log.error(" " + this.getClass().getSimpleName() + ":merge, full stack trace follows:", ex);
for (EntityBase entity : entities) {
entity.setAttempt(0);
}
throw ex;
} else {
for (EntityBase entity : entities) {
// entity.setAttempt(entity.getAttempt() + 1);
entity.setStartTime(entity.getDelay());
}
delete(false, entities);
}
} else if (ex.getCause() != null && ex.getCause() instanceof OptimisticLockException) {
for (EntityBase entity : entities) {
attempt = entity.getAttempt() + 1;
entity.setAttempt(attempt);
if (attempt >= retry) {
log.error(" " + this.getClass().getSimpleName() + ":delete attempt:" + entity.getAttempt() + " of " + retry
+ ", full stack trace follows:", ex);
entity.setAttempt(0);
throw ex;
}
}
for (EntityBase entity : entities) {
entity.setVersion(entity.getVersion() + 1);
entity.setStartTime(entity.getDelay());
log.error("Later version of " + entity.getClass().getSimpleName() + " id: " + entity.getId() + " already in database. Delete attempt "
+ entity.getAttempt() + " of " + retry);
}
//for (EntityBase entity : entities)
delete(false, entities);
} else {
log.error(" " + this.getClass().getSimpleName() + ":delete, full stack trace follows:", ex);
for (EntityBase entity : entities) {
entity.setAttempt(0);
}
throw ex;
}
// unitOfWork.end();
} finally {
if (deleted)
for (EntityBase entity : entities) {
entity.setAttempt(0);
log.trace(this.getClass().getSimpleName() + ":delete. Succefully deleted " + entity.getClass().getSimpleName() + " " + entity);
}
}
// break;
// }
// break;
// ex.printStackTrace();
}
@Override
public void mergeEntities(EntityBase... entities) {
int attempt = 0;
boolean merged = false;
try {
for (EntityBase entity : entities) {
long revision = entity.findRevisionById();
if (entity.getRevision() >= revision) {
update(entity);
merged = true;
}
}
} catch (EntityNotFoundException | IllegalArgumentException | LockTimeoutException enf) {
for (EntityBase entity : entities) {
attempt = entity.getAttempt() + 1;
entity.setAttempt(attempt);
// entity.setStartTime(entity.getDelay() * 2);f
log.error(this.getClass().getSimpleName() + "Entity " + entity.getClass().getSimpleName() + " id: " + entity.getId()
+ " not found in database, persisting. Merge attempt " + entity.getAttempt() + " of " + retry);
if (attempt >= retry) {
log.error(this.getClass().getSimpleName() + ":merge attempt:" + entity.getAttempt() + " of " + retry + ", full stack trace follows:", enf);
entity.setAttempt(0);
throw enf;
} else {
//try {
// restore(entity);
// } catch (Exception | Error ex1) {
// log.error(" " + this.getClass().getSimpleName() + ":merge attempt:" + entity.getAttempt() + " of " + retry
// + ", unable to restore entity " + entity.getClass().getSimpleName() + " id " + entity.getId());
// }
// entity.refresh();
// entity.setAttempt(0);
// well it may be in db put not in persistance context
//entity.setRevision(0);
persist(false, entity);
}
}
} catch (OptimisticLockException | StaleObjectStateException ole) {
// unitOfWork.end();
for (EntityBase entity : entities) {
attempt = entity.getAttempt() + 1;
entity.setAttempt(attempt);
if (attempt >= retry) {
log.error(" " + this.getClass().getSimpleName() + ":merge attempt:" + entity.getAttempt() + " of " + retry + ", full stack trace follows:",
ole);
entity.setAttempt(0);
throw ole;
} else {
//}
//for (EntityBase entity : entities) {
entity.setVersion(entity.getVersion() + 1);
// entity.setStartTime(entity.getDelay() * 2);
log.error("Later version of " + entity.getClass().getSimpleName() + " id: " + entity.getId() + " already merged. Merge attempt "
+ entity.getAttempt() + " of " + retry);
// entity.setRevision(0);
merge(false, entities);
}
}
} catch (Exception | Error ex) {
if (ex.getCause() != null && ex.getCause().getCause() instanceof TransientPropertyValueException) {
for (EntityBase entity : entities) {
// entity.setVersion(entity.getVersion() + 1);
attempt = entity.getAttempt() + 1;
entity.setAttempt(attempt);
log.error("Parent object not persisted for " + entity.getClass().getSimpleName() + " id: " + entity.getId() + ". Merge attempt "
+ entity.getAttempt() + " of " + retry);
if (attempt >= retry) {
log.error(" " + this.getClass().getSimpleName() + ":merge, full stack trace follows:", ex);
entity.setAttempt(0);
throw ex;
} else {
// entity.setRevision(0);
merge(false, entities);
}
}
} else if (ex.getCause() != null && ex.getCause().getCause() instanceof ConstraintViolationException) {
for (EntityBase entity : entities) {
attempt = entity.getAttempt() + 1;
entity.setAttempt(attempt);
log.debug(" " + this.getClass().getSimpleName() + " " + entity.getClass().getSimpleName() + ":" + entity.getId()
+ " :merge, duplicate primary key already in db. Persist attempt " + entity.getAttempt() + " of " + retry);
if (attempt >= retry) {
log.error(" " + this.getClass().getSimpleName() + ":merge, full stack trace follows:", ex);
entity.setAttempt(0);
throw ex;
} else {
// entity.setRevision(0);
merge(false, entities);
}
}
} else if (ex.getCause() != null && ex.getCause() instanceof PropertyAccessException) {
for (EntityBase entity : entities) {
attempt = entity.getAttempt() + 1;
entity.setAttempt(attempt);
log.debug(" " + this.getClass().getSimpleName() + " " + entity.getClass().getSimpleName() + ":" + entity.getId()
+ " :merge, issue with accessing proerpties, retrying merge. Persist attempt " + entity.getAttempt() + " of " + retry);
if (attempt >= retry) {
log.error(" " + this.getClass().getSimpleName() + ":merge, full stack trace follows:", ex);
entity.setAttempt(0);
throw ex;
} else {
// entity.setRevision(0);
merge(false, entities);
}
}
} else if (ex.getCause() != null && ex.getCause() instanceof OptimisticLockException) {
for (EntityBase entity : entities) {
attempt = entity.getAttempt() + 1;
entity.setAttempt(attempt);
if (attempt >= retry) {
log.error(" " + this.getClass().getSimpleName() + ":merge attempt:" + entity.getAttempt() + " of " + retry
+ ", full stack trace follows:", ex);
entity.setAttempt(0);
throw ex;
} else {
// }
// for (EntityBase entity : entities) {
entity.setVersion(entity.getVersion() + 1);
// entity.setStartTime(entity.getDelay() * 2);
log.error("Later version of " + entity.getClass().getSimpleName() + " id: " + entity.getId() + " already merged. Merge attempt "
+ entity.getAttempt() + " of " + retry);
// entity.setRevision(0);
merge(false, entities);
}
}
} else {
log.error(" " + this.getClass().getSimpleName() + ":merge, full stack trace follows:", ex);
for (EntityBase entity : entities)
entity.setAttempt(0);
throw ex;
}
// unitOfWork.end();
} finally {
if (merged)
for (EntityBase entity : entities) {
entity.setAttempt(0);
log.trace(" " + this.getClass().getSimpleName() + ":merge. Succefully merged " + entity.getClass().getSimpleName() + " " + entity);
}
}
}
/**
returns a single result entity. if none found, a javax.persistence.NoResultException is thrown.
*/
// @Override
// public <T> T queryOne(Class<T> resultType, String queryStr, Object... params) {
//
// final TypedQuery<T> query = entityManager.get().createQuery(queryStr, resultType);
// if (params != null) {
// for (int i = 0; i < params.length; i++) {
// Object param = params[i];
// query.setParameter(i + 1, param); // JPA uses 1-based indexes
// }
// }
// return query.getSingleResult();
//
// }
@Transactional
public void remove(EntityBase entity) {
// if (!em.contains(entity)) {
// System.out.println("delete() entity not managed: " + entity);
// utx.begin();
EntityBase target = entity;
// em.remove(target);
// utx.commit();
// EntityBase localEntity;
if (!entityManager.get().contains(entity))
target = entityManager.get().merge(entity);
/// entityManager.get().refresh(entity);
// if (localEntity != null)
entityManager.get().remove(target);
}
@Override
public <T extends EntityBase> T findById(Class<T> resultType, UUID id) throws NoResultException {
try {
return queryOne(resultType, "select x from " + resultType.getSimpleName() + " x where x.id = ?1", id);
} catch (Exception | Error ex) {
log.error("Unable to perform request in " + this.getClass().getSimpleName() + ":findById, full stack trace follows:", ex);
throw ex;
//break;
}
}
@Override
public <T> int findRevisionById(Class<T> resultType, UUID id) throws NoResultException {
try {
return queryOne(Integer.class, "select revision from " + resultType.getSimpleName() + " x where x.id = ?1", id);
} catch (Exception | Error ex) {
//log.error("Unable to perform request in " + this.getClass().getSimpleName() + ":findById, full stack trace follows:", ex);
throw ex;
//break;
}
}
}