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

com.notronix.hibermate.impl.DefaultPersistenceManagerImpl Maven / Gradle / Ivy

package com.notronix.hibermate.impl;

import com.notronix.hibermate.api.*;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.boot.model.relational.Database;
import org.hibernate.jpa.TypedParameterValue;
import org.hibernate.query.NativeQuery;
import org.hibernate.resource.transaction.spi.TransactionStatus;
import org.hibernate.type.BasicTypeRegistry;
import org.hibernate.type.Type;

import java.io.Serializable;
import java.time.Instant;
import java.util.List;
import java.util.Map;

import static com.notronix.albacore.ContainerUtils.*;
import static com.notronix.albacore.NumberUtils.doubleValueOf;
import static com.notronix.albacore.NumberUtils.longValueOf;
import static java.util.Objects.requireNonNull;
import static org.apache.commons.lang3.StringUtils.isNotBlank;

public class DefaultPersistenceManagerImpl implements PersistenceManager
{
    private final BasicTypeRegistry typeRegistry;
    private final DatabaseIntegrator databaseIntegrator;
    private final SessionFactory sessionFactory;

    protected DefaultPersistenceManagerImpl(SessionFactory sessionFactory,
                                            DatabaseIntegrator databaseIntegrator,
                                            BasicTypeRegistry typeRegistry) {
        this.sessionFactory = requireNonNull(sessionFactory);
        this.databaseIntegrator = requireNonNull(databaseIntegrator);
        this.typeRegistry = requireNonNull(typeRegistry);
    }

    @Override
    public Session openSession() throws PersistenceException {
        try {
            return sessionFactory.openSession();
        }
        catch (Exception ex) {
            throw new PersistenceException("An error occurred trying to open session.");
        }
    }

    @Override
    public Session getCurrentSession() throws PersistenceException {
        try {
            return sessionFactory.getCurrentSession();
        }
        catch (Exception ex) {
            throw new PersistenceException("An error occurred trying to open session.");
        }
    }

    @Override
    public Database getDatabase() {
        return databaseIntegrator.getDatabase();
    }

    @Override
    public  K makePersistent(PersistenceCapable object) throws PersistenceException {
        Session session = openSession();
        Transaction transaction = null;
        K systemId;

        try {
            transaction = session.beginTransaction();
            //noinspection unchecked
            systemId = (K) session.save(object);
            transaction.commit();
        }
        catch (Exception e) {
            if (transaction != null && transaction.getStatus() == TransactionStatus.ACTIVE) {
                transaction.rollback();
            }

            throw new PersistenceException("An error occurred trying to persist object.", e);
        }
        finally {
            session.close();
        }

        return systemId;
    }

    @Override
    public void deletePersistent(PersistenceCapable object) throws PersistenceException {
        Transaction transaction = null;

        try (Session session = openSession()) {
            @SuppressWarnings("unchecked")
            Class> clazz = (Class>) object.getClass();
            transaction = session.beginTransaction();
            PersistenceCapable alias = session.get(clazz, object.getSystemId());
            session.delete(alias);
            transaction.commit();
        }
        catch (Exception e) {
            if (transaction != null && transaction.getStatus() == TransactionStatus.ACTIVE) {
                transaction.rollback();
            }

            throw new PersistenceException("An error occurred trying to delete object.", e);
        }
    }

    @Override
    public void update(String recordId, String objectType, PersistenceCapable object)
            throws PersistenceException {
        try {
            if (object instanceof Syncable) {
                ((Syncable) object).setLastSynchronizedDate(Instant.now());
            }

            if (PersistenceManager.itIsAValid(object)) {
                update(object);
            }
            else {
                makePersistent(object);
            }
        }
        catch (Exception ex) {
            throw new PersistenceException(recordId + ": Failed storing " + objectType + ".", ex);
        }
    }

    @Override
    public > T update(T object) throws PersistenceException {
        Session session = openSession();
        Transaction transaction = null;
        T alias;

        try {
            transaction = session.beginTransaction();

            //noinspection unchecked
            alias = (T) session.merge(object);
            transaction.commit();
        }
        catch (Exception e) {
            if (transaction != null && transaction.getStatus() == TransactionStatus.ACTIVE) {
                transaction.rollback();
            }

            throw new PersistenceException("An error occurred trying to update object.", e);
        }
        finally {
            session.close();
        }

        return alias;
    }

    @Override
    public > T get(Class objectClass, K systemId)
            throws PersistenceException {
        if (systemId == null) {
            throw new PersistenceException("systemId is null", null);
        }

        Session session = openSession();
        Transaction transaction = null;
        T alias;

        try {
            transaction = session.beginTransaction();
            alias = session.get(objectClass, systemId);
            transaction.commit();
        }
        catch (Exception e) {
            if (transaction != null && transaction.getStatus() == TransactionStatus.ACTIVE) {
                transaction.rollback();
            }

            throw new PersistenceException("An error occurred trying to get object with system id.", e);
        }
        finally {
            session.close();
        }

        return alias;
    }

    @Override
    public > T getFirst(Class objectClass) throws PersistenceException {
        return getFirst(objectClass, null, null);
    }

    @Override
    public > T getFirst(Class objectClass, String predicate)
            throws PersistenceException {
        return getFirst(objectClass, predicate, null);
    }

    @Override
    public > T getFirst(Class objectClass, String
            predicate, Map params)
            throws PersistenceException {
        return theFirst(getList(objectClass, predicate, params));
    }

    @Override
    public > List getList(Class objectClass, String join, String
            predicate, Map params)
            throws PersistenceException {
        String query = "from " + objectClass.getSimpleName();

        if (isNotBlank(join)) {
            query += " " + join;
        }

        if (isNotBlank(predicate)) {
            query += " where " + predicate;
        }

        return getList(query, params, objectClass);
    }

