package com.mossle.core.hibernate; import java.io.Serializable; import java.lang.reflect.InvocationTargetException; import java.util.Collection; import java.util.List; import javax.annotation.Resource; import javax.transaction.Synchronization; import com.mossle.core.id.IdGenerator; import com.mossle.core.util.BeanUtils; import com.mossle.core.util.ReflectUtils; import org.hibernate.Criteria; import org.hibernate.Hibernate; import org.hibernate.Session; import org.hibernate.SessionFactory; import org.hibernate.criterion.Order; import org.hibernate.metadata.ClassMetadata; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.BeansException; import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContextAware; import org.springframework.context.ApplicationEvent; import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.support.TransactionSynchronizationAdapter; import org.springframework.transaction.support.TransactionSynchronizationManager; import org.springframework.util.Assert; import org.springframework.util.StringUtils; /** * 封装session和jdbcTemplate的基础类,不涉及泛型和CRUD操作. * * @author Lingo */ @Transactional(rollbackFor = Exception.class) public class HibernateBasicDao implements ApplicationContextAware { /** logger. */ private static Logger logger = LoggerFactory .getLogger(HibernateBasicDao.class); /** application context. */ private ApplicationContext applicationContext; /** sessionFactory. */ private SessionFactory sessionFactory; /** jdbcTemplate. */ private JdbcTemplate jdbcTemplate; /** idGenerator. */ private IdGenerator idGenerator; /** default constructor. */ public HibernateBasicDao() { } /** * constructor. * * @param sessionFactory * SessionFactory */ public HibernateBasicDao(SessionFactory sessionFactory) { this.sessionFactory = sessionFactory; } /** @return SessionFactory. */ public SessionFactory getSessionFactory() { return sessionFactory; } /** @return jdbcTemplate. */ public JdbcTemplate getJdbcTemplate() { return jdbcTemplate; } /** @return idGenerator. */ public IdGenerator getIdGenerator() { return idGenerator; } /** @return session. */ public Session getSession() { return this.sessionFactory.getCurrentSession(); } // ============================================================================================ // autowired // ============================================================================================ public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { logger.debug("Autowired applicationContext"); this.applicationContext = applicationContext; } /** * @param sessionFactory * SessionFactory. */ @Resource public void setSessionFactory(SessionFactory sessionFactory) { this.sessionFactory = sessionFactory; } /** * @param jdbcTemplate * JdbcTemplate. */ @Resource public void setJdbcTemplate(JdbcTemplate jdbcTemplate) { this.jdbcTemplate = jdbcTemplate; } /** * @param idGenerator * IdGenerator. */ @Resource public void setIdGenerator(IdGenerator idGenerator) { this.idGenerator = idGenerator; } // ============================================================================================ // get, load, getAll, save, remove, removeById, removeAll // ============================================================================================ /** * 获得一个实体类型的一条记录. * * @param <T> * 实体类型 * @param entityClass * 实体类型 * @param id * 主键 * @return 实例 */ @Transactional(readOnly = true) public <T> T get(Class<T> entityClass, Serializable id) { Assert.notNull(id, "Id can not be null."); return (T) this.getSession().get(entityClass, id); } /** * load一个实例,如果id不存在,会返回一个proxy,在调用proxy的时候出现问题. 使用这个方法,可以利用缓存,但是如果实例不存在,会出现不容易预计的错误 * * @param <T> * 实体类型 * @param entityClass * 实体类型 * @param id * 主键 * @return 实例 */ @Transactional(readOnly = true) public <T> T load(Class<T> entityClass, Serializable id) { Assert.notNull(id, "Id can not be null."); return (T) this.getSession().load(entityClass, id); } /** * 获得一个实体类型的所有记录. * * @param <T> * 实体类型 * @param entityClass * 实体类型 * @return 所有实例列表 */ @Transactional(readOnly = true) public <T> List<T> getAll(Class<T> entityClass) { return this.getSession().createCriteria(entityClass).list(); } /** * 获得所有记录,带排序参数. * * @param <T> * 实体类型 * @param entityClass * 实体类型 * @param orderBy * 排序字段名 * @param isAsc * 是否正序排列 * @return 返回结果列表 */ @Transactional(readOnly = true) public <T> List<T> getAll(Class<T> entityClass, String orderBy, boolean isAsc) { if (StringUtils.hasText(orderBy)) { Criteria criteria = this.getSession().createCriteria(entityClass); if (isAsc) { criteria.addOrder(Order.asc(orderBy)); } else { criteria.addOrder(Order.desc(orderBy)); } return criteria.list(); } else { return this.getAll(entityClass); } } /** * 添加或更新. 相关的操作包括:save, update, saveOrUpdate, merge, persist, refresh * * @param entity * 实例 */ @Transactional public void save(Object entity) { Assert.notNull(entity, "Entity can not be null."); this.getSession().saveOrUpdate(entity); logger.debug("save entity: {}", entity); } @Transactional public void insert(Object entity) { Assert.notNull(entity, "Entity can not be null."); this.getSession().save(entity); logger.debug("insert entity: {}", entity); } @Transactional public void update(Object entity) { Assert.notNull(entity, "Entity can not be null."); this.getSession().update(entity); logger.debug("update entity: {}", entity); } /** * 删除一条记录. * * @param entity * 实例 */ @Transactional public void remove(Object entity) { Assert.notNull(entity, "Entity can not be null."); this.getSession().delete(entity); logger.debug("remove entity: {}", entity); } /** * 根据主键删除记录. * * @param <T> * 实体类型 * @param entityClass * 实体类型 * @param id * 主键 */ @Transactional public <T> void removeById(Class<T> entityClass, Serializable id) { Assert.notNull(id, "Id can not be null."); this.remove(this.load(entityClass, id)); logger.debug("remove entity by id: {}", id); } /** * 删除集合里的所有记录. * * @param list * 需要删除的集合 */ @Transactional public void removeAll(Collection list) { Assert.notNull(list, "List can not be null."); for (Object obj : list) { this.remove(obj); } } /** * 删除所有记录. * * @param <T> * 实体类型 * @param entityClass * 实体类型 */ @Transactional public <T> void removeAll(Class<T> entityClass) { this.removeAll(this.getAll(entityClass)); } // ============================================================================================ // flush, clear, evict, initialize // ============================================================================================ /** 把session中的数据flush到数据库里. */ public void flush() { this.getSession().flush(); } /** 清空session. */ public void clear() { this.getSession().clear(); } /** * 把实体类对象从session中删除. * * @param entity * 实体类 */ public void evict(Object entity) { Assert.notNull(entity, "Entity cannot be null"); this.getSession().evict(entity); } /** * 直接初始化数据,避免出现lazy load错误的一个方法. * * @param object * entity */ public void initialize(Object object) { Assert.notNull(object, "Object cannot be null"); Hibernate.initialize(object); } // ============================================================================================ // getId, getIdName // ============================================================================================ /** * 取得对象的主键值,辅助函数. * * @param entityClass * 实体类型 * @param entity * 实体对象 * @param <T> * generic * @return 主键 * @throws NoSuchMethodException * 找不到方法 * @throws IllegalAccessException * 没有访问权限 * @throws InvocationTargetException * 反射异常 */ public Serializable getId(Class entityClass, Object entity) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException { Assert.notNull(entity); String idName = getIdName(entityClass); String getterName = ReflectUtils.getGetterMethodName(entity, idName); return (Serializable) BeanUtils.invokeMethod(entity, getterName); } public void setId(Class entityClass, Object entity, Serializable idValue) { Assert.notNull(entity); Assert.notNull(idValue); try { String idName = getIdName(entityClass); String setterName = ReflectUtils.getSetterMethodName(idName); BeanUtils.invokeMethod(entity, setterName, idValue); } catch (NoSuchMethodException ex) { logger.info(ex.getMessage(), ex); } catch (IllegalAccessException ex) { logger.info(ex.getMessage(), ex); } catch (InvocationTargetException ex) { logger.info(ex.getMessage(), ex); } } /** * 取得对象的主键名,辅助函数. * * @param entityClass * 实体类型 * @return 主键名称 */ public String getIdName(Class entityClass) { Assert.notNull(entityClass); entityClass = ReflectUtils.getOriginalClass(entityClass); ClassMetadata meta = this.getSessionFactory().getClassMetadata( entityClass); Assert.notNull(meta, "Class " + entityClass + " not define in hibernate session factory."); String idName = meta.getIdentifierPropertyName(); Assert.hasText(idName, entityClass.getSimpleName() + " has no identifier property define."); return idName; } // ============================================================================================ // publish event // ============================================================================================ public void registerSynchronization(Synchronization synchronization) { SynchronizationNotification synchronizationNotification = new SynchronizationNotification( synchronization); TransactionSynchronizationManager .registerSynchronization(synchronizationNotification); } public void publishEvent(ApplicationEvent applicationEvent) { this.applicationContext.publishEvent(applicationEvent); } public static class SynchronizationNotification extends TransactionSynchronizationAdapter { private Synchronization synchronization; public SynchronizationNotification(Synchronization synchronization) { this.synchronization = synchronization; } public void afterCompletion(int status) { synchronization.afterCompletion(status); } public void beforeCompletion() { synchronization.beforeCompletion(); } } }