想利用泛型抽取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是不用放的

当启动server时会报错: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>{ }

想偷个懒。少写个接口。也不easy啊!!!!!

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

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

    解决Spring框架的Dao层改用@Repository注解,无法使用JdbcDaoSupport的问题 Alternatively, create an own implementation of ...

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

    系统管理模块_部门管理_改进1:抽取添加与修改JSP页面中的公共代码 commons.jspf <%@ page language="java" import="j ...

  3. Javaee的Dao层的抽取

    有时候我们在实现不同功能的时候回看到很多的Dao层的增加.修改.删除.查找都很相似,修改我们将他们提取BaseDao 一.提取前 1. 提取前的LinkDao层: public interface L ...

  4. Mybatis Dao层注解及XML组合Dao的开发方式

    mybatis可以用xml进行数据操作,也可以在dao层用注解的方式,也可以采取xml和dao层接口组合使用的方法.显然 ,后者更加简单. 实体类Student   package com.zhao. ...

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

    1.  Mybatis 接口编程中dao 层接口没有注解和 为什么能被实例化为bean? 在Spring配置Mybatis的文件中我们可以看到如下代码: <bean class="or ...

  6. 基于注解的Spring AOP拦截含有泛型的DAO

    出错场景 1.抽象类BaseDao public abstract class BaseDao<T> { public BaseDao() { entityClass = (Class&l ...

  7. 通过对DAO层的封装减少数据库操作的代码量

     在学框架之前,写项目时总是要花大量的时间去写数据库操作层代码,这样会大大降低我们的效率,为了解决这个问题,我花了两天时间利用反射机制和泛型将DAO层进行了封装,这样我们只需要写sql语句,不需要再写 ...

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

    一.疑惑 一直以来,我在使用SSH框架的时候经常会发现后者有疑虑到底使用hibernate的那种方法或者如何配置hibernate来操作数据库,经过 一段时间的学习下面我来总结一下,常用的dao层配置 ...

  9. Dao层和Service层设计

    1.Dao接口层 public interface IBaseDao<T, ID extends Serializable>{ public abstract Serializable s ...

随机推荐

  1. Spark on Mesos: 搭建Mesos的一些问题

    资源管理系统 Spark可以搭建在Mesos上或YARN上,两个都是资源管理系统.了解资源管理系统的话,可以先参看以下几篇文章: 浅谈Borg/YARN/Mesos/Torca/Corona一类系统 ...

  2. Effective C++_笔记_条款04_确定对象被使用之前已先被初始化

    (整理自Effctive C++,转载请注明.整理者:华科小涛@http://www.cnblogs.com/hust-ghtao/) 读取未初始化的值会导致不确定的行为.在某些平台上,仅仅只是读取为 ...

  3. ASP.NET - 使用 Eval() 绑定数据时使用 三元运算符

    ASP.NET邦定数据“<%#Eval("Sex")%>”运用三元运算符: <%#(Eval("Sex", "{0}") ...

  4. POJ 2632 Crashing Robots(较为繁琐的模拟)

    题目链接:http://poj.org/problem?id=2632 题目大意:题意简单,N个机器人在一个A*B的网格上运动,告诉你机器人的起始位置和对它的具体操作,输出结果: 1.Robot i ...

  5. 用Stack实现对多线程的管理范例

    多线程就是并发技术,当线程数量超过一定数量时,系统响应就会变慢,所以就必须对线程数量进行控制,那么采用哪种控制方法呢?采用Stack类模仿堆栈,之所以说是模仿,就是因为Stack类毕竟不是真实的堆栈, ...

  6. 王立平--android中的anim(动画)

    简单有用步骤: 1.新建anim目录. 2.在anim下新建xml文件, 3.在xml下编写自己须要动画. 简单样例: 给Imageview加入动画 public class MainActivity ...

  7. ExtJs4 笔记(3) Ext.Ajax 对ajax的支持

    本篇主要介绍一下ExtJs常用的几个对JS语法的扩展支持,包括Ajax封装,函数事件操作封装,还有扩展的常用函数等.Ajax服务端交互式操作是提交到.NET MVC.后续服务端交互都采用这一方式实现. ...

  8. 9月mob(ShareSDK)活动预告,这个秋天非常热

    9月秋天来临,广州的天气依旧非常热,广州的活动氛围更热~ 先有GMGC B2B对接会在广州创新谷,再有上方网TFC全球移动游戏开发人员大会来袭,游戏圈的火越烧越旺,成都GMGDC全球移动游戏开发人员大 ...

  9. 一个网友写的栈,问为啥不能迭代。具有__iter__ 和next方法的对象叫迭代器-七七巴巴黄页网

    一个网友写的栈,问为啥不能迭代.具有__iter__ 和next方法的对象叫迭代器-七七巴巴黄页网 一个网友写的栈,问为啥不能迭代.具有__iter__ 和next方法的对象叫迭代器 python视频 ...

  10. openwrt 3g模块上网

    硬件环境:     开发板为RT5053F        3G模块为中兴 MC2176 电信版 以下是操作步骤 加入VID .PID VID . PID 的获取方法是 将设备插入电脑在linux下执行 ...