    @Override
    public > List getList(Class objectClass, String join, String predicate)
            throws PersistenceException {
        return getList(objectClass, join, predicate, null);
    }

    @Override
    public > List getList(Class objectClass, String
            predicate, Map params)
            throws PersistenceException {
        return getList(objectClass, null, predicate, params);
    }

    @Override
    public > List getList(Class objectClass, String predicate)
            throws PersistenceException {
        return getList(objectClass, null, predicate, null);
    }

    @Override
    public Long getLong(DBQuery query) throws PersistenceException {
        List results = getResults(query);

        if (thereAreNo(results)) {
            return null;
        }

        Object result = theFirst(results);

        if (result == null) {
            return null;
        }

        try {
            return longValueOf(result);
        }
        catch (Exception ex) {
            throw new PersistenceException("Query did not return a number value.", ex);
        }
    }

    public long getCount(Class> objectClass, String predicate)
            throws PersistenceException {
        String query = "select count(*) from " + objectClass.getSimpleName();

        if (isNotBlank(predicate)) {
            query += " " + predicate;
        }

        try (Session session = openSession()) {
            return (Long) session.createQuery(query).iterate().next();
        }
        catch (Exception ex) {
            throw new PersistenceException("Query did not return an Integer value.", ex);
        }
    }

    @Override
    public long getCount(DBQuery query) throws PersistenceException {
        List results = getResults(query);

        if (thereAreNo(results)) {
            return 0;
        }

        Object result = theFirst(results);

        if (result == null) {
            return 0;
        }

        try {
            return longValueOf(result);
        }
        catch (Exception e) {
            throw new PersistenceException("Query did not return a number value.", e);
        }
    }

    @Override
    public double getSum(DBQuery query) throws PersistenceException {
        List results = getResults(query);

        if (thereAreNo(results)) {
            return 0.0;
        }

        Object result = theFirst(results);

        if (result == null) {
            return 0.0;
        }

        try {
            return doubleValueOf(result);
        }
        catch (Exception e) {
            throw new PersistenceException("Query did not return a number value.", e);
        }
    }

    @Override
    public > List getList(DBQuery dbQuery, Class resultType)
            throws PersistenceException {
        Session session = openSession();
        Transaction transaction = null;
        List results;

        try {
            transaction = session.beginTransaction();
            NativeQuery query = dbQuery.getQuery(session, resultType);
            results = query.getResultList();
            transaction.commit();
        }
        catch (Exception e) {
            if (transaction != null && transaction.getStatus() == TransactionStatus.ACTIVE) {
                transaction.rollback();
            }

            throw new PersistenceException("An error occurred trying to execute a query.", e);
        }
        finally {
            session.close();
        }

        return results;
    }

    @Override
    public int executeManipulationQuery(DBQuery dbQuery) throws PersistenceException {
        Session session = openSession();
        Transaction transaction = null;
        int affectedItems;

        try {
            transaction = session.beginTransaction();
            NativeQuery query = dbQuery.getQuery(session, null);
            affectedItems = query.executeUpdate();
            transaction.commit();
        }
        catch (Exception e) {
            if (transaction != null && transaction.getStatus() == TransactionStatus.ACTIVE) {
                transaction.rollback();
            }

            throw new PersistenceException("An error occurred trying to execute a manipulation query.", e);
        }
        finally {
            session.close();
        }

        return affectedItems;
    }

    @Override
    public List getList(DBQuery dbQuery) throws PersistenceException {
        Session session = openSession();
        Transaction transaction = null;
        List results;

        try {
            transaction = session.beginTransaction();
            results = dbQuery.getQuery(session, null).list();
            transaction.commit();
        }
        catch (Exception e) {
            if (transaction != null && transaction.getStatus() == TransactionStatus.ACTIVE) {
                transaction.rollback();
            }

            throw new PersistenceException("An error occurred trying to execute a query.", e);
        }
        finally {
            session.close();
        }

        //noinspection unchecked
        return (List) results;
    }

    private  List getList(String query, Map params, Class resultType)
            throws PersistenceException {
        Session session = openSession();
        Transaction transaction = null;
        List results;

        try {
            transaction = session.beginTransaction();
            org.hibernate.query.Query hibernateQuery = session.createQuery(query, resultType);

            if (thereAreOneOrMore(params)) {
                for (Map.Entry entry : params.entrySet()) {
                    Object value = entry.getValue();
                    String registryKey = value.getClass().getName();
                    Type type = typeRegistry.getRegisteredType(registryKey);

                    if (type != null) {
                        value = new TypedParameterValue(type, value);
                    }

                    hibernateQuery.setParameter(entry.getKey(), value);
                }
            }

            results = hibernateQuery.list();
            transaction.commit();
        }
        catch (Exception e) {
            if (transaction != null && transaction.getStatus() == TransactionStatus.ACTIVE) {
                transaction.rollback();
            }

            throw new PersistenceException("An error occurred executing a query.", e);
        }
        finally {
            session.close();
        }

        return results;
    }

    private List getResults(DBQuery query) throws PersistenceException {
        Session session = openSession();
        Transaction transaction = null;
        List results;

        try {
            transaction = session.beginTransaction();
            NativeQuery sqlQuery = query.getQuery(session, null);
            sqlQuery.setMaxResults(1);
            results = sqlQuery.list();
            transaction.commit();
        }
        catch (Exception e) {
            if (transaction != null && transaction.getStatus() == TransactionStatus.ACTIVE) {
                transaction.rollback();
            }

            throw new PersistenceException("An error occurred trying to get the count.", e);
        }
        finally {
            session.close();
        }

        return results;
    }
}