BaseDAO开发及获取泛型的传输数据类型(Class)实例讲解

经常看到那些写好的项目的dao是用的泛型,就不不理解为什么,看到了这个论坛上的两个例子,粘给大家:
泛型是Java SE 1.5的新特性,泛型的本质是参数化类型,也就是说所操作的数据类型被指定为一个参数。这种参数类型可以用在类、接口和方法的创建中,分别称为泛型类、泛型接口、泛型方法。
 Java语言引入泛型的好处是安全简单。
  在Java SE 1.5之前,没有泛型的情况的下,通过对类型Object的引用来实现参数的“任意化”,“任意化”带来的缺点是要做显式的强制类型转换,而这种转换是要求开发者对实际参数类型可以预知的情况下进行的。对于强制类型转换错误的情况,编译器可能不提示错误,在运行的时候才出现异常,这是一个安全隐患。
  泛型的好处是在编译的时候检查类型安全,并且所有的强制转换都是自动和隐式的,提高代码的重用率。
  泛型在使用中还有一些规则和限制:
  1、泛型的类型参数只能是类类型(包括自定义类),不能是简单类型。
  2、同一种泛型可以对应多个版本(因为参数类型是不确定的),不同版本的泛型类实例是不兼容的。
  3、泛型的类型参数可以有多个。
4、泛型的参数类型可以使用extends语句,例如。习惯上成为“有界类型”。
  5、泛型的参数类型还可以是通配符类型。例如Class classType = Class.forName(java.lang.String);

一般在涉及DAO开发时,常用到的增删改查方法会封装到一个基类(BaseDAO),对于各个数据表的基本维护业务都需要用到增删改查等方法。

若对每张表都编写一套增删改差方法未必有些麻烦,并且不符合编码的基本准则。一般,我们可以将这些功能的所公用的部分封装为一个对象,或者是类,此类是所有DAO的基类,可以称为:BaseDAO。

由于此类接收到不同的操作对象,故需泛型的支持。

下面,我通过以下实例代码,为此知识进行展示,供大家参考

此例是基于ssh2的环境中进行搭建:


相关类:涉及到BaseDAO接口,接口实现类:BaseDAOImpl、两个数据表的操作对象及相应的接口:DAOA、DAOB、DAOAImpl、DAOBImpl


BaseDAO:接口代码,公共方法的接口类

package base;

import java.util.List;

public interface BaseDao {

	/**
	 * 保存实体
	 * 
	 * @param entity
	 */
	void save(T entity);

	/**
	 * 删除实体
	 * 
	 * @param id
	 */
	void delete(Long id);

	/**
	 * 更新实体
	 * 
	 * @param entity
	 */
	void update(T entity);

	/**
	 * 按id查询
	 * 
	 * @param id
	 * @return
	 */
	T getById(Long id);

	/**
	 * 按id查询
	 * 
	 * @param ids
	 * @return
	 */
	List getByIds(Long[] ids);

	/**
	 * 查询所有
	 * 
	 * @return
	 */
	List findAll();

}
BaseDAOImpl:公共方法的实现类

package base;

import java.lang.reflect.ParameterizedType;
import java.util.List;

import javax.annotation.Resource;

import org.hibernate.Session;
import org.hibernate.SessionFactory;

@SuppressWarnings("unchecked")
public abstract class BaseDaoImpl implements BaseDao {

	@Resource
	private SessionFactory sessionFactory;
	private Class clazz;

	public BaseDaoImpl() {
		// 使用反射技术得到T的真实类型
		ParameterizedType pt = (ParameterizedType) this.getClass().getGenericSuperclass(); // 获取当前new的对象的 泛型的父类 类型
		this.clazz = (Class) pt.getActualTypeArguments()[0]; // 获取第一个类型参数的真实类型
		System.out.println("clazz ---> " + clazz);
		
	}

	/**
	 * 获取当前可用的Session
	 * 
	 * @return
	 */
	protected Session getSession() {
		return sessionFactory.getCurrentSession();
	}

	public void save(T entity) {
		getSession().save(entity);
	}

	public void update(T entity) {
		getSession().update(entity);
	}

	public void delete(Long id) {
		Object obj = getById(id);
		if (obj != null) {
			getSession().delete(obj);
		}
	}

	public T getById(Long id) {
		return (T) getSession().get(clazz, id);
	}

	public List getByIds(Long[] ids) {
		return getSession().createQuery(//
				"FROM User WHERE id IN (:ids)")//
				.setParameterList("ids", ids)//
				.list();
	}

	public List findAll() {
		return getSession().createQuery(//
				"FROM " + clazz.getSimpleName())//
				.list();
	}

}

DAOA:vo A的DAO接口类,此类需要继承BaseDAO接口,实现公共类,另外在此可以声明自己特有的方法

package dao;

import pojo.A;
import base.BaseDao;

public interface DAOA extends BaseDao{
//...
}
DAOAImpl:vo A的DAO实现类,实现DAOA中声明的方法和BaseDAO的所以基本方法,为实现基本方法,故继承了BaseDaoImpl类

package dao.impls;

import org.springframework.stereotype.Repository;

import pojo.A;
import base.BaseDaoImpl;
import dao.DAOA;
@Repository
public class DAOAImpl extends BaseDaoImpl implements DAOA {

}

同理,DAOB同上

以此,便完成了公共方法的继承与实现机制。

当中用到了泛型机制,通过继承父类来实现泛型的数据转换:

 public class DAOAImpl extends BaseDaoImpl{}  A为vo的模型类,以此在父类中可调用实现!!

通过使用泛型T减少Dao的冗余代码,当T继承某个对象时(T extends EntityDao)限制了参数类型必须继承该对象(EntityDao),并且ClassT必须要有泛型参数(DeptDaoImpl extends ClassT),否则转换失败。

你可能感兴趣的:(SSH2,DAO模式)