/*
* Copyright 2011-2013 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 kr.debop4j.data.hibernate.tools;
import com.google.common.collect.Maps;
import kr.debop4j.core.Guard;
import kr.debop4j.core.tools.SerializeTool;
import kr.debop4j.core.tools.StringTool;
import kr.debop4j.data.hibernate.HibernateParameter;
import kr.debop4j.data.hibernate.listener.UpdateTimestampedEventListener;
import kr.debop4j.data.hibernate.repository.IHibernateRepository;
import kr.debop4j.data.hibernate.repository.IHibernateRepositoryFactory;
import kr.debop4j.data.model.IStatefulEntity;
import org.hibernate.Criteria;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
import org.hibernate.criterion.Criterion;
import org.hibernate.criterion.DetachedCriteria;
import org.hibernate.criterion.Order;
import org.hibernate.event.service.spi.EventListenerRegistry;
import org.hibernate.event.spi.EventType;
import org.hibernate.internal.CriteriaImpl;
import org.hibernate.internal.SessionFactoryImpl;
import org.hibernate.service.ServiceRegistryBuilder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.Map;
import static kr.debop4j.core.Guard.shouldNotBeNull;
/**
* Hibernate 관련 Tool
* Jpa@author 배성혁 ( sunghyouk.bae@gmail.com )
*
* @since 12. 11. 19
*/
@Component
public class HibernateTool {
private static final Logger log = LoggerFactory.getLogger(HibernateTool.class);
private static final boolean isTraceEnabled = log.isTraceEnabled();
private static final boolean isDebugEnabled = log.isDebugEnabled();
private HibernateTool() { }
/**
* Build session factory.
*
* @param cfg the cfg
* @return the session factory
*/
public static SessionFactory buildSessionFactory(Configuration cfg) {
assert cfg != null;
if (log.isInfoEnabled())
log.info("SessionFactory를 빌드합니다.");
ServiceRegistryBuilder registryBuilder = new ServiceRegistryBuilder().applySettings(cfg.getProperties());
SessionFactory factory = cfg.buildSessionFactory(registryBuilder.buildServiceRegistry());
if (log.isInfoEnabled())
log.info("SessionFactory를 빌드했습니다.");
return factory;
}
private static IHibernateRepositoryFactory hibernateDaoFactory;
/**
* Sets hibernate dao factory.
*
* @param factory the factory
*/
@Autowired
public void setHibernateDaoFactory(IHibernateRepositoryFactory factory) {
hibernateDaoFactory = factory;
}
/**
* Gets hibernate dao factory.
*
* @return the hibernate dao factory
*/
public static IHibernateRepositoryFactory getHibernateDaoFactory() {
return hibernateDaoFactory;
}
/**
* Gets hibernate dao.
*
* @param entityClass the entity class
* @return the hibernate dao
*/
public static <E extends IStatefulEntity> IHibernateRepository getHibernateRepository(Class<E> entityClass) {
return getHibernateDaoFactory().getOrCreateHibernateRepository(entityClass);
}
/**
* Register event listener.
*
* @param sessionFactory the session factory
* @param listener the listener
* @param eventTypes the event types
*/
@SuppressWarnings("unchecked")
public static void registerEventListener(SessionFactory sessionFactory, Object listener, EventType... eventTypes) {
shouldNotBeNull(sessionFactory, "sessionFactory");
shouldNotBeNull(listener, "listener");
log.trace("sessionFactory에 event listener를 등록합니다... listener=[{}], eventTypes=[{}]",
listener, StringTool.listToString(eventTypes));
EventListenerRegistry registry =
((SessionFactoryImpl) sessionFactory)
.getServiceRegistry()
.getService(EventListenerRegistry.class);
for (EventType eventType : eventTypes) {
try {
registry.getEventListenerGroup(eventType).appendListener(listener);
} catch (Exception ignored) {}
}
}
/**
* Register update timestamp event listener.
*
* @param sessionFactory the session factory
*/
public static void registerUpdateTimestampEventListener(SessionFactory sessionFactory) {
registerEventListener(sessionFactory,
new UpdateTimestampedEventListener(),
EventType.PRE_INSERT, EventType.PRE_UPDATE);
}
/**
* {@link HibernateParameter} 정보를 Name, Value 형태의 맵으로 변환합니다. @param parameters the parameters
*
* @return the map
*/
public static Map<String, Object> toMap(HibernateParameter... parameters) {
Map<String, Object> map = Maps.newHashMap();
for (HibernateParameter parameter : parameters) {
map.put(parameter.getName(), parameter.getValue());
}
return map;
}
/**
* 지정된 수형에 대한 Detached Criteria 를 제공합니다. @param clazz the clazz
*
* @return the detached criteria
*/
public static <T extends IStatefulEntity> DetachedCriteria createDetachedCriteria(Class<T> clazz) {
return DetachedCriteria.forClass(clazz);
}
/**
* 지정된 수형에 대한 Detached Criteria 를 제공합니다. @param entityClass the entity class
*
* @param session the session
* @param orders the orders
* @param criterions the criterions
* @return the criteria
*/
public static Criteria createCriteria(Class entityClass, Session session, Order[] orders, Criterion... criterions) {
if (log.isDebugEnabled())
log.debug("엔티티 [{}] 에 대한 Criteria를 생성합니다...", entityClass.getName());
Criteria criteria = session.createCriteria(entityClass);
addOrders(criteria, orders);
return addCriterions(criteria, criterions);
}
/**
* {@link org.hibernate.criterion.DetachedCriteria} 를 복사합니다. @param dc the dc
*
* @return the detached criteria
*/
public static DetachedCriteria copyDetachedCriteria(DetachedCriteria dc) {
shouldNotBeNull(dc, "dc");
return (DetachedCriteria) SerializeTool.copyObject(dc);
}
/**
* Copy criteria.
*
* @param criteria the criteria
* @return the criteria
*/
public static Criteria copyCriteria(Criteria criteria) {
shouldNotBeNull(criteria, "criteria");
return (Criteria) SerializeTool.copyObject((CriteriaImpl) criteria);
}
/**
* {@link org.hibernate.criterion.DetachedCriteria} 를 현 {@link org.hibernate.Session} 에서 사용할 {@link org.hibernate.Criteria} 로 변환합니다. @param session the session
*
* @param dc the dc
* @return the executable criteria
*/
public static Criteria getExecutableCriteria(Session session, DetachedCriteria dc) {
return dc.getExecutableCriteria(session);
}
/**
* {@link org.hibernate.criterion.DetachedCriteria} 를 가지고 {@link org.hibernate.Criteria} 를 빌드합니다. @param dc the dc
*
* @param session the session
* @param orders the orders
* @return the executable criteria
*/
public static Criteria getExecutableCriteria(DetachedCriteria dc, Session session, Order... orders) {
Guard.shouldNotBeNull(dc, "dc");
Guard.shouldNotBeNull(session, "session");
if (log.isDebugEnabled())
log.debug("DetachedCriteria를 가지고 Criteria를 빌드합니다.");
Criteria criteria = dc.getExecutableCriteria(session);
for (Order order : orders) {
criteria.addOrder(order);
}
return criteria;
}
/**
* Add orders.
*
* @param dc the dc
* @param orders the orders
* @return the detached criteria
*/
public static DetachedCriteria addOrders(DetachedCriteria dc, Order... orders) {
shouldNotBeNull(dc, "dc");
for (Order order : orders) {
dc.addOrder(order);
}
return dc;
}
/**
* Add orders.
*
* @param dc the dc
* @param orders the orders
* @return the detached criteria
*/
public static DetachedCriteria addOrders(DetachedCriteria dc, Iterable<Order> orders) {
shouldNotBeNull(dc, "dc");
for (Order order : orders)
dc.addOrder(order);
return dc;
}
/**
* Add orders.
*
* @param criteria the criteria
* @param orders the orders
* @return the criteria
*/
public static Criteria addOrders(Criteria criteria, Order... orders) {
shouldNotBeNull(criteria, "criteria");
for (Order order : orders) {
criteria.addOrder(order);
}
return criteria;
}
/**
* Add orders.
*
* @param criteria the criteria
* @param orders the orders
* @return the criteria
*/
public static Criteria addOrders(Criteria criteria, Iterable<Order> orders) {
shouldNotBeNull(criteria, "criteria");
for (Order order : orders) {
criteria.addOrder(order);
}
return criteria;
}
/**
* {@link org.hibernate.Criteria} 에 {@link org.hibernate.criterion.Criterion} 들을 AND 로 추가합니다. @param criteria the criteria
*
* @param criterions the criterions
* @return the criteria
*/
public static Criteria addCriterions(Criteria criteria, Criterion... criterions) {
shouldNotBeNull(criteria, "criteria");
for (Criterion criterion : criterions) {
criteria.add(criterion);
}
return criteria;
}
/**
* {@link org.hibernate.Query} 의 인자에 값을 설정합니다. @param query the query
*
* @param params the params
* @return the parameters
*/
public static Query setParameters(Query query, HibernateParameter... params) {
shouldNotBeNull(query, "query");
for (HibernateParameter param : params) {
log.trace("쿼리문의 인자값을 설정합니다. param=[{}]", param);
query.setParameter(param.getName(), param.getValue());
}
return query;
}
/**
* {@link org.hibernate.Criteria} 에 조회 범위를 지정합니다. @param criteria the criteria
*
* @param firstResult the first result
* @param maxResults the max results
* @return the paging
*/
public static Criteria setPaging(Criteria criteria, Integer firstResult, Integer maxResults) {
Guard.shouldNotBeNull(criteria, "criteria");
if (log.isDebugEnabled())
log.debug("criteria에 fetch range를 지정합니다. firstResult=[{}], maxResults=[{}]", firstResult, maxResults);
if (firstResult != null && firstResult >= 0)
criteria.setFirstResult(firstResult);
if (maxResults != null && maxResults > 0)
criteria.setMaxResults(maxResults);
return criteria;
}
/**
* {@link org.hibernate.Query} 에 조회 범위를 지정합니다. @param query the query
*
* @param firstResult the first result
* @param maxResults the max results
* @return the paging
*/
public static Query setPaging(Query query, Integer firstResult, Integer maxResults) {
Guard.shouldNotBeNull(query, "query");
if (log.isDebugEnabled())
log.debug("query에 fetch range를 지정합니다. firstResult=[{}], maxResults=[{}]", firstResult, maxResults);
if (firstResult != null && firstResult >= 0)
query.setFirstResult(firstResult);
if (maxResults != null && maxResults > 0)
query.setMaxResults(maxResults);
return query;
}
}