Java tutorial
/* * 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(); } } }