com.imos.sample.service.HibernateService.java Source code

Java tutorial

Introduction

Here is the source code for com.imos.sample.service.HibernateService.java

Source

/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package com.imos.sample.service;

import com.imos.sample.model.SMModel;
import com.imos.sample.util.RepositoryException;
import java.util.EnumSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.concurrent.locks.ReentrantLock;
import java.util.function.BiConsumer;
import java.util.function.Function;
import javax.persistence.Query;
import lombok.Setter;
import lombok.extern.log4j.Log4j2;
import org.hibernate.HibernateException;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.boot.MetadataSources;
import org.hibernate.boot.registry.StandardServiceRegistry;
import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
import org.hibernate.tool.hbm2ddl.SchemaExport;
import org.hibernate.tool.hbm2ddl.SchemaExportTask;
import org.hibernate.tool.schema.TargetType;

/**
 *
 * @author Pintu
 */
@Log4j2
public enum HibernateService {

    INSTANCE;

    @Setter
    private String filePath;
    private StandardServiceRegistry registry;
    private SessionFactory sessionFactory;
    private Session session;

    private final ReentrantLock reLock = new ReentrantLock();

    private static final BiConsumer<Session, ? super SMModel> SAVE = (s, d) -> s.persist(d);

    private static final BiConsumer<Session, ? super SMModel> DELETE = (s, d) -> s.delete(d);

    private static final BiConsumer<Session, ? super SMModel> MERGE = (s, d) -> s.merge(d);

    /**
     * Hibernate configuration.
     *
     * @throws RepositoryException
     */
    public void config() throws RepositoryException {
        try {
            StandardServiceRegistryBuilder registryBuilder = new StandardServiceRegistryBuilder();
            if (filePath == null || filePath.isEmpty()) {
                registryBuilder = registryBuilder.configure();
            } else {
                registryBuilder = registryBuilder.configure(filePath);
            }
            registry = registryBuilder.build();

            MetadataSources metaData = new MetadataSources(registry);
            sessionFactory = metaData.buildMetadata().buildSessionFactory();
            session = sessionFactory.openSession();

            SchemaExport schemaExport = new SchemaExport();
            schemaExport.setDelimiter(";");
            schemaExport.setFormat(true);
            schemaExport.setManageNamespaces(true);
            schemaExport.setOutputFile("./ddl_skilldb.sql");
            schemaExport.execute(EnumSet.of(TargetType.SCRIPT, TargetType.DATABASE, TargetType.STDOUT),
                    SchemaExport.Action.CREATE, metaData.buildMetadata(registry), registry);

            log.info("Configuration succeed");
        } catch (HibernateException e) {
            StandardServiceRegistryBuilder.destroy(registry);
            log.error("Configuration failed : {}", e);
        }
    }

    /**
     * Close Hibernate connection.
     *
     */
    public void closeConnection() {
        if (session != null && session.isOpen()) {
            session.clear();
            session.close();
            log.info("Session closed");
        }
        if (sessionFactory != null && sessionFactory.isOpen()) {
            sessionFactory.close();
            log.info("SessionFactory closed");
        }
        if (reLock.isLocked()) {
            reLock.unlock();
            log.info("lock is closed");
        }
        if (registry != null) {
            StandardServiceRegistryBuilder.destroy(registry);
            log.info("Mysql driver closed");
        }
    }

    /**
     * GET Hibernate Session.
     *
     * @return
     */
    public Session getSession() {
        checkSessionStatus();
        return session;
    }

    /**
     * Close Hibernate Session.
     *
     * @throws HibernateException
     */
    public void closeSession() {
        if (session != null && session.isOpen() && session.isJoinedToTransaction()) {
            if (session.isJoinedToTransaction()) {
                session.flush();
            }
            session.clear();
            session.close();
        }
    }

    /**
     * Get Basic Model.
     *
     * @param <T>
     * @param cls
     * @param id
     * @return
     * @throws RepositoryException
     */
    public <T extends SMModel> Optional<T> getSMModel(Class<T> cls, Long id) throws RepositoryException {
        Function<Session, Optional<T>> getSMModel = s -> {
            T obj = null;
            try {
                obj = s.get(cls, id);
            } catch (Exception e) {
                log.error(e);
            }
            return Optional.ofNullable(obj);
        };
        return HibernateService.INSTANCE.executeTransaction(getSMModel);
    }

    private <U> Optional<U> executeTransaction(Function<Session, Optional<U>> function) throws RepositoryException {
        try {
            reLock.lock();
            checkSessionStatus();
            return function.apply(session);
        } catch (HibernateException e) {
            log.error(e);
            throw new RepositoryException(e);
        } finally {
            closeSession();
            reLock.unlock();
        }
    }

