/*
* Copyright 2007 the original author or jdon.com
*
* 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 com.jdon.persistence.hibernate;
import java.io.Serializable;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.hibernate.Criteria;
import org.hibernate.HibernateException;
import org.hibernate.LockMode;
import org.hibernate.Query;
import org.hibernate.ReplicationMode;
import org.hibernate.Session;
import org.hibernate.criterion.DetachedCriteria;
import org.hibernate.criterion.Example;
import com.jdon.persistence.hibernate.util.HibernateCallback;
import com.jdon.persistence.hibernate.util.SessionFactoryHolder;
public class HibernateTemplate {
private final static Logger logger = LogManager.getLogger(HibernateTemplate.class);
private boolean cacheQueries = false;
private String queryCacheRegion;
private int fetchSize = 0;
private int firstResult = 0;
private int maxResults = 0;
private SessionProvider sessionProvider;
/**
* Create a new HibernateTemplate instance.
*
* @param sessionFactory
* SessionFactory to create Sessions
*/
public HibernateTemplate(SessionProvider sessionProvider) {
this.sessionProvider = sessionProvider;
}
/**
* Execute the action specified by the given action object within a Session.
*
* @param action
* callback object that specifies the Hibernate action
* @param exposeNativeSession
* whether to expose the native Hibernate Session to callback
* code
* @return a result object returned by the action, or <code>null</code>
* @throws org.springframework.dao.Exception
* in case of Hibernate errors
*/
public Object doHibernate(HibernateCallback action) throws Exception {
Session session = sessionProvider.getSession();
try {
Object result = action.execute(session);
return result;
} catch (Exception ex) {
logger.error("exception while execute", ex);
try {
sessionProvider.rollback();
} catch (HibernateException ee) {
logger.error("error while session rollback", ee);
} finally {
sessionProvider.resetSession();
}
throw new Exception(ex);
} finally {
// sessionProvider.returnCloseSession(session);
}
}
// -------------------------------------------------------------------------
// Convenience methods for loading individual objects
// -------------------------------------------------------------------------
public Object get(Class entityClass, Serializable id) throws Exception {
return get(entityClass, id, null);
}
public Object get(final Class entityClass, final Serializable id, final LockMode lockMode) throws Exception {
return doHibernate(new HibernateCallback() {
public Object execute(Session session) throws HibernateException {
if (lockMode != null) {
return session.get(entityClass, id, lockMode);
} else {
return session.get(entityClass, id);
}
}
});
}
public Object get(String entityName, Serializable id) throws Exception {
return get(entityName, id, null);
}
public Object get(final String entityName, final Serializable id, final LockMode lockMode) throws Exception {
return doHibernate(new HibernateCallback() {
public Object execute(Session session) throws HibernateException {
if (lockMode != null) {
return session.get(entityName, id, lockMode);
} else {
return session.get(entityName, id);
}
}
});
}
public Object load(Class entityClass, Serializable id) throws Exception {
return load(entityClass, id, null);
}
public Object load(final Class entityClass, final Serializable id, final LockMode lockMode) throws Exception {
return doHibernate(new HibernateCallback() {
public Object execute(Session session) throws HibernateException {
if (lockMode != null) {
return session.load(entityClass, id, lockMode);
} else {
return session.load(entityClass, id);
}
}
});
}
public Object load(String entityName, Serializable id) throws Exception {
return load(entityName, id, null);
}
public Object load(final String entityName, final Serializable id, final LockMode lockMode) throws Exception {
return doHibernate(new HibernateCallback() {
public Object execute(Session session) throws HibernateException {
if (lockMode != null) {
return session.load(entityName, id, lockMode);
} else {
return session.load(entityName, id);
}
}
});
}
public List loadAll(final Class entityClass) throws Exception {
return (List) doHibernate(new HibernateCallback() {
public Object execute(Session session) throws HibernateException {
Criteria criteria = session.createCriteria(entityClass);
prepareCriteria(criteria);
return criteria.list();
}
});
}
public void load(final Object entity, final Serializable id) throws Exception {
doHibernate(new HibernateCallback() {
public Object execute(Session session) throws HibernateException {
session.load(entity, id);
return null;
}
});
}
public void refresh(final Object entity) throws Exception {
refresh(entity, null);
}
public void refresh(final Object entity, final LockMode lockMode) throws Exception {
doHibernate(new HibernateCallback() {
public Object execute(Session session) throws HibernateException {
if (lockMode != null) {
session.refresh(entity, lockMode);
} else {
session.refresh(entity);
}
return null;
}
});
}
public boolean contains(final Object entity) throws Exception {
Boolean result = (Boolean) doHibernate(new HibernateCallback() {
public Object execute(Session session) {
return (session.contains(entity) ? Boolean.TRUE : Boolean.FALSE);
}
});
return result.booleanValue();
}
public void evict(final Object entity) throws Exception {
doHibernate(new HibernateCallback() {
public Object execute(Session session) throws HibernateException {
session.evict(entity);
return null;
}
});
}
// -------------------------------------------------------------------------
// Convenience methods for storing individual objects
// -------------------------------------------------------------------------
public void lock(final Object entity, final LockMode lockMode) throws Exception {
doHibernate(new HibernateCallback() {
public Object execute(Session session) throws HibernateException {
session.lock(entity, lockMode);
return null;
}
});
}
public void lock(final String entityName, final Object entity, final LockMode lockMode) throws Exception {
doHibernate(new HibernateCallback() {
public Object execute(Session session) throws HibernateException {
session.lock(entityName, entity, lockMode);
return null;
}
});
}
public Serializable save(final Object entity) throws Exception {
return (Serializable) doHibernate(new HibernateCallback() {
public Object execute(Session session) throws HibernateException {
return session.save(entity);
}
});
}
public Serializable save(final String entityName, final Object entity) throws Exception {
return (Serializable) doHibernate(new HibernateCallback() {
public Object execute(Session session) throws HibernateException {
return session.save(entityName, entity);
}
});
}
public void update(Object entity) throws Exception {
update(entity, null);
}
public void update(final Object entity, final LockMode lockMode) throws Exception {
doHibernate(new HibernateCallback() {
public Object execute(Session session) throws HibernateException {
session.update(entity);
if (lockMode != null) {
session.lock(entity, lockMode);
}
return null;
}
});
}
public void update(String entityName, Object entity) throws Exception {
update(entityName, entity, null);
}
public void update(final String entityName, final Object entity, final LockMode lockMode) throws Exception {
doHibernate(new HibernateCallback() {
public Object execute(Session session) throws HibernateException {
session.update(entityName, entity);
if (lockMode != null) {
session.lock(entity, lockMode);
}
return null;
}
});
}
public void saveOrUpdate(final Object entity) throws Exception {
doHibernate(new HibernateCallback() {
public Object execute(Session session) throws HibernateException {
session.saveOrUpdate(entity);
return null;
}
});
}
public void saveOrUpdate(final String entityName, final Object entity) throws Exception {
doHibernate(new HibernateCallback() {
public Object execute(Session session) throws HibernateException {
session.saveOrUpdate(entityName, entity);
return null;
}
});
}
public void saveOrUpdateAll(final Collection entities) throws Exception {
doHibernate(new HibernateCallback() {
public Object execute(Session session) throws HibernateException {
for (Iterator it = entities.iterator(); it.hasNext();) {
session.saveOrUpdate(it.next());
}
return null;
}
});
}
public void replicate(final Object entity, final ReplicationMode replicationMode) throws Exception {
doHibernate(new HibernateCallback() {
public Object execute(Session session) throws HibernateException {
session.replicate(entity, replicationMode);
return null;
}
});
}
public void replicate(final String entityName, final Object entity, final ReplicationMode replicationMode) throws Exception {
doHibernate(new HibernateCallback() {
public Object execute(Session session) throws HibernateException {
session.replicate(entityName, entity, replicationMode);
return null;
}
});
}
public void persist(final Object entity) throws Exception {
doHibernate(new HibernateCallback() {
public Object execute(Session session) throws HibernateException {
session.persist(entity);
return null;
}
});
}
public void persist(final String entityName, final Object entity) throws Exception {
doHibernate(new HibernateCallback() {
public Object execute(Session session) throws HibernateException {
session.persist(entityName, entity);
return null;
}
});
}
public Object merge(final Object entity) throws Exception {
return doHibernate(new HibernateCallback() {
public Object execute(Session session) throws HibernateException {
return session.merge(entity);
}
});
}
public Object merge(final String entityName, final Object entity) throws Exception {
return doHibernate(new HibernateCallback() {
public Object execute(Session session) throws HibernateException {
return session.merge(entityName, entity);
}
});
}
public void delete(Object entity) throws Exception {
delete(entity, null);
}
public void delete(final Object entity, final LockMode lockMode) throws Exception {
doHibernate(new HibernateCallback() {
public Object execute(Session session) throws HibernateException {
if (lockMode != null) {
session.lock(entity, lockMode);
}
session.delete(entity);
return null;
}
});
}
public void deleteAll(final Collection entities) throws Exception {
doHibernate(new HibernateCallback() {
public Object execute(Session session) throws HibernateException {
for (Iterator it = entities.iterator(); it.hasNext();) {
session.delete(it.next());
}
return null;
}
});
}
public void flush() throws Exception {
doHibernate(new HibernateCallback() {
public Object execute(Session session) throws HibernateException {
session.flush();
return null;
}
});
}
public void clearSession() throws Exception {
doHibernate(new HibernateCallback() {
public Object execute(Session session) {
session.clear();
return null;
}
});
}
// -------------------------------------------------------------------------
// Convenience finder methods for HQL strings
// -------------------------------------------------------------------------
public List find(String queryString) throws Exception {
return find(queryString, (Object[]) null);
}
public List find(String queryString, Object value) throws Exception {
return find(queryString, new Object[] { value });
}
public List find(final String queryString, final Object[] values) throws Exception {
return (List) doHibernate(new HibernateCallback() {
public Object execute(Session session) throws HibernateException {
Query queryObject = session.createQuery(queryString);
prepareQuery(queryObject);
if (values != null) {
for (int i = 0; i < values.length; i++) {
queryObject.setParameter(i, values[i]);
}
}
return queryObject.list();
}
});
}
public List findByNamedParam(String queryString, String paramName, Object value) throws Exception {
return findByNamedParam(queryString, new String[] { paramName }, new Object[] { value });
}
public List findByNamedParam(final String queryString, final String[] paramNames, final Object[] values) throws Exception {
if (paramNames.length != values.length) {
throw new IllegalArgumentException("Length of paramNames array must match length of values array");
}
return (List) doHibernate(new HibernateCallback() {
public Object execute(Session session) throws HibernateException {
Query queryObject = session.createQuery(queryString);
prepareQuery(queryObject);
if (values != null) {
for (int i = 0; i < values.length; i++) {
applyNamedParameterToQuery(queryObject, paramNames[i], values[i]);
}
}
return queryObject.list();
}
});
}
public List findByValueBean(final String queryString, final Object valueBean) throws Exception {
return (List) doHibernate(new HibernateCallback() {
public Object execute(Session session) throws HibernateException {
Query queryObject = session.createQuery(queryString);
prepareQuery(queryObject);
queryObject.setProperties(valueBean);
return queryObject.list();
}
});
}
// -------------------------------------------------------------------------
// Convenience finder methods for named queries
// -------------------------------------------------------------------------
public List findByNamedQuery(String queryName) throws Exception {
return findByNamedQuery(queryName, (Object[]) null);
}
public List findByNamedQuery(String queryName, Object value) throws Exception {
return findByNamedQuery(queryName, new Object[] { value });
}
public List findByNamedQuery(final String queryName, final Object[] values) throws Exception {
return (List) doHibernate(new HibernateCallback() {
public Object execute(Session session) throws HibernateException {
Query queryObject = session.getNamedQuery(queryName);
prepareQuery(queryObject);
if (values != null) {
for (int i = 0; i < values.length; i++) {
queryObject.setParameter(i, values[i]);
}
}
return queryObject.list();
}
});
}
public List findByNamedQueryAndNamedParam(String queryName, String paramName, Object value) throws Exception {
return findByNamedQueryAndNamedParam(queryName, new String[] { paramName }, new Object[] { value });
}
public List findByNamedQueryAndNamedParam(final String queryName, final String[] paramNames, final Object[] values) throws Exception {
if (paramNames != null && values != null && paramNames.length != values.length) {
throw new IllegalArgumentException("Length of paramNames array must match length of values array");
}
return (List) doHibernate(new HibernateCallback() {
public Object execute(Session session) throws HibernateException {
Query queryObject = session.getNamedQuery(queryName);
prepareQuery(queryObject);
if (values != null) {
for (int i = 0; i < values.length; i++) {
applyNamedParameterToQuery(queryObject, paramNames[i], values[i]);
}
}
return queryObject.list();
}
});
}
public List findByNamedQueryAndValueBean(final String queryName, final Object valueBean) throws Exception {
return (List) doHibernate(new HibernateCallback() {
public Object execute(Session session) throws HibernateException {
Query queryObject = session.getNamedQuery(queryName);
prepareQuery(queryObject);
queryObject.setProperties(valueBean);
return queryObject.list();
}
});
}
// -------------------------------------------------------------------------
// Convenience finder methods for detached criteria
// -------------------------------------------------------------------------
public List findByCriteria(DetachedCriteria criteria) throws Exception {
return findByCriteria(criteria, -1, -1);
}
public List findByCriteria(final DetachedCriteria criteria, final int firstResult, final int maxResults) throws Exception {
return (List) doHibernate(new HibernateCallback() {
public Object execute(Session session) throws HibernateException {
Criteria executableCriteria = criteria.getExecutableCriteria(session);
prepareCriteria(executableCriteria);
if (firstResult >= 0) {
executableCriteria.setFirstResult(firstResult);
}
if (maxResults > 0) {
executableCriteria.setMaxResults(maxResults);
}
return executableCriteria.list();
}
});
}
public List findByExample(Object exampleEntity) throws Exception {
return findByExample(exampleEntity, -1, -1);
}
public List findByExample(final Object exampleEntity, final int firstResult, final int maxResults) throws Exception {
return (List) doHibernate(new HibernateCallback() {
public Object execute(Session session) throws HibernateException {
Criteria executableCriteria = session.createCriteria(exampleEntity.getClass());
executableCriteria.add(Example.create(exampleEntity));
prepareCriteria(executableCriteria);
if (firstResult >= 0) {
executableCriteria.setFirstResult(firstResult);
}
if (maxResults > 0) {
executableCriteria.setMaxResults(maxResults);
}
return executableCriteria.list();
}
});
}
// -------------------------------------------------------------------------
// Convenience query methods for iteration and bulk updates/deletes
// -------------------------------------------------------------------------
public Iterator iterate(String queryString) throws Exception {
return iterate(queryString, (Object[]) null);
}
public Iterator iterate(String queryString, Object value) throws Exception {
return iterate(queryString, new Object[] { value });
}
public Iterator iterate(final String queryString, final Object[] values) throws Exception {
return (Iterator) doHibernate(new HibernateCallback() {
public Object execute(Session session) throws HibernateException {
Query queryObject = session.createQuery(queryString);
prepareQuery(queryObject);
if (values != null) {
for (int i = 0; i < values.length; i++) {
queryObject.setParameter(i, values[i]);
}
}
return queryObject.iterate();
}
});
}
public int bulkUpdate(String queryString) throws Exception {
return bulkUpdate(queryString, (Object[]) null);
}
public int bulkUpdate(String queryString, Object value) throws Exception {
return bulkUpdate(queryString, new Object[] { value });
}
public int bulkUpdate(final String queryString, final Object[] values) throws Exception {
Integer updateCount = (Integer) doHibernate(new HibernateCallback() {
public Object execute(Session session) throws HibernateException {
Query queryObject = session.createQuery(queryString);
prepareQuery(queryObject);
if (values != null) {
for (int i = 0; i < values.length; i++) {
queryObject.setParameter(i, values[i]);
}
}
return new Integer(queryObject.executeUpdate());
}
});
return updateCount.intValue();
}
// -------------------------------------------------------------------------
// Helper methods used by the operations above
// -------------------------------------------------------------------------
/**
* Prepare the given Query object, applying cache settings and/or a
* transaction timeout.
*
* @param queryObject
* the Query object to prepare
* @see #setCacheQueries
* @see #setQueryCacheRegion
* @see SessionProviderHolder#applyTransactionTimeout
*/
protected void prepareQuery(Query queryObject) {
if (isCacheQueries()) {
queryObject.setCacheable(true);
if (getQueryCacheRegion() != null) {
queryObject.setCacheRegion(getQueryCacheRegion());
}
}
if (getFetchSize() > 0) {
queryObject.setFetchSize(getFetchSize());
}
if (getMaxResults() > 0) {
queryObject.setMaxResults(getMaxResults());
}
if (getFirstResult() > 0) {
queryObject.setFirstResult(getFirstResult());
}
}
/**
* Prepare the given Criteria object, applying cache settings and/or a
* transaction timeout.
*
* @param criteria
* the Criteria object to prepare
* @see #setCacheQueries
* @see #setQueryCacheRegion
* @see SessionProviderHolder#applyTransactionTimeout
*/
protected void prepareCriteria(Criteria criteria) {
if (isCacheQueries()) {
criteria.setCacheable(true);
if (getQueryCacheRegion() != null) {
criteria.setCacheRegion(getQueryCacheRegion());
}
}
if (getFetchSize() > 0) {
criteria.setFetchSize(getFetchSize());
}
if (getMaxResults() > 0) {
criteria.setMaxResults(getMaxResults());
}
}
/**
* Apply the given name parameter to the given Query object.
*
* @param queryObject
* the Query object
* @param paramName
* the name of the parameter
* @param value
* the value of the parameter
* @throws HibernateException
* if thrown by the Query object
*/
protected void applyNamedParameterToQuery(Query queryObject, String paramName, Object value) throws HibernateException {
if (value instanceof Collection) {
queryObject.setParameterList(paramName, (Collection) value);
} else if (value instanceof Object[]) {
queryObject.setParameterList(paramName, (Object[]) value);
} else {
queryObject.setParameter(paramName, value);
}
}
/**
* Set whether to cache all queries executed by this template. If this is
* true, all Query and Criteria objects created by this template will be
* marked as cacheable (including all queries through find methods).
* <p>
* To specify the query region to be used for queries cached by this
* template, set the "queryCacheRegion" property.
*
* @see #setQueryCacheRegion
* @see org.hibernate.Query#setCacheable
* @see org.hibernate.Criteria#setCacheable
*/
public void setCacheQueries(boolean cacheQueries) {
this.cacheQueries = cacheQueries;
}
/**
* Return whether to cache all queries executed by this template.
*/
public boolean isCacheQueries() {
return cacheQueries;
}
/**
* Set the name of the cache region for queries executed by this template.
* If this is specified, it will be applied to all Query and Criteria
* objects created by this template (including all queries through find
* methods).
* <p>
* The cache region will not take effect unless queries created by this
* template are configured to be cached via the "cacheQueries" property.
*
* @see #setCacheQueries
* @see org.hibernate.Query#setCacheRegion
* @see org.hibernate.Criteria#setCacheRegion
*/
public void setQueryCacheRegion(String queryCacheRegion) {
this.queryCacheRegion = queryCacheRegion;
}
/**
* Return the name of the cache region for queries executed by this
* template.
*/
public String getQueryCacheRegion() {
return queryCacheRegion;
}
/**
* Set the fetch size for this HibernateTemplate. This is important for
* processing large result sets: Setting this higher than the default value
* will increase processing speed at the cost of memory consumption; setting
* this lower can avoid transferring row data that will never be read by the
* application.
* <p>
* Default is 0, indicating to use the JDBC driver's default.
*/
public void setFetchSize(int fetchSize) {
this.fetchSize = fetchSize;
}
/**
* Return the fetch size specified for this HibernateTemplate.
*/
public int getFetchSize() {
return fetchSize;
}
/**
* Set the maximum number of rows for this HibernateTemplate. This is
* important for processing subsets of large result sets, avoiding to read
* and hold the entire result set in the database or in the JDBC driver if
* we're never interested in the entire result in the first place (for
* example, when performing searches that might return a large number of
* matches).
* <p>
* Default is 0, indicating to use the JDBC driver's default.
*/
public void setMaxResults(int maxResults) {
this.maxResults = maxResults;
}
/**
* Return the maximum number of rows specified for this HibernateTemplate.
*/
public int getMaxResults() {
return maxResults;
}
public int getFirstResult() {
return firstResult;
}
public void setFirstResult(int firstResult) {
this.firstResult = firstResult;
}
public SessionProvider getSessionProvider() {
return sessionProvider;
}
public void closeSession() {
if (SessionFactoryHolder.isSessionIsActive()) {
sessionProvider.closeSession();
}
}
public void clearParams() {
this.cacheQueries = false;
this.fetchSize = 0;
this.firstResult = 0;
this.maxResults = 0;
this.queryCacheRegion = null;
}
}