Java tutorial
package org.cobbzilla.wizard.dao; /** * Forked from dropwizard https://github.com/dropwizard/ * https://github.com/dropwizard/dropwizard/blob/master/LICENSE */ import lombok.extern.slf4j.Slf4j; import org.cobbzilla.wizard.api.CrudOperation; import org.cobbzilla.wizard.model.AuditLog; import org.cobbzilla.wizard.model.Identifiable; import org.hibernate.FlushMode; import org.hibernate.criterion.Criterion; import org.hibernate.criterion.DetachedCriteria; import org.hibernate.criterion.Order; import org.springframework.orm.hibernate4.HibernateTemplate; import org.springframework.transaction.annotation.Transactional; import javax.validation.Valid; import java.util.*; import static com.google.common.base.Preconditions.checkNotNull; import static org.cobbzilla.util.daemon.ZillaRuntime.die; import static org.cobbzilla.util.daemon.ZillaRuntime.empty; import static org.cobbzilla.util.json.JsonUtil.toJsonOrDie; import static org.cobbzilla.util.reflect.ReflectionUtil.toMap; import static org.hibernate.criterion.Restrictions.*; @Transactional @Slf4j public abstract class AbstractCRUDDAO<E extends Identifiable> extends AbstractDAO<E> { public <A extends AuditLog> AuditLogDAO<A> getAuditLogDAO() { return null; } public boolean auditingEnabled() { return getAuditLogDAO() != null; } @Transactional(readOnly = true) @Override public List<E> findAll() { return list(criteria()); } @Transactional(readOnly = true) @Override public E findByUuid(String uuid) { return findByUniqueField("uuid", uuid); } @Transactional(readOnly = true) public List<E> findByUuids(Collection<String> uuids) { return empty(uuids) ? new ArrayList<E>() : findByFieldIn("uuid", uuids); } @Transactional(readOnly = true) @Override public boolean exists(String uuid) { return findByUuid(uuid) != null; } @Override public Object preCreate(@Valid E entity) { return auditingEnabled() ? audit(null, entity, CrudOperation.create) : entity; } @Override public E postCreate(E entity, Object context) { return auditingEnabled() ? commit_audit(entity, context) : entity; } @Override public E create(@Valid E entity) { return AbstractCRUDDAO.create(entity, this); } public static <E extends Identifiable> E create(E entity, AbstractCRUDDAO<E> dao) { entity.beforeCreate(); final Object ctx = dao.preCreate(entity); setFlushMode(dao.getHibernateTemplate()); entity.setUuid((String) dao.getHibernateTemplate().save(checkNotNull(entity))); dao.getHibernateTemplate().flush(); return dao.postCreate(entity, ctx); } @Override public E createOrUpdate(@Valid E entity) { return (entity.getUuid() == null) ? create(entity) : update(entity); } public static <E extends Identifiable> E createOrUpdate(@Valid E entity, DAO<E> dao) { return (entity.getUuid() == null) ? dao.create(entity) : dao.update(entity); } public E upsert(@Valid E entity) { if (entity.getUuid() == null) throw new IllegalArgumentException("upsert: uuid must not be null"); return exists(entity.getUuid()) ? update(entity) : create(entity); } @Override public Object preUpdate(@Valid E entity) { return auditingEnabled() ? audit(findByUuid(entity.getUuid()), entity, CrudOperation.update) : entity; } @Override public E postUpdate(E entity, Object context) { return auditingEnabled() ? commit_audit(entity, context) : entity; } @Override public E update(@Valid E entity) { entity.beforeUpdate(); final Object ctx = preUpdate(entity); setFlushMode(); entity = getHibernateTemplate().merge(checkNotNull(entity)); getHibernateTemplate().flush(); return postUpdate(entity, ctx); } public static <E extends Identifiable> E update(@Valid E entity, AbstractCRUDDAO<E> dao) { final Object ctx = dao.preUpdate(entity); setFlushMode(dao.getHibernateTemplate()); entity = dao.getHibernateTemplate().merge(checkNotNull(entity)); dao.getHibernateTemplate().flush(); return dao.postUpdate(entity, ctx); } @Override public void delete(String uuid) { final E found = get(checkNotNull(uuid)); setFlushMode(); if (found != null) { final AuditLog auditLog = auditingEnabled() ? audit_delete(found) : null; getHibernateTemplate().delete(found); getHibernateTemplate().flush(); if (auditLog != null) commit_audit_delete(auditLog); } } @Transactional(readOnly = true) @Override public E findByUniqueField(String field, Object value) { return uniqueResult(value == null ? isNull(field) : eq(field, value)); } @Transactional(readOnly = true) public E findByUniqueFields(String f1, Object v1, String f2, Object v2) { final Criterion expr1 = v1 == null ? isNull(f1) : eq(f1, v1); final Criterion expr2 = v2 == null ? isNull(f2) : eq(f2, v2); return uniqueResult(and(expr1, expr2)); } @Transactional(readOnly = true) public E findByUniqueFields(String f1, Object v1, String f2, Object v2, String f3, Object v3) { final Criterion expr1 = v1 == null ? isNull(f1) : eq(f1, v1); final Criterion expr2 = v2 == null ? isNull(f2) : eq(f2, v2); final Criterion expr3 = v3 == null ? isNull(f3) : eq(f3, v3); return uniqueResult(and(expr1, expr2, expr3)); } @Transactional(readOnly = true) public E findByUniqueFields(String f1, Object v1, String f2, Object v2, String f3, Object v3, String f4, Object v4) { final Criterion expr1 = v1 == null ? isNull(f1) : eq(f1, v1); final Criterion expr2 = v2 == null ? isNull(f2) : eq(f2, v2); final Criterion expr3 = v3 == null ? isNull(f3) : eq(f3, v3); final Criterion expr4 = v4 == null ? isNull(f4) : eq(f4, v4); return uniqueResult(and(expr1, expr2, expr3, expr4)); } @Transactional(readOnly = true) @Override public List<E> findByField(String field, Object value) { return list(sort(criteria().add(eq(field, value))), 0, getFinderMaxResults()); } protected DetachedCriteria sort(DetachedCriteria criteria) { final Order order = getDefaultSortOrder(); return order == null ? criteria : criteria.addOrder(order); } public Order getDefaultSortOrder() { return null; } @Transactional(readOnly = true) @Override public List<E> findByFieldLike(String field, String value) { return list(criteria().add(ilike(field, value)).addOrder(Order.asc(field)), 0, getFinderMaxResults()); } @Transactional(readOnly = true) @Override public List<E> findByFieldEqualAndFieldLike(String eqField, Object eqValue, String likeField, String likeValue) { final Criterion expr1 = eqValue == null ? isNull(eqField) : eq(eqField, eqValue); return list(criteria().add(and(expr1, ilike(likeField, likeValue))).addOrder(Order.asc(likeField)), 0, getFinderMaxResults()); } @Transactional(readOnly = true) @Override public List<E> findByFieldIn(String field, Object[] values) { return empty(values) ? new ArrayList<E>() : list(criteria().add(in(field, values)).addOrder(Order.asc(field)), 0, getFinderMaxResults()); } @Transactional(readOnly = true) @Override public List<E> findByFieldIn(String field, Collection<?> values) { return empty(values) ? new ArrayList<E>() : list(criteria().add(in(field, values)).addOrder(Order.asc(field)), 0, getFinderMaxResults()); } protected int getFinderMaxResults() { return 100; } @Transactional(readOnly = true) public List<E> findByFields(String f1, Object v1, String f2, Object v2) { final Criterion expr1 = v1 == null ? isNull(f1) : eq(f1, v1); final Criterion expr2 = v2 == null ? isNull(f2) : eq(f2, v2); return list(sort(criteria().add(and(expr1, expr2))), 0, getFinderMaxResults()); } @Transactional(readOnly = true) public List<E> findByFields(String f1, Object v1, String f2, Object v2, String f3, Object v3) { final Criterion expr1 = v1 == null ? isNull(f1) : eq(f1, v1); final Criterion expr2 = v2 == null ? isNull(f2) : eq(f2, v2); final Criterion expr3 = v3 == null ? isNull(f3) : eq(f3, v3); return list(sort(criteria().add(and(expr1, expr2, expr3))), 0, getFinderMaxResults()); } @Transactional(readOnly = true) public List<E> findByFields(String f1, Object v1, String f2, Object v2, String f3, Object v3, String f4, Object v4) { final Criterion expr1 = v1 == null ? isNull(f1) : eq(f1, v1); final Criterion expr2 = v2 == null ? isNull(f2) : eq(f2, v2); final Criterion expr3 = v3 == null ? isNull(f3) : eq(f3, v3); final Criterion expr4 = v4 == null ? isNull(f4) : eq(f4, v4); return list(sort(criteria().add(and(expr1, expr2, expr3, expr4))), 0, getFinderMaxResults()); } @Transactional(readOnly = true) public E cacheLookup(String uuid, Map<String, E> cache) { final E thing = cache.get(uuid); return (thing != null) ? thing : findByUuid(uuid); } protected void setFlushMode() { setFlushMode(getHibernateTemplate()); } public static void setFlushMode(HibernateTemplate template) { template.getSessionFactory().getCurrentSession().setFlushMode(FlushMode.COMMIT); } private static final String PROP_AUDIT_LOG = "__auditLog"; private Object audit(E prevEntity, E newEntity, CrudOperation operation) { if (newEntity == null) die("audit(" + operation.name() + "): newEntity cannot be null"); AuditLog auditLog = getAuditLogDAO().newEntity().setEntityType(getEntityClass().getName()) .setEntityUuid(newEntity.getUuid()).setOperation(operation) .setPrevState(prevEntity == null ? null : toJsonOrDie(toMap(prevEntity))) .setNewState(toJsonOrDie(toMap(newEntity, getAuditFields(), getAuditExcludeFields()))); auditLog = getAuditLogDAO().create(auditLog); final Map<String, Object> ctx = new HashMap<>(); ctx.put(PROP_AUDIT_LOG, auditLog); return ctx; } protected String[] getAuditFields() { return null; } protected String[] getAuditExcludeFields() { return null; } private E commit_audit(E entity, Object context) { final Map<String, Object> ctx = (Map<String, Object>) context; final AuditLog auditLog = (AuditLog) ctx.get(PROP_AUDIT_LOG); auditLog.setSuccess(true); getAuditLogDAO().update(auditLog); return entity; } private AuditLog audit_delete(E found) { AuditLog auditLog = getAuditLogDAO().newEntity().setEntityType(getEntityClass().getName()) .setEntityUuid(found.getUuid()).setOperation(CrudOperation.delete) .setPrevState(toJsonOrDie(toMap(found))).setNewState(null); return getAuditLogDAO().create(auditLog); } private void commit_audit_delete(AuditLog auditLog) { auditLog.setSuccess(true); getAuditLogDAO().update(auditLog); } }