    /**
     *
     * @param <T>
     * @param cls
     * @param queryStr
     * @return
     * @throws RepositoryException
     */
    public <T extends SMModel> Optional<T> getData(Class<T> cls, String queryStr) throws RepositoryException {
        Function<Session, Optional<T>> getData = s -> {
            T obj = null;
            try {
                Query query = s.createQuery(queryStr, cls);
                obj = cls.cast(query.getSingleResult());
            } catch (Exception e) {
                log.error(e);
            }
            return Optional.ofNullable(obj);
        };
        return HibernateService.INSTANCE.executeTransaction(getData);
    }

    /**
     *
     * @param <T>
     * @param cls
     * @param queryStr
     * @param parameters
     * @return
     * @throws RepositoryException
     */
    public <T extends SMModel> Optional<T> getData(Class<T> cls, String queryStr, List<Object> parameters)
            throws RepositoryException {
        Function<Session, Optional<T>> getData = s -> {

            T obj = null;
            try {
                Query query = s.createQuery(queryStr, cls);
                int index = 1;
                for (Object o : parameters) {
                    query.setParameter(index, o);
                    index++;
                }
                obj = cls.cast(query.getSingleResult());
            } catch (Exception e) {
                log.error(e);
            }
            return Optional.ofNullable(obj);
        };
        return HibernateService.INSTANCE.executeTransaction(getData);
    }

    /**
     *
     * @param <T>
     * @param cls
     * @param queryStr
     * @param parameters
     * @return
     * @throws RepositoryException
     */
    public <T extends SMModel> Optional<T> getData(Class<T> cls, String queryStr, Map<String, Object> parameters)
            throws RepositoryException {
        Function<Session, Optional<T>> getData = s -> {
            T obj = null;
            try {
                Query query = s.createQuery(queryStr, cls);
                parameters.entrySet().forEach((entry) -> {
                    query.setParameter(entry.getKey(), entry.getValue());
                });
                obj = cls.cast(query.getSingleResult());
            } catch (Exception e) {
                log.error(e);
            }
            return Optional.ofNullable(obj);
        };
        return HibernateService.INSTANCE.executeTransaction(getData);
    }

    /**
     *
     * @param <T>
     * @param cls
     * @param queryStr
     * @param parameters
     * @return
     * @throws RepositoryException
     */
    public <T extends SMModel> Optional<T> getDataAsNativeQuery(Class<T> cls, String queryStr,
            Map<String, Object> parameters) throws RepositoryException {
        Function<Session, Optional<T>> getData = s -> {
            T obj = null;
            try {
                Query query = s.createNativeQuery(queryStr, cls);
                parameters.entrySet().forEach((entry) -> {
                    query.setParameter(entry.getKey(), entry.getValue());
                });
                obj = cls.cast(query.getSingleResult());
            } catch (Exception e) {
                log.error(e);
            }
            return Optional.ofNullable(obj);
        };
        return HibernateService.INSTANCE.executeTransaction(getData);
    }

    /**
     *
     * @param <T>
     * @param cls
     * @param queryStr
     * @return
     * @throws RepositoryException
     */
    public <T extends SMModel> Optional<List<T>> getDataList(Class<T> cls, String queryStr)
            throws RepositoryException {
        Function<Session, Optional<List<T>>> getData = s -> {
            Query query = s.createQuery(queryStr, cls);
            List list = query.getResultList();
            return Optional.ofNullable(list);
        };
        return HibernateService.INSTANCE.executeTransaction(getData);
    }

    /**
     *
     * @param <T>
     * @param cls
     * @param queryStr
     * @param parameters
     * @return
     * @throws RepositoryException
     */
    public <T extends SMModel> Optional<List<T>> getDataList(Class<T> cls, String queryStr,
            Map<String, Object> parameters) throws RepositoryException {
        Function<Session, Optional<List<T>>> getData = s -> {
            Query query = s.createQuery(queryStr, cls);
            parameters.entrySet().forEach((entry) -> {
                query.setParameter(entry.getKey(), entry.getValue());
            });
            List list = query.getResultList();
            return Optional.ofNullable(list);
        };
        return HibernateService.INSTANCE.executeTransaction(getData);
    }

