Java tutorial
/** * 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.L_PARENTHESIS; import static org.bonitasoft.engine.persistence.search.FilterOperationType.R_PARENTHESIS; import static org.bonitasoft.engine.persistence.search.FilterOperationType.isNormalOperator; 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<String, String> classAliasMappings; protected final Map<String, String> cacheQueries; protected final List<Class<? extends PersistentObject>> classMapping; protected final Map<String, Class<? extends PersistentObject>> interfaceToClassMapping; protected final List<String> 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<Class<? extends PersistentObject>> classMapping, final Map<String, String> classAliasMappings, final boolean enableWordSearch, final Set<String> 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<String> 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<PersistentClass> classMappingsIterator = configuration.getClassMappings(); classMapping = new ArrayList<Class<? extends PersistentObject>>(); 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 <T> void logWarningMessage(final SelectListDescriptor<T> 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<String, Object> 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<PersistentObject> 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<String, Object> 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> T selectOne(final SelectOneDescriptor<T> 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 extends PersistentObject> T selectById(final SelectByIdDescriptor<T> 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 extends PersistentObject> T selectById(final Session session, final SelectByIdDescriptor<T> 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> T selectOne(final Session session, final AbstractSelectDescriptor<T> selectDescriptor, final Map<String, Object> 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<FilterOption> filters, final SearchFields multipleFilter, final boolean enableWordSearch) { final StringBuilder builder = new StringBuilder(query); final Set<String> specificFilters = new HashSet<String>(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<String> specificFilters, final boolean enableWordSearch) { final Map<Class<? extends PersistentObject>, Set<String>> allTextFields = multipleFilter.getFields(); final Set<String> fields = new HashSet<String>(); for (final Entry<Class<? extends PersistentObject>, Set<String>> entry : allTextFields.entrySet()) { final String alias = getClassAliasMappings().get(entry.getKey().getName()); for (final String field : entry.getValue()) { final StringBuilder aliasBuilder = new StringBuilder(alias); aliasBuilder.append('.').append(field); fields.add(aliasBuilder.toString()); } } fields.removeAll(specificFilters); if (!fields.isEmpty()) { final List<String> terms = multipleFilter.getTerms(); applyFiltersOnQuery(builder, fields, terms, enableWordSearch); } } protected void applyFiltersOnQuery(final StringBuilder queryBuilder, final Set<String> fields, final List<String> terms, final boolean enableWordSearch) { if (!queryBuilder.toString().contains("WHERE")) { queryBuilder.append(" WHERE "); } else { queryBuilder.append(" AND "); } queryBuilder.append("("); final Iterator<String> 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<String> terms, final boolean enableWordSearch) { final Iterator<String> 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 <T> String getQueryWithOrderByClause(final String query, final SelectListDescriptor<T> 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 = "'" + 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 ? "'" + filterOption.getFrom() + "'" : filterOption.getFrom(); final Object to = filterOption.getTo() instanceof 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(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 <T> void appendOrderByClause(final StringBuilder builder, final SelectListDescriptor<T> 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 <T> List<T> selectList(final SelectListDescriptor<T> 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<T> 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<String, Object> inputParameters) { for (final Map.Entry<String, Object> 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<String, String> 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<Long> 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(); } }