GeneralRepositoryImpl.java
package com.tradecloud.repository.impl;
import com.tradecloud.common.externalreference.ExternalReference;
import com.tradecloud.common.externalreference.IntegratedSystem;
import com.tradecloud.domain.common.IntegratedPersistenceBase;
import com.tradecloud.domain.costing.clean.CostedOrder;
import com.tradecloud.domain.infrastructure.persistence.CriteriaBuilder;
import com.tradecloud.domain.party.ServiceProvider;
import com.tradecloud.domain.place.NamedPlace;
import com.tradecloud.domain.search.SearchParams;
import com.tradecloud.repository.GeneralRepository;
import com.tradecloud.repository.SearchMetaParams;
import com.tradecloud.repository.base.impl.BaseHibernateDaoSupport;
import org.apache.commons.lang3.time.StopWatch;
import org.apache.log4j.Logger;
import org.hibernate.Criteria;
import org.hibernate.Query;
import org.hibernate.SQLQuery;
import org.hibernate.Session;
import org.hibernate.criterion.DetachedCriteria;
import org.hibernate.criterion.Order;
import org.hibernate.criterion.Projections;
import org.hibernate.criterion.Restrictions;
import org.hibernate.jdbc.ReturningWork;
import org.hibernate.query.NativeQuery;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.CacheManager;
import org.springframework.context.annotation.Primary;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;
import java.io.Serializable;
import java.math.BigInteger;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
/**
* Default implementation of the {@code GeneralRepository} interface.
*/
@Repository(value = "generalRepository")
@Primary
@Transactional(propagation = Propagation.REQUIRED, isolation = Isolation.DEFAULT)
public class GeneralRepositoryImpl extends BaseHibernateDaoSupport implements GeneralRepository, Serializable {
private static final long serialVersionUID = 1L;
private static final Logger log = Logger.getLogger(GeneralRepositoryImpl.class);
@Autowired
private CacheManager cacheManager;
@Override
@Transactional(readOnly = true)
public <T> List<T> findAll(Class<T> c) {
StopWatch sw = new StopWatch();
sw.start();
List<T> results = (List<T>) loadAll(c);
sw.stop();
log.debug("Found " + results.size() + " results. Class=" + c + ". Time=" + sw.getTime());
return results;
}
@Override
@Transactional(readOnly = true)
public <T> List<T> findAll(Class<T> c, SearchParams searchParams) {
StopWatch sw = new StopWatch();
sw.start();
Order resultOrdering = searchParams.isDescending() == true ? Order.desc(searchParams.getOrderBy()) : Order.asc(searchParams.getOrderBy());
DetachedCriteria criteria = DetachedCriteria.forClass(c).addOrder(resultOrdering);
// Check if we are only searching for active entities
if (searchParams.isActiveOnly()) {
criteria.add(Restrictions.eq("active", true));
}
if (c.equals(ServiceProvider.class)) {
criteria.add(Restrictions.eq("costCompareOnly", searchParams.isCostCompareOnly()));
}
@SuppressWarnings("unchecked")
List<T> results = criteria.getExecutableCriteria(getSessionCustom()).list();
sw.stop();
log.debug("Found " + results.size() + " results. Class=" + c + ". Time=" + sw.getTime());
return results;
}
@Override
@Transactional(readOnly = true)
public <T> List<T> findAllNotActive(Class<T> c, SearchParams searchParams) {
Order resultOrdering = searchParams.isDescending() == true ? Order.desc(searchParams.getOrderBy()) : Order.asc(searchParams.getOrderBy());
DetachedCriteria criteria = DetachedCriteria.forClass(c).addOrder(resultOrdering);
criteria.add(Restrictions.eq("active", false));
if (c.equals(ServiceProvider.class)) {
criteria.add(Restrictions.eq("costCompareOnly", searchParams.isCostCompareOnly()));
}
@SuppressWarnings("unchecked")
List<T> results = criteria.getExecutableCriteria(getSessionCustom()).list();
return results;
}
@Override
@Transactional(readOnly = true)
public <T> List<T> findAllActive(Class<T> c) {
DetachedCriteria criteria = DetachedCriteria.forClass(c);
criteria.add(Restrictions.eq("active", true));
@SuppressWarnings("unchecked")
List<T> results = criteria.getExecutableCriteria(getSessionCustom()).list();
return results;
}
@Override
@Transactional(readOnly = true)
public <T> int count(Class<T> c) {
return findAll(c).size();
}
@Override
public <T> long count(Class<T> c, Boolean active) {
DetachedCriteria criteria = DetachedCriteria.forClass(c);
// Check if we are only searching for active entities
if (active != null) {
criteria.add(Restrictions.eq("active", active));
}
long count = getExecutableCriteriaCount(criteria);
log.debug("Found " + count + " results. Class=" + c + ".");
return count;
}
@Override
public Object save(final Object entity) {
// TODO. What is the point of returning the passed in entity?
getCurrentSession().save(entity);
return entity;
}
@Override
public Serializable save2(Object entity) {
return getCurrentSession().save(entity);
}
@Override
public void delete(Object entity) {
try {
getCurrentSession().delete(entity);
getCurrentSession().flush();
} catch (Exception e) {
if (entity != null) {
handleDeleteConstraint(entity.getClass().getSimpleName(), e);
}
throw e;
}
}
@Override
public void deleteNoFlush(Object entity) {
try {
getCurrentSession().delete(entity);
} catch (Exception e) {
if (entity != null) {
handleDeleteConstraint(entity.getClass().getSimpleName(), e);
}
throw e;
}
}
@Override
public void update(Object entity) {
getCurrentSession().merge(entity);
}
@Override
public void refresh(Object entity) {
getCurrentSession().refresh(entity);
}
@Override
public <T> T merge(T entity) {
return (T) getCurrentSession().merge(entity);
}
@Override
public void evict(Object entity) {
if (entity != null) {
getCurrentSession().evict(entity);
}
}
@Override
@Transactional(readOnly = true)
public <T> T retrieve(Class<T> c, Long id) {
return (T) getCurrentSession().get(c, id);
}
@Override
@Transactional(readOnly = true)
public <T> T getObject(Class<T> c, Serializable id) {
return (T) getCurrentSession().get(c, id);
}
@Override
@Transactional(readOnly = true)
public <T> T retrieve(Class<T> c, String code) {
return (T) getCurrentSession().load(c, code);
}
/**
* @deprecated Turns out the reference on all the entity is really EXTERNAL
* reference. Be careful using this.
*/
@Deprecated
@Override
@Transactional(readOnly = true)
public <T> T findByReference(Class<T> c, String reference) {
@SuppressWarnings("unchecked")
T result = (T) getCurrentSession().createCriteria(c).add(Restrictions.eq("reference", reference)).uniqueResult();
return result;
}
@Transactional(readOnly = true)
public <T> T findByElcReference(Class<T> c, String reference) {
@SuppressWarnings("unchecked")
T result = (T) getCurrentSession().createCriteria(c).add(Restrictions.ilike("orderReference", reference)).uniqueResult();
return result;
}
@Override
@Transactional(readOnly = true)
public <T> T findByExternalReference(Class<T> c, String externalReference) {
@SuppressWarnings("unchecked")
T result = (T) getCurrentSession().createCriteria(c).add(Restrictions.eq("externalReference", externalReference)).uniqueResult();
return result;
}
@Override
@Transactional(readOnly = true)
public <T> List<T> findByExternalReferenceList(Class<T> c, String externalReference) {
@SuppressWarnings("unchecked")
List<T> result = getCurrentSession().createCriteria(c).add(Restrictions.eq("externalReference", externalReference)).list();
return result;
}
@Override
@Transactional(readOnly = true)
public <T> T findByName(Class<T> c, String name) {
@SuppressWarnings("unchecked")
T result = (T) getCurrentSession().createCriteria(c).add(Restrictions.eq("name", name)).uniqueResult();
return result;
}
@Override
@Transactional(readOnly = true)
public <T> List<T> findByNameList(Class<T> c, String name) {
@SuppressWarnings("unchecked")
List<T> result = getCurrentSession().createCriteria(c).add(Restrictions.eq("name", name).ignoreCase()).list();
return result;
}
@Override
@Transactional(readOnly = true)
public <T> T findByNameAndReferenceIgnoreCase(Class<T> c, String name, String externalReference) {
@SuppressWarnings("unchecked")
T result = (T) getCurrentSession().createCriteria(c).add(Restrictions.eq("name", name).ignoreCase())
.add(Restrictions.eq("externalReference", externalReference).ignoreCase())
.uniqueResult();
return result;
}
@Override
@Transactional(readOnly = true)
public <T> List<T> findByNameAndReferenceIgnoreCaseList(Class<T> c, String name, String externalReference) {
@SuppressWarnings("unchecked")
List<T> result = getCurrentSession().createCriteria(c).add(Restrictions.eq("name", name).ignoreCase())
.add(Restrictions.eq("externalReference", externalReference).ignoreCase())
.list();
return result;
}
@Override
@Transactional(readOnly = true)
public <T> T findByNumberAndReferenceIgnoreCase(Class<T> c, String number, String reference) {
@SuppressWarnings("unchecked")
T result = (T) getCurrentSession().createCriteria(c).add(Restrictions.eq("number", number).ignoreCase())
.add(Restrictions.eq("reference", reference).ignoreCase())
.uniqueResult();
return result;
}
@Override
@Transactional(readOnly = true)
public <T> T findByNumberIgnoreCase(Class<T> c, String number) {
@SuppressWarnings("unchecked")
T result = (T) getCurrentSession().createCriteria(c).add(Restrictions.eq("number", number).ignoreCase())
.uniqueResult();
return result;
}
@Override
@Transactional(readOnly = true)
public <T> T findByNumber(Class<T> c, BigInteger number) {
@SuppressWarnings("unchecked")
T result = (T) getCurrentSession().createCriteria(c).add(Restrictions.eq("number", number))
.uniqueResult();
return result;
}
@Override
public <T> List<T> findAllByNumberIgnoreCase(Class<T> entityClass, String number) {
javax.persistence.criteria.CriteriaBuilder cb = getSessionCustom().getCriteriaBuilder();
CriteriaQuery<T> query = cb.createQuery(entityClass);
Root<T> root = query.from(entityClass);
Predicate condition = cb.equal(cb.lower(root.get("number")), number.toLowerCase());
query.select(root).where(condition);
return getSessionCustom().createQuery(query).getResultList();
}
@Override
@Transactional(readOnly = true)
public <T> T findByCode(Class<T> c, String code) {
@SuppressWarnings("unchecked")
T result = (T) getCurrentSession().createCriteria(c).add(Restrictions.eq("code", code)).uniqueResult();
return result;
}
@Override
public BigInteger nextValue(String sequence) {
SQLQuery sequenceResult
= getCurrentSession().createSQLQuery("select nextval('" + sequence + "')");
return (BigInteger) sequenceResult.uniqueResult();
}
@Override
public Connection getConnection() {
@SuppressWarnings("deprecation")
Connection connection = getCurrentSession().getSessionFactory().openSession().doReturningWork(new ReturningWork<Connection>() {
@Override
public Connection execute(Connection connection) throws SQLException {
return connection;
}
});
return connection;
}
@Override
public void flush() {
getCurrentSession().flush();
}
@Override
public void initialize(final Object entity) {
initialize(entity);
}
protected <T> List<T> getExecutableCriteriaList(DetachedCriteria detachedCriteria, Class<T> c, SearchMetaParams searchMetaParams) {
// The class parameter is not strictly needed, but it will ensure you have don't have the wrong type of list.
if (searchMetaParams != null && searchMetaParams.getOrderBy() != null) {
detachedCriteria.addOrder(CriteriaBuilder.createOrdering(searchMetaParams.getOrderBy(), searchMetaParams.isAsc()));
}
Criteria criteria = detachedCriteria.getExecutableCriteria(getSessionCustom());
if (searchMetaParams != null) {
criteria.setFirstResult(searchMetaParams.getRowIndex());
criteria.setMaxResults(searchMetaParams.getRowCount());
}
@SuppressWarnings("unchecked")
List<T> results = criteria.list();
return results;
}
protected <T> List<T> getExecutableCriteriaList(DetachedCriteria criteria, Class<T> c) {
// The class parameter is not strictly needed, but it will ensure you have don't have the wrong type of list.
return (List<T>) criteria.getExecutableCriteria(getSessionCustom()).list();
}
protected long getExecutableCriteriaCount(DetachedCriteria detachedCriteria) {
detachedCriteria.setProjection(Projections.rowCount());
long count = (Long) detachedCriteria.getExecutableCriteria(getSessionCustom()).list().get(0);
log.debug("Found " + count + " results for count.");
return count;
}
@Override
@Transactional(readOnly = true)
public <T> T retrieve(Class<T> c, ExternalReference externalReference) {
DetachedCriteria criteria = DetachedCriteria.forClass(c);
criteria.add(Restrictions.eq("active", true));
DetachedCriteria eventCrit = criteria.createCriteria("externalReferences")
.add(Restrictions.eq("integratedSystem", externalReference.getIntegratedSystem()))
.add(Restrictions.eq("referenceValue", externalReference.getReferenceValue()));
eventCrit.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY);
T result = (T) criteria.getExecutableCriteria(getSessionCustom()).uniqueResult();
return result;
}
@Override
@Transactional(readOnly = true)
public <T> List<T> getAllUsedServiceProvidersByInvoices() {
String queryString = "from ServiceProvider sp where sp.id "
+ "in (select spi.serviceProvider.id from ServiceProviderInvoice spi) order by sp.name asc";
Query query = getCurrentSession().createQuery(queryString);
return (List<T>) query.list();
}
@Override
public List<Object[]> executeSql(String s, Map<String, Object> params) {
NativeQuery sqlQuery = getCurrentSession().createSQLQuery(s);
if (params != null && !params.isEmpty()) {
Set<String> strings = params.keySet();
for (String key : strings) {
sqlQuery.setParameter(key, params.get(key));
}
}
return sqlQuery.list();
}
@Override
public void executeInsertSql(String s) {
getCurrentSession().createSQLQuery(s).executeUpdate();
}
@Override
public <T> void batchSave(List<T> entities) {
for (Object o : entities) {
getCurrentSession().persist(o);
}
}
@Override
public <T> List batchMerge(List<T> entities) {
for (Object o : entities) {
o = getCurrentSession().merge(o);
}
return entities;
}
@Override
public Session getCurrentSession() {
return super.getCurrentSession();
}
@Override
@Transactional(readOnly = true)
public <T extends IntegratedPersistenceBase> String findReferenceByIntegratedSystem(Class<T> c,
IntegratedSystem integratedSystem) {
DetachedCriteria criteria = DetachedCriteria.forClass(c);
criteria.createAlias("externalReferences", "extRefs");
criteria.add(Restrictions.eq("active", true));
criteria.add(Restrictions.eq("extRefs.integratedSystem", integratedSystem));
criteria.setProjection(Projections.property("extRefs.referenceValue"));
return (String) criteria.getExecutableCriteria(getSessionCustom()).uniqueResult();
}
@Override
public List<CostedOrder> findCostedOrders(Set<Long> purchaseOrderIds) {
StringBuilder stringBuilder = new StringBuilder(" select co from CostedOrder co,PurchaseOrder po where ")
.append(" po.number=co.number and po.orderReference=co.reference ")
.append(" and po.id in (:purchaseOrderIds) ");
return getCurrentSession().createQuery(stringBuilder.toString()).setParameterList("purchaseOrderIds", purchaseOrderIds).list();
}
@Override
public void evictAllCache() {
cacheManager.getCacheNames()
.forEach(n -> cacheManager.getCache(n).clear());
}
@Override
public void persist(Object entity) {
getCurrentSession().persist(entity);
}
public Optional<NamedPlace> findNamedPlaceRegExp(String externalReference) {
String cleanedReference = preprocessReference(externalReference);
List<NamedPlace> results = getCurrentSession()
.createQuery(
"FROM NamedPlace np " +
"WHERE LOWER(FUNCTION('regexp_replace', np.name, '\\s+', '', 'g')) " +
"LIKE LOWER(FUNCTION('regexp_replace', :searchTerm, '\\s+', '', 'g'))",
NamedPlace.class)
.setParameter("searchTerm", cleanedReference)
.getResultList();
return results.stream().findFirst();
}
private String preprocessReference(String reference) {
return reference == null ? "" : reference.strip().toLowerCase().replaceAll("\\s+", "");
}
}