All Downloads are FREE. Search and download functionalities are using the official Maven repository.

ca.gc.aafc.dina.testsupport.DatabaseSupportService Maven / Gradle / Ivy

The newest version!
package ca.gc.aafc.dina.testsupport;

import java.io.Serializable;
import java.util.Objects;
import java.util.function.Consumer;

import javax.inject.Inject;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.EntityTransaction;
import javax.persistence.TypedQuery;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaDelete;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Root;

import org.springframework.stereotype.Service;

/**
 * Provides database access for Integration tests. All transactions are
 * rollbacked at the end of a test. Session is not exposed by design to ensure
 * constant behaviors with transactions and caching. *
 */
@Service
public class DatabaseSupportService {

  @Inject
  private EntityManager entityManager;

  // Should only be used with runInNewTransaction
  @Inject
  private EntityManagerFactory entityManagerFactory;

  protected DatabaseSupportService() {
  }

  public DatabaseSupportService(EntityManagerFactory entityManagerFactory, EntityManager entityManager) {
    this.entityManagerFactory = entityManagerFactory;
    this.entityManager = entityManager;
  }

  /**
   * Save the provided object and the session and evict the object from the
   * session. It will force a fresh load of the data when find method will be
   * called.
   * 
   * @param obj
   */
  public void save(Object obj) {
    save(obj, true);
  }

  public void save(Object obj, boolean detach) {
    entityManager.persist(obj);
    entityManager.flush();
    if (detach) {
      entityManager.detach(obj);
    }
  }

  public  T find(Class clazz, Serializable id) {
    T obj = entityManager.find(clazz, id);
    return obj;
  }

  /**
   * See {@link EntityManager#detach(Object)}.
   * 
   * @param obj
   */
  public void detach(Object obj) {
    entityManager.detach(obj);
  }

  /**
   * Find an entity based on the class, property and the property value.
   * 
   * @param clazz    The entity class being retrieved.
   * @param property The property in the entity to query against.
   * @param value    The value of the property to find the entity against.
   * @return The entity being retrieved.
   */
  public  T findUnique(Class clazz, String property, Object value) {
    // Create a criteria to retrieve the specific property.
    CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder();
    CriteriaQuery criteria = criteriaBuilder.createQuery(clazz);
    Root root = criteria.from(clazz);

    criteria.where(criteriaBuilder.equal(root.get(property), value));
    criteria.select(root);

    TypedQuery query = entityManager.createQuery(criteria);

    return query.getSingleResult();
  }

  /**
   * Remove an entity with a given id from the database.
   *
   * @param    - Type of entity
   * @param clazz - Class of the entity
   * @param id    - id of entity
   */
  public  void deleteById(Class clazz, Serializable id) {
    entityManager.remove(entityManager.find(clazz, id));
    entityManager.flush();
  }

  /**
   * Accepts a {@link Consumer} of {@link EntityManager} that will be called in a
   * new, unmanaged transaction. The main goal is to not interfere with SpringTest
   * Managed transaction. Note that the Transaction will be committed.
   * 
   * This should only be used for setup/tear down purpose.
   * 
   * @param emConsumer
   */
  public void runInNewTransaction(Consumer emConsumer) {
    EntityManager em = entityManagerFactory.createEntityManager();
    EntityTransaction et = em.getTransaction();
    et.begin();
    emConsumer.accept(em);
    em.flush();
    et.commit();
    em.close();
  }

  /**
   * Removes entitties from the database with a given property which equals a
   * given value.
   *
   * @param       - Type of entity
   * @param clazz    - Class of the entity
   * @param property - property of entity to match
   * @param value    - value of the given property
   */
  public  void deleteByProperty(Class clazz, String property, Object value) {
    deleteByProperty(clazz, property, value, false);
  }

  /**
   * Removes entitties from the database with a given property which equals a
   * given value.
   *
   * @param                  - Type of entity
   * @param clazz               - Class of the entity
   * @param property            - property of entity to match
   * @param value               - value of the given property
   * @param runInNewTransaction - True if you want to run in a seperate
   *                            transaction.
   */
  public  void deleteByProperty(Class clazz, String property, Object value, boolean runInNewTransaction) {
    if (runInNewTransaction) {
      runInNewTransaction(em -> deleteByProperty(clazz, property, value, em));
    } else {
      deleteByProperty(clazz, property, value, entityManager);
    }
  }

  /**
   * Removes entitties from the database with a given property which equals a
   * given value.
   *
   * @param       - Type of entity
   * @param clazz    - Class of the entity
   * @param property - property of entity to match
   * @param value    - value of the given property
   * @param em       - Entity Manager to use
   */
  private static  void deleteByProperty(Class clazz, String property, Object value, EntityManager em) {
    Objects.requireNonNull(clazz, "class cannot be null");
    Objects.requireNonNull(property, "property cannot be null");
    Objects.requireNonNull(em, "Entity Manager cannot be null");

    CriteriaBuilder criteriaBuilder = em.getCriteriaBuilder();
    CriteriaDelete query = criteriaBuilder.createCriteriaDelete(clazz);
    Root root = query.from(clazz);
    query.where(criteriaBuilder.equal(root.get(property), value));
    em.createQuery(query).executeUpdate();
  }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy