想利用泛型抽取BaseDao层,简化操作时出现问题:
@Transactional这个注解是可以继承的,于是就想写在抽取的BaseDao层上,让实现的类可以不用写@Transactional,就可开启事务。
问题描述:
由于偷懒,没给BaseDao抽接口,代码如下:
- package com.liang.ssh2.base;
- import java.lang.reflect.ParameterizedType;
- import java.util.Collections;
- import java.util.List;
- import javax.annotation.Resource;
- import org.hibernate.Query;
- import org.hibernate.Session;
- import org.hibernate.SessionFactory;
- import org.springframework.transaction.annotation.Transactional;
- import com.liang.ssh2.config.Configuration;
- import com.liang.ssh2.entity.Page;
- import com.liang.ssh2.util.QueryHelper;
- @Transactional
- @SuppressWarnings("unchecked")
- public class BaseDao<T>{
- @Resource
- private SessionFactory sessionFactory;
- Class <T> clazz;
- /**
- * 通过反射获取参数类型
- */
- public BaseDaoImpl(){
- System.out.println(this);
- ParameterizedType pt = (ParameterizedType) this.getClass().getGenericSuperclass();
- clazz=(Class<T>) pt.getActualTypeArguments()[0];
- }
- /**
- * 获取当前可用的Session
- * @return
- */
- protected Session getSession() {
- return sessionFactory.getCurrentSession();
- }
- /* (non-Javadoc)
- * @see com.liang.ssh2.base.BaseDao#save(T)
- */
- public void save(T entity){
- getSession().save(entity);
- }
- /* (non-Javadoc)
- * @see com.liang.ssh2.base.BaseDao#getById(java.lang.Long)
- */
- public T getById(Long id){
- if(id==null) return null;
- return (T) getSession().get(clazz, id);
- }
- /* (non-Javadoc)
- * @see com.liang.ssh2.base.BaseDao#update(T)
- */
- public void update(T entity){
- getSession().update(entity);
- }
- /* (non-Javadoc)
- * @see com.liang.ssh2.base.BaseDao#delete(java.lang.Long)
- */
- public void delete(Long id){
- if(id!=null){
- Object entity=getById(id);
- if(entity!=null){
- getSession().delete(entity);
- }
- }
- }
- /* (non-Javadoc)
- * @see com.liang.ssh2.base.BaseDao#getByIds(java.lang.Long[])
- */
- public List<T> getByIds(Long[] ids){
- if(ids==null||ids.length==0){
- return Collections.EMPTY_LIST;
- }
- return getSession().createQuery(//
- "from "+clazz.getSimpleName()+"where id in(:ids)")//
- .setParameterList("ids", ids)//
- .list();
- }
- /* (non-Javadoc)
- * @see com.liang.ssh2.base.BaseDao#findAll()
- */
- public List<T> findAll(){
- return getSession().createQuery(//
- "from "+clazz.getSimpleName())//
- .list();
- }
- /* (non-Javadoc)
- * @see com.liang.ssh2.base.BaseDao#getPage(long, java.lang.Long, com.liang.ssh2.util.QueryHelper)
- */
- public Page getPage(long currentPage,Long pageSize,QueryHelper queryHelper){
- //如果用户没有动态指定pageSize,则读取配置文件
- if(pageSize==null){
- pageSize=Configuration.getPageSize();
- }
- //获得参数
- List<Object> parameters = queryHelper.getParameters();
- Query query = getSession().createQuery(queryHelper.getQueryListHql());
- if(parameters!=null&¶meters.size()>0){
- for (int i = 0; i < parameters.size(); i++) {
- query.setParameter(i, parameters.get(i));
- }
- }
- query.setFirstResult((int) ((currentPage-1)*pageSize));
- query.setMaxResults(pageSize.intValue());
- List recordList = query.list();
- // 查询总记录数
- query = getSession().createQuery(queryHelper.getQueryCountHql()); // 注意空格!
- if (parameters != null && parameters.size() > 0) { // 设置参数
- for (int i = 0; i < parameters.size(); i++) {
- query.setParameter(i, parameters.get(i));
- }
- }
- Long recordCount = (Long) query.uniqueResult(); // 查询
- return new Page(currentPage, pageSize, recordCount, recordList);
- }
- }
使用如下:
- package com.liang.ssh2.service.impl;
- import org.springframework.stereotype.Service;
- import com.liang.ssh2.base.BaseDao;
- import com.liang.ssh2.entity.User;
- @Service
- public class UserServiceImpl extends BaseDao<User>{
- }
注意我是把@Transactional放在BaseDao上了,由于@Transactional可继承,所以UserServiceImpl是不用放的
当启动服务器时会报错:Caused by: java.lang.ClassCastException: java.lang.Class cannot be cast to java.lang.reflect.ParameterizedType
为什么会这样呢?
测试了半天发现,出错就在BaseDao上注解:@Transactional上,原因不是很清楚!!!
两种解决方案:
一、直接将BaseDao上的@Transactional注解去掉,在实现类上加@Transactional,对于本例,在UserServiceImpl加上@Transactional即可开启事务,也不会报错!
二、别偷懒了,乖乖的给BaseDao抽个接口吧,其他什么都不用改,@Transactional还是照样可以继承,修改代码如下:
- package com.liang.ssh2.base;
- import java.util.List;
- import com.liang.ssh2.entity.Page;
- import com.liang.ssh2.util.QueryHelper;
- public interface BaseDao<T> {
- /**
- * 保存实体
- * @param entity
- */
- public abstract void save(T entity);
- /**
- * 根据id获取实体
- * @param id
- * @return
- */
- public abstract T getById(Long id);
- public abstract void update(T entity);
- public abstract void delete(Long id);
- public abstract List<T> getByIds(Long[] ids);
- public abstract List<T> findAll();
- /**
- * 获取page
- * @param currentPage
- * @param pageSize //如果用户没有动态指定pageSize(null),则读取配置文件
- * @param queryHelper
- * @return
- */
- public abstract Page getPage(long currentPage, Long pageSize,
- QueryHelper queryHelper);
- }
- package com.liang.ssh2.base;
- import java.lang.reflect.ParameterizedType;
- import java.util.Collections;
- import java.util.List;
- import javax.annotation.Resource;
- import org.hibernate.Query;
- import org.hibernate.Session;
- import org.hibernate.SessionFactory;
- import org.springframework.transaction.annotation.Transactional;
- import com.liang.ssh2.config.Configuration;
- import com.liang.ssh2.entity.Page;
- import com.liang.ssh2.util.QueryHelper;
- @Transactional
- @SuppressWarnings("unchecked")
- public class BaseDaoImpl<T> implements BaseDao<T>{
- @Resource
- private SessionFactory sessionFactory;
- Class <T> clazz;
- /**
- * 通过反射获取参数类型
- */
- public BaseDaoImpl(){
- System.out.println(this);
- ParameterizedType pt = (ParameterizedType) this.getClass().getGenericSuperclass();
- clazz=(Class<T>) pt.getActualTypeArguments()[0];
- }
- /**
- * 获取当前可用的Session
- * @return
- */
- protected Session getSession() {
- return sessionFactory.getCurrentSession();
- }
- /* (non-Javadoc)
- * @see com.liang.ssh2.base.BaseDao#save(T)
- */
- public void save(T entity){
- getSession().save(entity);
- }
- /* (non-Javadoc)
- * @see com.liang.ssh2.base.BaseDao#getById(java.lang.Long)
- */
- public T getById(Long id){
- if(id==null) return null;
- return (T) getSession().get(clazz, id);
- }
- /* (non-Javadoc)
- * @see com.liang.ssh2.base.BaseDao#update(T)
- */
- public void update(T entity){
- getSession().update(entity);
- }
- /* (non-Javadoc)
- * @see com.liang.ssh2.base.BaseDao#delete(java.lang.Long)
- */
- public void delete(Long id){
- if(id!=null){
- Object entity=getById(id);
- if(entity!=null){
- getSession().delete(entity);
- }
- }
- }
- /* (non-Javadoc)
- * @see com.liang.ssh2.base.BaseDao#getByIds(java.lang.Long[])
- */
- public List<T> getByIds(Long[] ids){
- if(ids==null||ids.length==0){
- return Collections.EMPTY_LIST;
- }
- return getSession().createQuery(//
- "from "+clazz.getSimpleName()+"where id in(:ids)")//
- .setParameterList("ids", ids)//
- .list();
- }
- /* (non-Javadoc)
- * @see com.liang.ssh2.base.BaseDao#findAll()
- */
- public List<T> findAll(){
- return getSession().createQuery(//
- "from "+clazz.getSimpleName())//
- .list();
- }
- /* (non-Javadoc)
- * @see com.liang.ssh2.base.BaseDao#getPage(long, java.lang.Long, com.liang.ssh2.util.QueryHelper)
- */
- public Page getPage(long currentPage,Long pageSize,QueryHelper queryHelper){
- //如果用户没有动态指定pageSize,则读取配置文件
- if(pageSize==null){
- pageSize=Configuration.getPageSize();
- }
- //获得参数
- List<Object> parameters = queryHelper.getParameters();
- Query query = getSession().createQuery(queryHelper.getQueryListHql());
- if(parameters!=null&¶meters.size()>0){
- for (int i = 0; i < parameters.size(); i++) {
- query.setParameter(i, parameters.get(i));
- }
- }
- query.setFirstResult((int) ((currentPage-1)*pageSize));
- query.setMaxResults(pageSize.intValue());
- List recordList = query.list();
- // 查询总记录数
- query = getSession().createQuery(queryHelper.getQueryCountHql()); // 注意空格!
- if (parameters != null && parameters.size() > 0) { // 设置参数
- for (int i = 0; i < parameters.size(); i++) {
- query.setParameter(i, parameters.get(i));
- }
- }
- Long recordCount = (Long) query.uniqueResult(); // 查询
- return new Page(currentPage, pageSize, recordCount, recordList);
- }
- }
- </pre><pre name="code" class="java">package com.liang.ssh2.service.impl;
- import org.springframework.stereotype.Service;
- import com.liang.ssh2.base.BaseDaoImpl;
- import com.liang.ssh2.entity.User;
- @Service
- public class UserServiceImpl extends BaseDaoImpl<User>{
- }
想偷个懒,少写个接口,也不容易啊!!!!!