利用泛型抽取Dao层,加事务注解问题(java.lang.Class cannot be cast to java.lang.reflect.ParameterizedType)

来源:互联网 发布:苹果电脑降价规律知乎 编辑:程序博客网 时间:2024/06/05 01:01

想利用泛型抽取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>{@Resourceprivate 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;@Servicepublic 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>{@Resourceprivate 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;@Servicepublic class UserServiceImpl extends BaseDaoImpl<User>{}

想偷个懒,少写个接口,也不容易啊!!!!!










0 0