org.bonitasoft.engine.persistence.AbstractHibernatePersistenceService Maven / Gradle / Ivy
/**
* Copyright (C) 2015 BonitaSoft S.A.
* BonitaSoft, 32 rue Gustave Eiffel - 38000 Grenoble
* This library is free software; you can redistribute it and/or modify it under the terms
* of the GNU Lesser General Public License as published by the Free Software Foundation
* version 2.1 of the License.
* This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
* You should have received a copy of the GNU Lesser General Public License along with this
* program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
* Floor, Boston, MA 02110-1301, USA.
**/
package org.bonitasoft.engine.persistence;
import static org.bonitasoft.engine.persistence.search.FilterOperationType.*;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Properties;
import java.util.Set;
import javax.sql.DataSource;
import org.bonitasoft.engine.commons.ClassReflector;
import org.bonitasoft.engine.commons.EnumToObjectConvertible;
import org.bonitasoft.engine.log.technical.TechnicalLogSeverity;
import org.bonitasoft.engine.log.technical.TechnicalLoggerService;
import org.bonitasoft.engine.persistence.search.FilterOperationType;
import org.bonitasoft.engine.sequence.SequenceManager;
import org.bonitasoft.engine.services.SPersistenceException;
import org.bonitasoft.engine.services.UpdateDescriptor;
import org.hibernate.AssertionFailure;
import org.hibernate.HibernateException;
import org.hibernate.Interceptor;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.StaleStateException;
import org.hibernate.cfg.Configuration;
import org.hibernate.exception.LockAcquisitionException;
import org.hibernate.mapping.PersistentClass;
import org.hibernate.stat.Statistics;
/**
* Hibernate implementation of the persistence service
*
* @author Charles Souillard
* @author Nicolas Chabanoles
* @author Yanyan Liu
* @author Matthieu Chaffotte
* @author Celine Souchet
* @author Laurent Vaills
*/
public abstract class AbstractHibernatePersistenceService extends AbstractDBPersistenceService {
private final SessionFactory sessionFactory;
private final OrderByCheckingMode orderByCheckingMode;
private final Map classAliasMappings;
protected final Map cacheQueries;
protected final List> classMapping;
protected final Map> interfaceToClassMapping;
protected final List mappingExclusions;
Statistics statistics;
int stat_display_count;
// ----
/**
* @param sessionFactory
* @param classMapping
* @param classAliasMappings
* @param enableWordSearch
* @param wordSearchExclusionMappings
* @param logger
* @throws ClassNotFoundException
*/
protected AbstractHibernatePersistenceService(final SessionFactory sessionFactory, final List> classMapping,
final Map classAliasMappings, final boolean enableWordSearch,
final Set wordSearchExclusionMappings, final TechnicalLoggerService logger) throws ClassNotFoundException {
super("TEST", "#", enableWordSearch, wordSearchExclusionMappings, logger);
this.sessionFactory = sessionFactory;
this.classAliasMappings = classAliasMappings;
this.classMapping = classMapping;
orderByCheckingMode = getOrderByCheckingMode();
statistics = sessionFactory.getStatistics();
cacheQueries = Collections.emptyMap();
interfaceToClassMapping = Collections.emptyMap();
mappingExclusions = Collections.emptyList();
}
// Setter for session
// ----
/**
* @param name
* @param hbmConfigurationProvider
* @param likeEscapeCharacter
* @param logger
* @param sequenceManager
* @param datasource
* @param enableWordSearch
* @param wordSearchExclusionMappings
* @throws SPersistenceException
* @throws ClassNotFoundException
*/
public AbstractHibernatePersistenceService(final String name, final HibernateConfigurationProvider hbmConfigurationProvider,
final Properties extraHibernateProperties,
final String likeEscapeCharacter, final TechnicalLoggerService logger, final SequenceManager sequenceManager, final DataSource datasource,
final boolean enableWordSearch, final Set wordSearchExclusionMappings) throws SPersistenceException, ClassNotFoundException {
super(name, likeEscapeCharacter, sequenceManager, datasource, enableWordSearch,
wordSearchExclusionMappings, logger);
orderByCheckingMode = getOrderByCheckingMode();
Configuration configuration;
try {
configuration = hbmConfigurationProvider.getConfiguration();
if (extraHibernateProperties != null) {
configuration.addProperties(extraHibernateProperties);
}
} catch (final ConfigurationException e) {
throw new SPersistenceException(e);
}
final String dialect = configuration.getProperty("hibernate.dialect");
if (dialect != null) {
if (dialect.contains("PostgreSQL")) {
configuration.setInterceptor(new PostgresInterceptor());
} else if (dialect.contains("SQLServer")) {
configuration.setInterceptor(new SQLServerInterceptor());
}
}
final String className = configuration.getProperty("hibernate.interceptor");
if (className != null && !className.isEmpty()) {
try {
final Interceptor interceptor = (Interceptor) Class.forName(className).newInstance();
configuration.setInterceptor(interceptor);
} catch (final ClassNotFoundException cnfe) {
throw new SPersistenceException(cnfe);
} catch (final InstantiationException e) {
throw new SPersistenceException(e);
} catch (final IllegalAccessException e) {
throw new SPersistenceException(e);
}
}
sessionFactory = configuration.buildSessionFactory();
statistics = sessionFactory.getStatistics();
final Iterator classMappingsIterator = configuration.getClassMappings();
classMapping = new ArrayList>();
while (classMappingsIterator.hasNext()) {
classMapping.add(classMappingsIterator.next().getMappedClass());
}
classAliasMappings = hbmConfigurationProvider.getClassAliasMappings();
interfaceToClassMapping = hbmConfigurationProvider.getInterfaceToClassMapping();
mappingExclusions = hbmConfigurationProvider.getMappingExclusions();
cacheQueries = hbmConfigurationProvider.getCacheQueries();
}
private OrderByCheckingMode getOrderByCheckingMode() {
final String property = System.getProperty("sysprop.bonita.orderby.checking.mode");
return property != null && !property.isEmpty() ? OrderByCheckingMode.valueOf(property) : OrderByCheckingMode.NONE;
}
/**
* Log synthetic information about cache every 10.000 sessions, if hibernate.gather_statistics, is enabled.
*/
protected void logStats() {
if (!statistics.isStatisticsEnabled()) {
return;
}
if (stat_display_count == 10 || stat_display_count == 100 || stat_display_count == 1000 || stat_display_count % 10000 == 0) {
final long query_cache_hit = statistics.getQueryCacheHitCount();
final long query_cache_miss = statistics.getQueryCacheMissCount();
final long query_cahe_put = statistics.getQueryCachePutCount();
final long level_2_cache_hit = statistics.getSecondLevelCacheHitCount();
final long level_2_cache_miss = statistics.getSecondLevelCacheMissCount();
final long level_2_put = statistics.getSecondLevelCachePutCount();
logger.log(this.getClass(), TechnicalLogSeverity.INFO, "Query Cache Ratio "
+ (int) ((double) query_cache_hit / (query_cache_hit + query_cache_miss) * 100) + "% " + query_cache_hit + " hits " + query_cache_miss
+ " miss " + query_cahe_put + " puts");
logger.log(this.getClass(), TechnicalLogSeverity.INFO, "2nd Level Cache Ratio "
+ (int) ((double) level_2_cache_hit / (level_2_cache_hit + level_2_cache_miss) * 100) + "% " + level_2_cache_hit + " hits "
+ level_2_cache_miss + " miss " + level_2_put + " puts");
}
stat_display_count++;
}
protected Session getSession(final boolean useTenant) throws SPersistenceException {
logStats();
try {
return sessionFactory.getCurrentSession();
} catch (final HibernateException e) {
throw new SPersistenceException(e);
}
}
protected void flushStatements(final boolean useTenant) throws SPersistenceException {
final Session session = getSession(useTenant);
session.flush();
}
protected void logWarningMessage(final SelectListDescriptor selectDescriptor, final Query query) {
final StringBuilder message = new StringBuilder();
message.append("selectList call without \"order by\" clause ");
message.append("\n");
message.append(query.toString());
message.append("\n");
message.append(String.format("query name:%s\nentity:%s\nstart index:%d\npage size:%d", selectDescriptor.getQueryName(), selectDescriptor
.getEntityType().getCanonicalName(), selectDescriptor.getStartIndex(), selectDescriptor.getPageSize()));
logger.log(this.getClass(), TechnicalLogSeverity.WARNING, message.toString());
// throw new IllegalArgumentException("Query " + selectDescriptor.getQueryName());
}
@Override
public void delete(final PersistentObject entity) throws SPersistenceException {
if (logger.isLoggable(getClass(), TechnicalLogSeverity.DEBUG)) {
logger.log(this.getClass(), TechnicalLogSeverity.DEBUG,
"Deleting instance of class " + entity.getClass().getSimpleName() + " with id=" + entity.getId());
}
final Class extends PersistentObject> mappedClass = getMappedClass(entity.getClass());
final Session session = getSession(true);
try {
if (session.contains(entity)) {
session.delete(entity);
} else {
// Deletion must be performed on the session entity and not on a potential transitional entity.
final Object pe = session.get(mappedClass, new PersistentObjectId(entity.getId(), 0));
session.delete(pe);
}
} catch (final AssertionFailure | LockAcquisitionException | StaleStateException e) {
throw new SRetryableException(e);
} catch (final HibernateException he) {
throw new SPersistenceException(he);
}
}
@Override
public int update(final String updateQueryName) throws SPersistenceException {
return update(updateQueryName, null);
}
@Override
public int update(final String updateQueryName, final Map inputParameters) throws SPersistenceException {
final Query query = getSession(true).getNamedQuery(updateQueryName);
try {
if (inputParameters != null) {
setParameters(query, inputParameters);
}
return query.executeUpdate();
} catch (final HibernateException he) {
throw new SPersistenceException(he);
}
}
@Override
public void deleteAll(final Class extends PersistentObject> entityClass) throws SPersistenceException {
final Class extends PersistentObject> mappedClass = getMappedClass(entityClass);
final Query query = getSession(true).getNamedQuery("deleteAll" + mappedClass.getSimpleName());
try {
query.executeUpdate();
} catch (final AssertionFailure | LockAcquisitionException | StaleStateException e) {
throw new SRetryableException(e);
} catch (final HibernateException he) {
throw new SPersistenceException(he);
}
}
@Override
public void insert(final PersistentObject entity) throws SPersistenceException {
final Class extends PersistentObject> entityClass = entity.getClass();
checkClassMapping(entityClass);
final Session session = getSession(true);
setId(entity);
try {
session.save(entity);
} catch (final AssertionFailure | LockAcquisitionException | StaleStateException e) {
throw new SRetryableException(e);
} catch (final HibernateException he) {
throw new SPersistenceException(he);
}
}
@Override
public void insertInBatch(final List entities) throws SPersistenceException {
if (!entities.isEmpty()) {
final Session session = getSession(true);
for (final PersistentObject entity : entities) {
final Class extends PersistentObject> entityClass = entity.getClass();
checkClassMapping(entityClass);
setId(entity);
session.save(entity);
}
}
}
@Override
public void update(final UpdateDescriptor updateDescriptor) throws SPersistenceException {
// FIXME: deal with disconnected objects:
final Class extends PersistentObject> entityClass = updateDescriptor.getEntity().getClass();
checkClassMapping(entityClass);
final PersistentObject entity = updateDescriptor.getEntity();
final Session session = getSession(false);
if (!session.contains(entity)) {
throw new SPersistenceException("The object cannot be updated because it's deconnected " + entity);
}
for (final Map.Entry field : updateDescriptor.getFields().entrySet()) {
setField(entity, field.getKey(), field.getValue());
}
}
void setField(final PersistentObject entity, final String fieldName, final Object parameterValue) throws SPersistenceException {
Long id = null;
try {
id = entity.getId();
ClassReflector.setField(entity, fieldName, parameterValue);
} catch (final Exception e) {
throw new SPersistenceException("Problem while updating entity: " + entity + " with id: " + id, e);
}
}
@Override
public T selectOne(final SelectOneDescriptor selectDescriptor) throws SBonitaReadException {
try {
final Session session = getSession(true);
return this.selectOne(session, selectDescriptor, selectDescriptor.getInputParameters());
} catch (final SPersistenceException e) {
throw new SBonitaReadException(e, selectDescriptor);
}
}
protected Class extends PersistentObject> getMappedClass(final Class extends PersistentObject> entityClass) throws SPersistenceException {
if (classMapping.contains(entityClass)) {
return entityClass;
}
if (interfaceToClassMapping.containsKey(entityClass.getName())) {
return interfaceToClassMapping.get(entityClass.getName());
}
throw new SPersistenceException("Unable to locate class " + entityClass + " in Hibernate configuration");
}
protected void checkClassMapping(final Class extends PersistentObject> entityClass) throws SPersistenceException {
if (!classMapping.contains(entityClass) && !interfaceToClassMapping.containsKey(entityClass.getName())
&& !mappingExclusions.contains(entityClass.getName())) {
throw new SPersistenceException("Unable to locate class " + entityClass + " in Hibernate configuration");
}
}
@Override
public T selectById(final SelectByIdDescriptor selectDescriptor) throws SBonitaReadException {
try {
return this.selectById(getSession(true), selectDescriptor);
} catch (final SPersistenceException e) {
throw new SBonitaReadException(e, selectDescriptor);
}
}
@Override
protected void setId(PersistentObject entity) throws SPersistenceException {
super.setId(entity);
}
@SuppressWarnings("unchecked")
T selectById(final Session session, final SelectByIdDescriptor selectDescriptor) throws SBonitaReadException {
Class extends PersistentObject> mappedClass = null;
try {
mappedClass = getMappedClass(selectDescriptor.getEntityType());
} catch (final SPersistenceException e) {
throw new SBonitaReadException(e);
}
try {
return (T) session.get(mappedClass, selectDescriptor.getId());
} catch (final AssertionFailure | LockAcquisitionException | StaleStateException e) {
throw new SRetryableException(e);
} catch (final HibernateException he) {
throw new SBonitaReadException(he);
}
}
@SuppressWarnings("unchecked")
private T selectOne(final Session session, final AbstractSelectDescriptor selectDescriptor, final Map parameters)
throws SBonitaReadException {
try {
checkClassMapping(selectDescriptor.getEntityType());
} catch (final SPersistenceException e) {
throw new SBonitaReadException(e);
}
final Query query = session.getNamedQuery(selectDescriptor.getQueryName());
setQueryCache(query, selectDescriptor.getQueryName());
if (parameters != null) {
setParameters(query, parameters);
}
query.setMaxResults(1);
try {
return (T) query.uniqueResult();
} catch (final AssertionFailure | LockAcquisitionException | StaleStateException e) {
throw new SRetryableException(e);
} catch (final HibernateException he) {
throw new SBonitaReadException(he);
}
}
protected String getQueryWithFilters(final String query, final List filters, final SearchFields multipleFilter,
final boolean enableWordSearch) {
final StringBuilder builder = new StringBuilder(query);
final Set specificFilters = new HashSet(filters.size());
if (!filters.isEmpty()) {
FilterOption previousFilter = null;
if (!query.contains("WHERE")) {
builder.append(" WHERE (");
} else {
builder.append(" AND (");
}
for (final FilterOption filterOption : filters) {
if (previousFilter != null) {
final FilterOperationType prevOp = previousFilter.getFilterOperationType();
final FilterOperationType currOp = filterOption.getFilterOperationType();
// Auto add AND if previous operator was normal op or ')' and that current op is normal op or '(' :
if ((isNormalOperator(prevOp) || prevOp == R_PARENTHESIS) && (isNormalOperator(currOp) || currOp == L_PARENTHESIS)) {
builder.append(" AND ");
}
}
final StringBuilder aliasBuilder = appendFilterClause(builder, filterOption);
// FIXME: is it really filterOption.getFieldName() or is it its formatted value: classAliasMappings.get(.......) ?:
// specificFilters.add(filterOption.getFieldName());
if (aliasBuilder != null) {
specificFilters.add(aliasBuilder.toString());
}
previousFilter = filterOption;
}
builder.append(")");
}
if (multipleFilter != null && multipleFilter.getTerms() != null && !multipleFilter.getTerms().isEmpty()) {
handleMultipleFilters(builder, multipleFilter, specificFilters, enableWordSearch);
}
return builder.toString();
}
/**
* @param builder
* @param multipleFilter
* @param specificFilters
* @param enableWordSearch
*/
protected void handleMultipleFilters(final StringBuilder builder, final SearchFields multipleFilter, final Set specificFilters,
final boolean enableWordSearch) {
final Map, Set> allTextFields = multipleFilter.getFields();
final Set fields = new HashSet();
for (final Entry, Set> entry : allTextFields.entrySet()) {
final String alias = getClassAliasMappings().get(entry.getKey().getName());
for (final String field : entry.getValue()) {
fields.add(alias + '.' + field);
}
}
fields.removeAll(specificFilters);
if (!fields.isEmpty()) {
final List terms = multipleFilter.getTerms();
applyFiltersOnQuery(builder, fields, terms, enableWordSearch);
}
}
protected void applyFiltersOnQuery(final StringBuilder queryBuilder, final Set fields, final List terms, final boolean enableWordSearch) {
if (!queryBuilder.toString().contains("WHERE")) {
queryBuilder.append(" WHERE ");
} else {
queryBuilder.append(" AND ");
}
queryBuilder.append("(");
final Iterator fieldIterator = fields.iterator();
while (fieldIterator.hasNext()) {
buildLikeClauseForOneFieldMultipleTerms(queryBuilder, fieldIterator.next(), terms, enableWordSearch);
if (fieldIterator.hasNext()) {
queryBuilder.append(" OR ");
}
}
queryBuilder.append(")");
}
/**
* @param queryBuilder
* @param currentField
* @param terms
* @param enableWordSearch
*/
protected void buildLikeClauseForOneFieldMultipleTerms(final StringBuilder queryBuilder, final String currentField, final List terms,
final boolean enableWordSearch) {
final Iterator termIterator = terms.iterator();
while (termIterator.hasNext()) {
final String currentTerm = termIterator.next();
buildLikeClauseForOneFieldOneTerm(queryBuilder, currentField, currentTerm, enableWordSearch);
if (termIterator.hasNext()) {
queryBuilder.append(" OR ");
}
}
}
/**
* @param queryBuilder
* @param currentField
* @param currentTerm
* @param enableWordSearch
*/
protected void buildLikeClauseForOneFieldOneTerm(final StringBuilder queryBuilder, final String currentField, final String currentTerm,
final boolean enableWordSearch) {
// Search if a sentence starts with the term
queryBuilder.append(currentField).append(buildLikeEscapeClause(currentTerm, "", "%"));
if (enableWordSearch) {
// Search also if a word starts with the term
// We do not want to search for %currentTerm% to ensure we can use Lucene-like library.
queryBuilder.append(" OR ").append(currentField).append(buildLikeEscapeClause(currentTerm, "% ", "%"));
}
}
private String getQueryWithOrderByClause(final String query, final SelectListDescriptor selectDescriptor) throws SBonitaReadException {
final StringBuilder builder = new StringBuilder(query);
appendOrderByClause(builder, selectDescriptor);
return builder.toString();
}
private StringBuilder appendFilterClause(final StringBuilder clause, final FilterOption filterOption) {
final FilterOperationType type = filterOption.getFilterOperationType();
StringBuilder completeField = null;
if (filterOption.getPersistentClass() != null) {
completeField = new StringBuilder(getClassAliasMappings().get(filterOption.getPersistentClass().getName())).append('.').append(
filterOption.getFieldName());
}
Object fieldValue = filterOption.getValue();
if (fieldValue instanceof String) {
fieldValue = "'" + escapeString((String) fieldValue) + "'";
} else if (fieldValue instanceof EnumToObjectConvertible) {
fieldValue = ((EnumToObjectConvertible) fieldValue).fromEnum();
}
switch (type) {
case EQUALS:
if (fieldValue == null) {
clause.append(completeField).append(" IS NULL");
} else {
clause.append(completeField).append(" = ").append(fieldValue);
}
break;
case GREATER:
clause.append(completeField).append(" > ").append(fieldValue);
break;
case GREATER_OR_EQUALS:
clause.append(completeField).append(" >= ").append(fieldValue);
break;
case LESS:
clause.append(completeField).append(" < ").append(fieldValue);
break;
case LESS_OR_EQUALS:
clause.append(completeField).append(" <= ").append(fieldValue);
break;
case DIFFERENT:
clause.append(completeField).append(" != ").append(fieldValue);
break;
case IN:
clause.append(getInClause(completeField, filterOption));
break;
case BETWEEN:
final Object from = filterOption.getFrom() instanceof String ? "'" + escapeString((String) filterOption.getFrom()) + "'"
: filterOption.getFrom();
final Object to = filterOption.getTo() instanceof String ? "'" + escapeString((String) filterOption.getTo()) + "'" : filterOption.getTo();
clause.append("(").append(from).append(" <= ").append(completeField);
clause.append(" AND ").append(completeField).append(" <= ").append(to).append(")");
break;
case LIKE:
// TODO:write LIKE
clause.append(completeField).append(" LIKE '%").append(escapeTerm((String) filterOption.getValue())).append("%'");
break;
case L_PARENTHESIS:
clause.append(" (");
break;
case R_PARENTHESIS:
clause.append(" )");
break;
case AND:
clause.append(" AND ");
break;
case OR:
clause.append(" OR ");
break;
default:
// TODO:do we want default behaviour?
break;
}
return completeField;
}
private String getInClause(final StringBuilder completeField, final FilterOption filterOption) {
final StringBuilder stb = new StringBuilder(completeField);
stb.append(" in (");
stb.append(getInValues(filterOption));
stb.append(")");
return stb.toString();
}
private String getInValues(final FilterOption filterOption) {
final StringBuilder stb = new StringBuilder();
for (final Object element : filterOption.getIn()) {
stb.append(element + ",");
}
final String inValues = stb.toString();
return inValues.substring(0, inValues.length() - 1);
}
private void appendOrderByClause(final StringBuilder builder, final SelectListDescriptor selectDescriptor) throws SBonitaReadException {
builder.append(" ORDER BY ");
boolean startWithComma = false;
boolean sortedById = false;
for (final OrderByOption orderByOption : selectDescriptor.getQueryOptions().getOrderByOptions()) {
if (startWithComma) {
builder.append(',');
}
final Class extends PersistentObject> clazz = orderByOption.getClazz();
if (clazz != null) {
appendClassAlias(builder, clazz);
}
final String fieldName = orderByOption.getFieldName();
if ("id".equalsIgnoreCase(fieldName) || "sourceObjectId".equalsIgnoreCase(fieldName)) {
sortedById = true;
}
builder.append(fieldName);
builder.append(' ');
builder.append(orderByOption.getOrderByType().toString());
startWithComma = true;
}
if (!sortedById) {
if (startWithComma) {
builder.append(',');
}
appendClassAlias(builder, selectDescriptor.getEntityType());
builder.append("id");
builder.append(' ');
builder.append("ASC");
}
}
private void appendClassAlias(final StringBuilder builder, final Class extends PersistentObject> clazz) throws SBonitaReadException {
final String className = clazz.getName();
final String classAlias = getClassAliasMappings().get(className);
if (classAlias == null || classAlias.trim().isEmpty()) {
throw new SBonitaReadException("No class alias found for class " + className);
}
builder.append(classAlias);
builder.append('.');
}
protected void setQueryCache(final Query query, final String name) {
if (cacheQueries != null && cacheQueries.containsKey(name)) {
query.setCacheable(true);
}
}
@Override
public List selectList(final SelectListDescriptor selectDescriptor) throws SBonitaReadException {
try {
final Class extends PersistentObject> entityClass = selectDescriptor.getEntityType();
checkClassMapping(entityClass);
final Session session = getSession(true);
Query query = session.getNamedQuery(selectDescriptor.getQueryName());
String builtQuery = query.getQueryString();
if (selectDescriptor.hasAFilter()) {
final QueryOptions queryOptions = selectDescriptor.getQueryOptions();
final boolean enableWordSearch = isWordSearchEnabled(selectDescriptor.getEntityType());
builtQuery = getQueryWithFilters(builtQuery, queryOptions.getFilters(), queryOptions.getMultipleFilter(), enableWordSearch);
}
if (selectDescriptor.hasOrderByParameters()) {
builtQuery = getQueryWithOrderByClause(builtQuery, selectDescriptor);
}
if (!builtQuery.equals(query.getQueryString())) {
query = session.createQuery(builtQuery);
}
setQueryCache(query, selectDescriptor.getQueryName());
setParameters(query, selectDescriptor.getInputParameters());
query.setFirstResult(selectDescriptor.getStartIndex());
query.setMaxResults(selectDescriptor.getPageSize());
checkOrderByClause(query);
@SuppressWarnings("unchecked")
final List list = query.list();
if (list != null) {
return list;
}
return Collections.emptyList();
} catch (final AssertionFailure | LockAcquisitionException | StaleStateException e) {
throw new SRetryableException(e);
} catch (final HibernateException | SPersistenceException e) {
throw new SBonitaReadException(e, selectDescriptor);
}
}
private void checkOrderByClause(final Query query) {
if (!query.getQueryString().toLowerCase().contains("order by")) {
switch (orderByCheckingMode) {
case NONE:
break;
case WARNING:
logger.log(
AbstractHibernatePersistenceService.class,
TechnicalLogSeverity.WARNING,
"Query '"
+ query.getQueryString()
+ "' does not contain 'ORDER BY' clause. It's better to modify your query to order the result, especially if you use the pagination.");
break;
case STRICT:
default:
throw new IllegalArgumentException("Query " + query.getQueryString()
+ " does not contain 'ORDER BY' clause hence is not allowed. Please specify ordering before re-sending the query");
}
}
}
protected void setParameters(final Query query, final Map inputParameters) {
for (final Map.Entry entry : inputParameters.entrySet()) {
final Object value = entry.getValue();
if (value instanceof Collection>) {
query.setParameterList(entry.getKey(), (Collection>) value);
} else {
query.setParameter(entry.getKey(), value);
}
}
}
public Map getClassAliasMappings() {
return classAliasMappings;
}
@Override
public void delete(final long id, final Class extends PersistentObject> entityClass) throws SPersistenceException {
final Class extends PersistentObject> mappedClass = getMappedClass(entityClass);
final Query query = getSession(true).getNamedQuery("delete" + mappedClass.getSimpleName());
query.setLong("id", id);
try {
query.executeUpdate();
} catch (final AssertionFailure | LockAcquisitionException | StaleStateException e) {
throw new SRetryableException(e);
} catch (final HibernateException he) {
throw new SPersistenceException(he);
}
}
@Override
public void delete(final List ids, final Class extends PersistentObject> entityClass) throws SPersistenceException {
final Class extends PersistentObject> mappedClass = getMappedClass(entityClass);
final Query query = getSession(true).getNamedQuery("deleteByIds" + mappedClass.getSimpleName());
query.setParameterList("ids", ids);
try {
query.executeUpdate();
} catch (final AssertionFailure | LockAcquisitionException | StaleStateException e) {
throw new SRetryableException(e);
} catch (final HibernateException sse) {
throw new SPersistenceException(sse);
}
}
public void destroy() {
logger.log(getClass(), TechnicalLogSeverity.INFO, "Closing Hibernate session factory of " + getClass().getName());
sessionFactory.close();
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy