Java tutorial
/* * Copyright 2012-2015, the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.trpr.dataaccess.orm.handler; import java.sql.SQLException; import java.util.Collection; import java.util.LinkedList; import java.util.List; import javax.sql.DataSource; import org.trpr.dataaccess.RDBMSHandler; import org.trpr.dataaccess.RDBMSIdentifier; import org.trpr.platform.core.impl.logging.NullMetricsLogger; import org.trpr.platform.core.spi.logging.PerformanceMetricsLogger; import org.trpr.platform.core.spi.persistence.Criteria; import org.trpr.platform.core.spi.persistence.IncorrectResultSizePersistenceException; import org.trpr.platform.core.spi.persistence.PersistenceException; import org.trpr.platform.core.spi.persistence.PersistenceHandler; import org.trpr.platform.core.spi.persistence.PersistentEntity; import org.hibernate.HibernateException; import org.hibernate.Query; import org.hibernate.SQLQuery; import org.hibernate.Session; import org.springframework.dao.DataAccessException; import org.springframework.dao.DataIntegrityViolationException; import org.springframework.jmx.export.annotation.ManagedOperation; import org.springframework.jmx.export.annotation.ManagedResource; import org.springframework.orm.hibernate3.HibernateCallback; import org.springframework.orm.hibernate3.HibernateTemplate; import org.springframework.orm.hibernate3.SessionFactoryUtils; /** * The <code>HibernateHandler</code> is an implementation of {@link PersistenceHandler} that uses Hibernate as the persistence framework. * Hibernate is used via the Spring {@link HibernateTemplate}. * * This class is also instrumented to log performance metrics using the platform-core {@link PerformanceMetricsLogger} * * @author Ashok Ayengar, Raja S, Regunath B * @version 1.0, 24/05/2012 */ @ManagedResource(objectName = "spring.application:application=Trooper-Perf-Metrics,type=PerformanceMetrics,name=HibernatePerfMetrics", description = "Hibernate Performance Metrics Logger") public class HibernateHandler extends RDBMSHandler { /** * The PerformanceMetricsLogger instance to use for capturing metrics of code block execution. Initialized with the Null logger * The real logger may be injected using {@link #setPerformanceMetricsLogger(PerformanceMetricsLogger)} */ private PerformanceMetricsLogger performanceMetricsLogger = new NullMetricsLogger(); /** * Hibernate Template to provide the hibernate API. */ private HibernateTemplate template; /** * No arg constructor. */ public HibernateHandler() { } /** * Interface method implementation * @see PersistenceHandler#findEntities(Criteria) */ @SuppressWarnings("unchecked") public Collection<PersistentEntity> findEntities(final Criteria criteria) throws PersistenceException { // signal performance metrics capture. actual capture will happen only if it has been enabled via #startPerformanceMetricsLogging(). Default is off this.performanceMetricsLogger.startPerformanceMetricsCapture(); if (criteria.getQueryType() == Criteria.NATIVE_QUERY) { return findObjectBySQLQuery(criteria); } Collection<PersistentEntity> results = new LinkedList<PersistentEntity>(); // create an empty list if (criteria.getMaxResults() > 0) { results = (Collection<PersistentEntity>) this.getTemplate().execute(new HibernateCallback() { public Object doInHibernate(Session session) throws HibernateException, SQLException { Query query = null; if (Criteria.NAMED_QUERY == criteria.getQueryType()) { query = session.getNamedQuery(criteria.getQuery()); } else { query = session.createQuery(criteria.getQuery()); } query.setFirstResult(criteria.getFirstResult()); query.setMaxResults(criteria.getMaxResults()); for (String paramKey : criteria.getParamsMap().keySet()) { if (criteria.getParamsMap().get(paramKey) instanceof Collection) { query.setParameterList(paramKey, (Collection) criteria.getParamsMap().get(paramKey)); } else if (criteria.getParamsMap().get(paramKey) instanceof Object[]) { query.setParameterList(paramKey, (Object[]) criteria.getParamsMap().get(paramKey)); } else { query.setParameter(paramKey, criteria.getParamsMap().get(paramKey)); } } List result = query.list(); return result; } }); } else { if (Criteria.NAMED_QUERY == criteria.getQueryType()) { results = this.getTemplate().findByNamedQueryAndNamedParam(criteria.getQuery(), criteria.getParamNamesArray(), criteria.getParamValuesArray()); } else { results = this.getTemplate().findByNamedParam(criteria.getQuery(), criteria.getParamNamesArray(), criteria.getParamValuesArray()); } } // log performance metrics captured. actual capture will happen only if it has been enabled via #startPerformanceMetricsLogging(). Default is off this.performanceMetricsLogger.logPerformanceMetrics("HibernateHandler.findEntities", criteria.toConciseString()); return results; } /** * Interface method implementation * @see PersistenceHandler#findEntity(Criteria) */ public PersistentEntity findEntity(Criteria criteria) throws PersistenceException { Collection<PersistentEntity> results = this.findEntities(criteria); if (results.size() != 1) { // we expect to get only ONE result throw new IncorrectResultSizePersistenceException(1, results.size()); } return (PersistentEntity) ((List<PersistentEntity>) results).get(0); } /** * Interface method implementation * @see PersistenceHandler#findEntity(PersistentEntity) */ public PersistentEntity findEntity(PersistentEntity entity) throws PersistenceException { if (entity.getIdentifier() != null) { // first preference is given to the identifier. Use the load criteria otherwise. // signal performance metrics capture. actual capture will happen only if it has been enabled via #startPerformanceMetricsLogging(). Default is off this.performanceMetricsLogger.startPerformanceMetricsCapture(); String message = entity.getEntityName() + ":" + entity.getIdentifier(); this.getTemplate().load(entity, ((RDBMSIdentifier) entity.getIdentifier()).getObjectId()); // log performance metrics captured. actual capture will happen only if it has been enabled via #startPerformanceMetricsLogging(). Default is off this.performanceMetricsLogger.logPerformanceMetrics("HibernateHandler.findObject", message); return entity; } else { return findEntity(entity.getCriteriaForLoad()); } } /** * Interface method implementation * @see PersistenceHandler#makePersistent(PersistentEntity) */ public PersistentEntity makePersistent(PersistentEntity entity) throws PersistenceException { // signal performance metrics capture. actual capture will happen only if it has been enabled via #startPerformanceMetricsLogging(). Default is off this.performanceMetricsLogger.startPerformanceMetricsCapture(); try { if (entity.getEntityName() != null) { template.saveOrUpdate(entity.getEntityName(), entity); } else { template.saveOrUpdate(entity); } } catch (DataIntegrityViolationException die) { throw new org.trpr.platform.core.spi.persistence.DataIntegrityViolationException( "Data integrity violation for entity:id " + entity.getEntityName() + ":" + ((RDBMSIdentifier) entity.getIdentifier()).getObjectId(), die); } catch (DataAccessException de) { throw new PersistenceException("Persistence failure for entity:id " + entity.getEntityName() + ":" + ((RDBMSIdentifier) entity.getIdentifier()).getObjectId(), de); } catch (Exception e) { throw new PersistenceException("Unrecognized/Unhandled Exception while persisting entity:id " + entity.getEntityName() + ":" + ((RDBMSIdentifier) entity.getIdentifier()).getObjectId(), e); } finally { template.clear(); } // log performance metrics captured. actual capture will happen only if it has been enabled via #startPerformanceMetricsLogging(). Default is off this.performanceMetricsLogger.logPerformanceMetrics("HibernateHandler.makePersistent", entity.getEntityName() + ":" + ((RDBMSIdentifier) entity.getIdentifier()).getObjectId()); return entity; } /** * Interface method implementation. * @see PersistenceHandler#makeTransient(PersistentEntity) */ public void makeTransient(PersistentEntity entity) throws PersistenceException { // signal performance metrics capture. actual capture will happen only if it has been enabled via #startPerformanceMetricsLogging(). Default is off this.performanceMetricsLogger.startPerformanceMetricsCapture(); try { if (entity.getEntityName() != null) { template.delete(entity.getEntityName(), entity); } else { template.delete(entity); } } catch (DataAccessException e) { throw new PersistenceException("Delete failure for entity:id " + entity.getEntityName() + ":" + ((RDBMSIdentifier) entity.getIdentifier()).getObjectId(), e); } catch (Exception e) { throw new PersistenceException("Unrecognized/Unhandled Exception while deleting entity:id " + entity.getEntityName() + ":" + ((RDBMSIdentifier) entity.getIdentifier()).getObjectId(), e); } finally { template.clear(); } // log performance metrics captured. actual capture will happen only if it has been enabled via #startPerformanceMetricsLogging(). Default is off this.performanceMetricsLogger.logPerformanceMetrics("HibernateHandler.makeTransient", entity.getEntityName() + ":" + ((RDBMSIdentifier) entity.getIdentifier()).getObjectId()); } /** * Interface method implementation. * @see PersistenceHandler#update(Criteria) */ public int update(Criteria criteria) throws PersistenceException { // signal performance metrics capture. actual capture will happen only if it has been enabled via #startPerformanceMetricsLogging(). Default is off this.performanceMetricsLogger.startPerformanceMetricsCapture(); int result = template.bulkUpdate(criteria.getQuery(), criteria.getParamValuesArray()); // log performance metrics captured. actual capture will happen only if it has been enabled via #startPerformanceMetricsLogging(). Default is off this.performanceMetricsLogger.logPerformanceMetrics("HibernateHandler.update", criteria.toConciseString()); return result; } /** * Enables performance metrics logging for this handler * @param performanceLoggingThreshold the elapsed time threshold for code block execution */ @ManagedOperation public void startPerformanceMetricsLogging(long performanceLoggingThreshold) { this.performanceMetricsLogger.setMetricsCaptureParams(true, performanceLoggingThreshold); } /** * Equals method implementation. Checks if the database URLs of the underlying session factory match * @param persistenceHandler the PersistenceHandler to check for equals * @return true if the specified PersistenceHandler equals this one * @throws PersistenceException in case of SQL exceptions in accessing the handlers' properties */ public boolean equals(PersistenceHandler persistenceHandler) throws PersistenceException { DataSource currentDatasource = SessionFactoryUtils.getDataSource(this.template.getSessionFactory()); DataSource otherDatasource = SessionFactoryUtils .getDataSource(((HibernateHandler) persistenceHandler).getTemplate().getSessionFactory()); try { return (currentDatasource.getConnection().getMetaData().getURL() .equalsIgnoreCase(otherDatasource.getConnection().getMetaData().getURL())); } catch (SQLException e) { throw new PersistenceException("Error evaluating PersistenceHandler#equals() : " + e.getMessage(), e); } } /** * Stops performance metrics logging, if any. */ @ManagedOperation public void stopPerformanceMetricsLogging() { this.performanceMetricsLogger.setMetricsCaptureParams(false, 0); // threshold is set as zero. Value does not matter as logging is getting turned off } /** Start Spring DI style Setter/Getter methods */ public void setTemplate(HibernateTemplate template) { this.template = template; } public HibernateTemplate getTemplate() { return this.template; } public PerformanceMetricsLogger getPerformanceMetricsLogger() { return this.performanceMetricsLogger; } public void setPerformanceMetricsLogger(PerformanceMetricsLogger performanceMetricsLogger) { this.performanceMetricsLogger = performanceMetricsLogger; } /** End Spring DI style Setter/Getter methods */ /** * Helper method to execute a native SQL query and return the results as a List of PersistentEntity instances. * Note that this implementation doesnot support scalar values to be returned and instead expects all resultant data to be * mapped to a PersistentEntity defined for the purpose. This approach helps to maintain consistency in the {@link #findEntities(Criteria)} * interface implementation and also provide for standard Hibernate-to-Java entity type mapping semantics. */ @SuppressWarnings("unchecked") private List<PersistentEntity> findObjectBySQLQuery(final Criteria criteria) { return (List<PersistentEntity>) this.getTemplate().execute(new HibernateCallback() { public Object doInHibernate(Session session) throws HibernateException, SQLException { SQLQuery sqlQueryObject = session.createSQLQuery(criteria.getQuery()); sqlQueryObject.addEntity(criteria.getManagedClass()); sqlQueryObject.setFirstResult(criteria.getFirstResult()); if (criteria.getMaxResults() > 0) { sqlQueryObject.setMaxResults(criteria.getMaxResults()); } return sqlQueryObject.list(); } }); } }