2、利用反射技术得到泛型类型,实现对实体添删改查操作进行代码重用设计

一、定义BaseDao接口

    将对所有实体都进行的增删改查操作提取到一个接口里面,可以提高代码的可重用性

BaseDao<T> 接口:

package com.charlie.shop.dao.base;

import java.util.List;

public interface BaseDao<T> {
	/**
	 * 添加 一个对象
	 * 
	 * @param t  实体对象
	 */
	public void save(T t);

	/**
	 * 删除一个对象
	 * 
	 * @param id  实体id号
	 */
	public void delete(Long...ids);

	/**
	 * 更新一个对象
	 * 
	 * @param t  实体对象
	 */
	public void update(T t);

	/**
	 * 根据id号查询一个对象
	 * 
	 * @param id  实体id号
	 * @return    返回一个实体对象,查找失败则返回null
	 */
	public T getById(Long id);

	/**
	 * 根据id数组查询对象
	 * 
	 * @param ids  id数组
	 * @return     实体列表
	 */
	public List<T> getByIds(Long[] ids);

	/**
	 * 查询所有
	 * 
	 * @return
	 */
	public List<T> findAll();
}


二、定义抽象BaseDaoImpl类去实现BaseDao接口

要实现该接口中的方法时,有一个关键的问题需要解决,那就是必须获得参数类型T的真正类型信息,即T对应的Class对象。

比如,在实现getById(Long id)方法时,必然需要用到Hibernate API中的

Session.get(Class clazz,Serializable id)方法,这个方法的第一个参数就是需要一个Class对象;

另外,在拼接HQL语句时,也需要用到实体类的类名,这也需要通过其Class对象来获得。

那么,该如何获得T的Class对象呢?

重点关注JDK API中的以下方法:


getClass

public final Class<?> getClass()
返回此 Object 的运行时类。返回的 Class 对象是由所表示类的static synchronized 方法锁定的对象。

实际结果类型是 Class<? extends |X|>,其中|X| 表示清除表达式中的静态类型,该表达式调用getClass 例如,以下代码片段中不需要强制转换:

Number n = 0;
Class<? extends Number> c = n.getClass();

返回:
表示此对象运行时类的 Class 对象。

getGenericSuperclass

public Type getGenericSuperclass()
返回表示此 Class 所表示的实体(类、接口、基本类型或 void)的直接超类的 Type

如果超类是参数化类型,则返回的 Type 对象必须准确反映源代码中所使用的实际类型参数。如果以前未曾创建表示超类的参数化类型,则创建这个类型。有关参数化类型创建过程的语义,请参阅 ParameterizedType 声明。如果此 Class 表示 Object 类、接口、基本类型或 void,则返回 null。如果此对象表示一个数组类,则返回表示 Object 类的 Class 对象。

返回:
此对象所表示的类的超类
抛出:
GenericSignatureFormatError - 如果常规类签名不符合 Java Virtual Machine Specification, 3rd edition 规定的格式
TypeNotPresentException - 如果常规超类引用不存在的类型声明
MalformedParameterizedTypeException - 如果常规超类引用的参数化类型由于某种原因无法实例化

getActualTypeArguments

Type[] getActualTypeArguments()
返回表示此类型实际类型参数的 Type 对象的数组。

注意,在某些情况下,返回的数组为空。如果此类型表示嵌套在参数化类型中的非参数化类型,则会发生这种情况。

返回:
表示此类型的实际类型参数的 Type 对象的数组
抛出:
TypeNotPresentException - 如果任何实际类型参数引用不存在的类型声明
MalformedParameterizedTypeException - 如果任何实际类型参数引用参数化类型,该类型出于某种原因无法被实例化


BaseDaoImpl.java

package com.charlie.shop.dao.base;

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

import javax.annotation.Resource;

import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.springframework.transaction.annotation.Transactional;

@SuppressWarnings("unchecked")
@Transactional
public abstract class BaseDaoImpl<T> implements BaseDao<T> {
	@Resource
	// 注入父类的属性,父类可以不用托管,只要子类有托管即可
	private SessionFactory sessionFactory;
	// 泛型T的真实类型
	protected Class<?> clazz = getGenericType();

	@Override
	public void save(T t) {
		getSession().save(t);
	}

	@Override
	public void delete(Long... ids) {
		for (Long id : ids) {
			// 先取出对象
			Object obj = getSession().get(clazz, id);
			if (obj != null) {
				getSession().delete(obj);
			}
		}
	}

	@Override
	public void update(T t) {
		if (t == null) {
			return;
		} else {
			getSession().update(t);
		}
	}

	@Override
	public T getById(Long id) {
		if (id == null)
			return null;
		return (T) getSession().get(clazz, id);
	}

	@Override
	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();
	}

	@Override
	public List<T> findAll() {
		return getSession().createQuery(//
				"FROM " + clazz.getSimpleName())//
				.list();
	}

	/**
	 * 返回一个会话 声明为protected修饰,可以让子类直接用 因为用到spring
	 * 事务管理,所以要用getCurrentSession,不用openSession
	 */
	protected Session getSession() {
		return sessionFactory.getCurrentSession();
	}

	/**
	 * 获取泛型类型
	 */
	protected Class<?> getGenericType() {
		ParameterizedType pt = (ParameterizedType) this.getClass()
				.getGenericSuperclass();
		return (Class<?>) pt.getActualTypeArguments()[0];
	}
}



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值