    /**
     *
     * @param <T>
     * @param cls
     * @param queryStr
     * @param parameters
     * @return
     * @throws RepositoryException
     */
    public <T extends SMModel> Optional<List<T>> getDataList(Class<T> cls, String queryStr, List<Object> parameters)
            throws RepositoryException {
        Function<Session, Optional<List<T>>> getData = s -> {
            Query query = s.createQuery(queryStr, cls);
            int index = 1;
            for (Object obj : parameters) {
                query.setParameter(index, obj);
                index++;
            }
            List list = query.getResultList();
            return Optional.ofNullable(list);
        };
        return HibernateService.INSTANCE.executeTransaction(getData);
    }

    /**
     *
     * @param queryStr
     * @return
     * @throws RepositoryException
     */
    public Optional<List<Object>> getDataList(String queryStr) throws RepositoryException {
        Function<Session, Optional<List<Object>>> getData = s -> {
            Query query = s.createQuery(queryStr);
            List list = query.getResultList();
            return Optional.ofNullable(list);
        };
        return HibernateService.INSTANCE.executeTransaction(getData);
    }

    /**
     *
     * @param queryStr
     * @param parameters
     * @return
     * @throws RepositoryException
     */
    public Optional<List<Object>> getDataList(String queryStr, List<Object> parameters) throws RepositoryException {
        Function<Session, Optional<List<Object>>> getData = s -> {
            List list;
            Query query = s.createQuery(queryStr);
            int index = 1;
            for (Object obj : parameters) {
                query.setParameter(index, obj);
                index++;
            }
            list = query.getResultList();
            return Optional.ofNullable(list);
        };
        return HibernateService.this.executeTransaction(getData);
    }

    /**
     *
     * @param queryStr
     * @param parameters
     * @return
     * @throws RepositoryException
     */
    public Optional<List<Object>> getDataList(String queryStr, Map<String, Object> parameters)
            throws RepositoryException {
        Function<Session, Optional<List<Object>>> getData = s -> {
            List list;
            Query query = s.createQuery(queryStr);
            parameters.entrySet().forEach((entry) -> {
                query.setParameter(entry.getKey(), entry.getValue());
            });
            list = query.getResultList();
            return Optional.ofNullable(list);
        };
        return HibernateService.INSTANCE.executeTransaction(getData);
    }

    /**
     *
     * @param queryStr
     * @param parameters
     * @return
     * @throws RepositoryException
     */
    public Optional<List<Object>> getDataListAsNativeQuery(String queryStr, Map<String, Object> parameters)
            throws RepositoryException {
        Function<Session, Optional<List<Object>>> getData = s -> {
            List list;
            Query query = s.createNativeQuery(queryStr);
            parameters.entrySet().forEach((entry) -> {
                query.setParameter(entry.getKey(), entry.getValue());
            });
            list = query.getResultList();
            return Optional.ofNullable(list);
        };
        return HibernateService.INSTANCE.executeTransaction(getData);
    }

    /**
     *
     * @param <T>
     * @param data
     * @throws RepositoryException
     */
    public <T extends SMModel> void save(T... data) throws RepositoryException {
        if (data.length == 1) {
            executeTransaction(data[0], SAVE);
        } else {
            reLock.lock();
            checkSessionStatus();
            Transaction tran = null;
            try {
                tran = session.beginTransaction();
                for (T d : data) {
                    session.save(d);
                }
                tran.commit();
            } catch (Exception e) {
                transactionRollback(tran);
                log.error(e);
                throw new RepositoryException(e);
            } finally {
                closeSession();
                reLock.unlock();
            }
        }
    }

    private void transactionRollback(Transaction tran) {
        if (tran != null && tran.isActive()) {
            tran.rollback();
        }
    }

    /**
     *
     * @param <T>
     * @param data
     * @throws RepositoryException
     */
    public <T extends SMModel> void delete(final T data) throws RepositoryException {
        executeTransaction(data, DELETE);
    }

    /**
     *
     * @param <T>
     * @param data
     * @throws RepositoryException
     */
    public <T extends SMModel> void update(T data) throws RepositoryException {
        executeTransaction(data, MERGE);
    }

    private void checkSessionStatus() throws HibernateException {
        session = Objects.requireNonNull(session);
        if (!session.isConnected() || !session.isOpen()) {
            session = sessionFactory.openSession();
        }
    }

    private <T extends SMModel> void executeTransaction(T data, BiConsumer<Session, ? super SMModel> consumer)
            throws RepositoryException {
        Transaction tran = null;
        try {
            reLock.lock();
            checkSessionStatus();
            tran = session.beginTransaction();
            consumer.accept(session, data);
            tran.commit();
            log.info(data.getClass().getSimpleName() + " is executed.");
        } catch (HibernateException e) {
            transactionRollback(tran);
            log.error("Rollback due to " + e.getMessage(), e);
            throw e;
        } finally {
            closeSession();
            reLock.unlock();
        }
    }
}