/** * This Source Code Form is subject to the terms of the Mozilla Public License, * v. 2.0. If a copy of the MPL was not distributed with this file, You can * obtain one at http://mozilla.org/MPL/2.0/. OpenMRS is also distributed under * the terms of the Healthcare Disclaimer located at http://openmrs.org/license. * * Copyright (C) OpenMRS Inc. OpenMRS is a registered trademark and the OpenMRS * graphic logo is a trademark of OpenMRS Inc. */ package org.openmrs.api.db.hibernate; import java.sql.Connection; import java.sql.SQLException; import java.util.Map; import org.apache.commons.lang.StringUtils; import org.hibernate.Criteria; import org.hibernate.Hibernate; import org.hibernate.SessionFactory; import org.hibernate.criterion.Conjunction; import org.hibernate.criterion.DetachedCriteria; import org.hibernate.criterion.Projections; import org.hibernate.criterion.Property; import org.hibernate.criterion.Restrictions; import org.hibernate.dialect.Dialect; import org.hibernate.dialect.HSQLDialect; import org.hibernate.engine.spi.SessionFactoryImplementor; import org.hibernate.jdbc.ReturningWork; import org.hibernate.proxy.HibernateProxy; import org.openmrs.Location; import org.openmrs.attribute.AttributeType; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * This class holds common methods and utilities that are used across the hibernate related classes */ public class HibernateUtil { private static Logger log = LoggerFactory.getLogger(HibernateUtil.class); private static Dialect dialect = null; private static Boolean isHSQLDialect = null; /** * Check and cache whether the currect dialect is HSQL or not. This is needed because some * queries are different if in the hsql world as opposed to the mysql/postgres world * * @param sessionFactory * @return true/false whether we're in hsql right now or not */ public static boolean isHSQLDialect(SessionFactory sessionFactory) { if (isHSQLDialect == null) { // check and cache the dialect isHSQLDialect = HSQLDialect.class.getName().equals(getDialect(sessionFactory).getClass().getName()); } return isHSQLDialect; } /** * Fetch the current Dialect of the given SessionFactory * * @param sessionFactory SessionFactory to pull the dialect from * @return Dialect of sql that this connection/session is using */ public static Dialect getDialect(SessionFactory sessionFactory) { // return cached dialect if (dialect != null) { return dialect; } SessionFactoryImplementor implementor = (SessionFactoryImplementor) sessionFactory; dialect = implementor.getDialect(); if (log.isDebugEnabled()) { log.debug("Getting dialect for session: " + dialect); } return dialect; } /** * @see HibernateUtil#escapeSqlWildcards(String, Connection) */ public static String escapeSqlWildcards(final String oldString, SessionFactory sessionFactory) { return sessionFactory.getCurrentSession().doReturningWork(new ReturningWork<String>() { @Override public String execute(Connection connection) throws SQLException { return escapeSqlWildcards(oldString, connection); } }); } /** * Escapes all sql wildcards in the given string, returns the same string if it doesn't contain * any sql wildcards * * @param oldString the string in which to escape the sql wildcards * @param connection The underlying database connection * @return the string with sql wildcards escaped if any found otherwise the original string is * returned */ public static String escapeSqlWildcards(String oldString, Connection connection) { //replace all sql wildcards if any if (!StringUtils.isBlank(oldString)) { String escapeCharacter = ""; try { //get the database specific escape character from the metadata escapeCharacter = connection.getMetaData().getSearchStringEscape(); } catch (SQLException e) { log.warn("Error generated", e); } //insert an escape character before each sql wildcard in the search phrase return StringUtils.replaceEach(oldString, new String[] { "%", "_", "*", "'" }, new String[] { escapeCharacter + "%", escapeCharacter + "_", escapeCharacter + "*", "''" }); } else { return oldString; } } /** * Adds attribute value criteria to the given criteria query * * @param criteria the criteria * @param serializedAttributeValues the serialized attribute values * @param <AT> the attribute type */ public static <AT extends AttributeType> void addAttributeCriteria(Criteria criteria, Map<AT, String> serializedAttributeValues) { Conjunction conjunction = Restrictions.conjunction(); int a = 0; for (Map.Entry<AT, String> entry : serializedAttributeValues.entrySet()) { String alias = "attributes" + (a++); DetachedCriteria detachedCriteria = DetachedCriteria.forClass(Location.class).setProjection(Projections.id()); detachedCriteria.createAlias("attributes", alias); detachedCriteria.add(Restrictions.eq(alias + ".attributeType", entry.getKey())); detachedCriteria.add(Restrictions.eq(alias + ".valueReference", entry.getValue())); detachedCriteria.add(Restrictions.eq(alias + ".voided", false)); conjunction.add(Property.forName("id").in(detachedCriteria)); } criteria.add(conjunction); } /** * Gets an object as an instance of its persistent type if it is a hibernate proxy otherwise * returns the same passed in object * * @param persistentObject the object to unproxy * @return the unproxied object * @since 1.10 */ public static <T> T getRealObjectFromProxy(T persistentObject) { if (persistentObject == null) { return null; } if (persistentObject instanceof HibernateProxy) { Hibernate.initialize(persistentObject); persistentObject = (T) ((HibernateProxy) persistentObject).getHibernateLazyInitializer().getImplementation(); } return persistentObject; } }