/*
* Copyright 2014-2016 CyberVision, Inc.
*
* 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 org.kaaproject.kaa.server.common.dao.impl.sql;
import static org.apache.commons.lang.StringUtils.isNotBlank;
import org.hibernate.Criteria;
import org.hibernate.FlushMode;
import org.hibernate.LockMode;
import org.hibernate.LockOptions;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.criterion.Criterion;
import org.hibernate.sql.JoinType;
import org.kaaproject.kaa.server.common.dao.impl.SqlDao;
import org.kaaproject.kaa.server.common.dao.model.sql.GenericModel;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
@SuppressWarnings("unchecked")
public abstract class HibernateAbstractDao<T extends GenericModel<?>> implements SqlDao<T> {
public static final int FIRST = 1;
private static final Logger LOG = LoggerFactory.getLogger(HibernateAbstractDao.class);
private static final int MAX_TIMEOUT = 30000;
@Autowired
private SessionFactory sessionFactory;
protected abstract Class<T> getEntityClass();
@Override
public Session getSession(FlushMode flushMode) {
Session session = sessionFactory.getCurrentSession();
session.setFlushMode(flushMode);
return session;
}
@Override
public Session getSession() {
return getSession(FlushMode.AUTO);
}
@Override
public void refresh(Object object) {
getSession().refresh(object);
}
protected Criteria getCriteria() {
return getSession().createCriteria(getEntityClass());
}
protected Query getQuery(String hql) {
return getSession().createQuery(hql);
}
protected List<T> findListByCriterion(Criterion criterion) {
String className = getSimpleClassName();
LOG.trace("Searching {} entities by criterion [{}] ", className, criterion);
Criteria criteria = getCriteria();
criteria.add(criterion);
List<T> resultList = criteria.list();
if (resultList == null) {
resultList = Collections.emptyList();
}
return resultList;
}
protected List<Long> toLongIds(List<String> ids) {
List<Long> lids = Collections.emptyList();
if (ids != null && !ids.isEmpty()) {
lids = new ArrayList<>();
for (String id : ids) {
try {
Long lid = Long.parseLong(id);
lids.add(lid);
} catch (NumberFormatException ex) {
LOG.warn("Can't convert string id {} to Long id", id);
}
}
}
return lids;
}
protected List<T> findListByCriterionWithAlias(String path, String alias, Criterion criterion) {
return findListByCriterionWithAlias(path, alias, null, criterion);
}
protected List<T> findListByCriterionWithAlias(String path, String alias,
JoinType type, Criterion criterion) {
String className = getSimpleClassName();
LOG.trace("Searching {} entities by criterion [{}] ", className, criterion);
Criteria criteria = getCriteria();
if (type == null) {
criteria.createAlias(path, alias);
} else {
criteria.createAlias(path, alias, type);
}
criteria.add(criterion);
List<T> resultList = criteria.list();
if (resultList == null) {
resultList = Collections.emptyList();
}
return resultList;
}
protected List<T> findListByCriteria(Criteria criteria) {
String className = getSimpleClassName();
LOG.trace("Searching {} entities by criteria [{}] ", className, criteria);
List<T> resultList = criteria.list();
if (resultList == null) {
resultList = Collections.emptyList();
}
return resultList;
}
protected T findOneByCriterion(Criterion criterion) {
String className = getSimpleClassName();
LOG.trace("Searching {} entity by criterion [{}] ", className, criterion);
Criteria criteria = getCriteria();
criteria.add(criterion);
return (T) criteria.uniqueResult();
}
protected T findOneByCriterionWithLock(Criterion criterion, LockMode lockMode) {
String className = getSimpleClassName();
LOG.trace("Searching {} entity by criterion [{}] ", className, criterion);
Criteria criteria = getCriteria();
criteria.setLockMode(lockMode);
criteria.add(criterion);
return (T) criteria.uniqueResult();
}
protected T findOneByCriterionWithAlias(String path, String alias, Criterion criterion) {
String className = getSimpleClassName();
LOG.trace("Searching {} entity by criterion [{}] ", className, criterion);
Criteria criteria = getCriteria();
criteria.createAlias(path, alias);
criteria.add(criterion);
return (T) criteria.uniqueResult();
}
protected T findOneByCriteria(Criteria criteria) {
String className = getSimpleClassName();
LOG.trace("Searching {} entity by criteria [{}] ", className, criteria);
return (T) criteria.uniqueResult();
}
@Override
public T save(T object, boolean flush) {
LOG.debug("Saving {} entity {}", getEntityClass(), object);
Session session = getSession();
object = (T) session.merge(object);
if (flush) {
session.flush();
}
if (LOG.isTraceEnabled()) {
LOG.trace("Saving result: {}", object);
} else {
LOG.debug("Saving result: {}", object != null);
}
return object;
}
@Override
public T save(T object) {
return save(object, false);
}
@Override
public <V> V save(V object, Class<?> clazz) {
LOG.debug("Saving {} entity {}", clazz, object);
Session session = getSession();
session.saveOrUpdate(object);
if (LOG.isTraceEnabled()) {
LOG.trace("[{}] Saving result: {}", clazz, object);
} else {
LOG.debug("[{}] Saving result: {}", clazz, object != null);
}
return object;
}
/**
* Updates an entity.
*
* @param obj entity
* @return updated entity.
*/
public T update(T obj) {
LOG.trace("Updated {} entity: {} ", getSimpleClassName(), obj);
getSession().update(obj);
LOG.trace("[{}] Update result: {}", getSimpleClassName(), obj != null);
return obj;
}
@Override
public T persist(T object) {
LOG.debug("Persisting {} entity {}", getEntityClass(), object);
Session session = getSession();
session.persist(object);
if (LOG.isTraceEnabled()) {
LOG.trace("Persisting result: {}", object);
} else {
LOG.debug("Persisting result: {}", object != null);
}
return object;
}
@Override
public List<T> find() {
List<T> resultList = getCriteria().list();
if (resultList == null) {
resultList = Collections.emptyList();
}
if (LOG.isTraceEnabled()) {
LOG.trace("Search result: {}.", Arrays.toString(resultList.toArray()));
} else {
LOG.debug("Search result: {}.", resultList.size());
}
return resultList;
}
@Override
public T findById(String id) {
return findById(id, false);
}
@Override
public T findById(String id, boolean lazy) {
T result = null;
String className = getSimpleClassName();
LOG.debug("Searching {} entity by id [{}] ", className, id);
if (isNotBlank(id)) {
Session session = getSession();
if (lazy) {
result = (T) session.load(getEntityClass(), Long.parseLong(id));
} else {
result = (T) session.get(getEntityClass(), Long.parseLong(id));
}
}
if (LOG.isTraceEnabled()) {
LOG.trace("[{}] Search result: {}.", id, result);
} else {
LOG.debug("[{}] Search result: {}.", id, result != null);
}
return result;
}
@Override
public void removeAll() {
Session session = getSession();
session.delete(getEntityClass());
LOG.debug("Removed all {} entities ", getSimpleClassName());
}
@Override
public void removeById(String id) {
if (isNotBlank(id)) {
Session session = getSession();
session.delete(findById(id, true));
LOG.debug("Removed {} entity by id [{}]", getSimpleClassName(), id);
}
}
@Override
public Session.LockRequest lockRequest(LockOptions lockOptions) {
int timeout = lockOptions.getTimeOut();
if (timeout > MAX_TIMEOUT) {
lockOptions.setTimeOut(MAX_TIMEOUT);
}
LOG.debug("Build lock request with options {}", lockOptions);
return getSession().buildLockRequest(lockOptions);
}
protected void remove(T obj) {
if (obj != null) {
getSession().delete(obj);
LOG.debug("Removed entity {} ", obj);
}
}
protected void removeList(List<T> list) {
if (list != null && !list.isEmpty()) {
Session session = getSession();
for (T o : list) {
session.delete(o);
}
LOG.debug("Removed list of {} entities ", list);
}
}
private String getSimpleClassName() {
return getEntityClass().getSimpleName();
}
}