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

想利用泛型抽取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>{

}

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

时间: 2024-08-03 11:24:30

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

biz处理dao层的事务

前言 正文 1.创建一个事物管理对象,该对象将连接对象绑定到当前线程 2.dao层的代码示例 3.biz层处理数据库的事务 总结 biz处理dao层的事务

解决Spring框架的Dao层改用@Repository注解,无法使用JdbcDaoSupport的问题

目的: 想改用spring框架强大的注解功能(@Repository注解)来实现自动注册dao的bean的功能(原来是在xml中配置的).改完之后,运行的时候直接报错: Error creating bean with name 'UserVODao' defined in file [D:\JSP_MyEclipse\.metadata\.me_tcat7\webapps\XYG_WEBDEV_SAMPLE\WEB-INF\classes\com\xinyiglass\springSample

系统管理模块_部门管理_改进_抽取添加与修改JSP页面中的公共代码_在显示层抽取BaseAction_合并Service层与Dao层

系统管理模块_部门管理_改进1:抽取添加与修改JSP页面中的公共代码 commons.jspf <%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%> <%@ taglib prefix="s" uri="/struts-tags" %> <meta http-equiv="Conten

Javaee的Dao层的抽取

有时候我们在实现不同功能的时候回看到很多的Dao层的增加.修改.删除.查找都很相似,修改我们将他们提取BaseDao 一.提取前 1. 提取前的LinkDao层: public interface LinkManDao { Integer findCount(DetachedCriteria detachedCriteria); List<LinkMan> findByPage(DetachedCriteria detachedCriteria, Integer startIndex, Int

为什么在SSM中的dao层不用写@Repository注解

1.  Mybatis 接口编程中dao 层接口没有注解和 为什么能被实例化为bean? 在Spring配置Mybatis的文件中我们可以看到如下代码: <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer"> <property name="basePackage" value="org.tarena.note.dao"> </property

SSH框架整合中Hibernate实现Dao层常用结构

一.疑惑 一直以来,我在使用SSH框架的时候经常会发现后者有疑虑到底使用hibernate的那种方法或者如何配置hibernate来操作数据库,经过 一段时间的学习下面我来总结一下,常用的dao层配置. 二.常用的hibernate操作dao  第一种,通过继承HibernateDaoSupport来操作 第二种,通过HibernateTemplate来操作 第三种,通过使用Hibernate的session来操作 第四种,直接写JDBC来实现数据库操作 三.四种常用方法介绍及配置 通过继承Hi

MyBatis xml和dao层接口组合使用

在这里,不再介绍Mybatis的配置. mybatis可以用xml进行数据操作,也可以在dao层用注解的方式,也可以采取xml和dao层接口组合使用的方法.显然 ,后者更加简单. 实体类Student package com.zhao.entity; /** * * @author: zhao * @time: 2016年5月31日 * * @description:学生 */ public class Student { private int stuId; private String st

Dao层和Service层设计

1.Dao接口层 public interface IBaseDao<T, ID extends Serializable>{ public abstract Serializable save(T t); /*其他接口*/ } 2.StudentDao接口层 public interface IStudentDao extends IBaseDao<Student,Serializable> { /*只有特殊的接口才在这里声明*/ } 3.BaseDao实现层 为了让BaseDa

dao层单元测试报错CONDITIONS EVALUATION REPORT

0 环境 系统:win10 编辑器:IDEA 1 正文 1.1 起因 在controller层测试 测试url时没问题的 但是我单元测试就报错 1.2 排查 因为controller层 springbootapplication启动项目没问题 说明xml文件是没问题的 可能性很大的就是dao层没映射到 重点排查一下 打算debug的 突然想起来我在springbootapplication文件下添加了mappe包的包扫描 然而dao层的单元测试 没有启动springbootapplication