DAO泛型使用
来源:互联网 发布:有做标书软件 编辑:程序博客网 时间:2024/06/15 01:03
这是一个来自CaveatEmptor实例应用,在JDK5.0下实现的DAO模式. 这个模式在Java Persistence With Hibernate里面也有讲到. 另外有两个链接,可能会对你有用,Sessions and transactions 和Open Session in View.
这次的DAO例子是基于接口的.很多工具, 像Hibernate已经提供了数据库的便携访问,所以我们不是为持久层的轻便而设计接口. 然而, DAO接口在较为复杂的应用中更有意义, 当有几个持久化服务被封装到一个持久层的时候, 我想在很多情况下你应该直接使用Hibernate或者JPA, 而使用外加的DAO层最好的理由是为了实现更高的抽象化(例如:定义方法名getMaximumBid()而不是无数次地重复 session.createQuery(...)).
DAO接口
每一个持久化实体我用一个接口, 另外还有一个定义了泛型CRUD(增,删,改,查)操作的顶层接口.
- public interface GenericDAO<T, IDextends Serializable> {
- T findById(ID id, boolean lock);
- List<T> findAll();
- List<T> findByExample(T exampleInstance);
- T makePersistent(T entity);
- void makeTransient(T entity);
- }
public interface GenericDAO<T, ID extends Serializable> {
T findById(ID id, boolean lock);
List<T> findAll();
List<T> findByExample(T exampleInstance);
T makePersistent(T entity);
void makeTransient(T entity); }
你已经可以看到这将是一个"面向状态",具有像makePersistent()和makeTransient()方法的数据访问API.而且, 你必须提供一个类型和一个标识参数(这里指的是持久化对象的标识符-Object Identifier),对于大多数的持久化解决方案,标识符类型必须是Serializable的.
以下是提供了类型参数关于某一实体的DAO接口,它继承了泛型接口:
- public interface ItemDAOextends GenericDAO<Item, Long> {
- public staticfinal String QUERY_MAXBID = "ItemDAO.QUERY_MAXBID";
- public staticfinal String QUERY_MINBID = "ItemDAO.QUERY_MINBID";
- Bid getMaxBid(Long itemId);
- Bid getMinBid(Long itemId);
- }
public interface ItemDAO extends GenericDAO<Item, Long> {
public static final String QUERY_MAXBID = "ItemDAO.QUERY_MAXBID";
public static final String QUERY_MINBID = "ItemDAO.QUERY_MINBID";
Bid getMaxBid(Long itemId); Bid getMinBid(Long itemId);
}
基本上我们把通用的CRUD操作和具体业务相关的数据访问操作都分开了.(暂且不用理上面接口中的常量,如果使用Annotation,他们将会 很有用.)然而,即使对于具体某个实体你只需要这些通用的CRUD操作,你也应该为它单独写一个接口.即使这个接口是空的.在你的controller code(控制器/业务代码)中使用一个具体的DAO是很重要的.否则当你要为这个实体引入具体的数据访问操作的时候,你将面临重构的问题.
一个Hibernate的(泛型DAO)实现
任何一个"可管理状态"的持久化服务都可以实现上面的泛型接口.首先,我们用Hibernate来实现这些泛型CRUD
- public abstractclass GenericHibernateDAO<T, ID extends Serializable>
- implements GenericDAO<T, ID> {
- private Class<T> persistentClass;
- private Session session;
- public GenericHibernateDAO() {
- this.persistentClass = (Class<T>) ((ParameterizedType) getClass()
- .getGenericSuperclass()).getActualTypeArguments()[0];
- }
- @SuppressWarnings("unchecked")
- public void setSession(Session s) {
- this.session = s;
- }
- protected Session getSession() {
- if (session == null)
- throw new IllegalStateException("Session has not been set on DAO before usage");
- return session;
- }
- public Class<T> getPersistentClass() {
- return persistentClass;
- }
- @SuppressWarnings("unchecked")
- public T findById(ID id, boolean lock) {
- T entity;
- if (lock)
- entity = (T) getSession().load(getPersistentClass(), id, LockMode.UPGRADE);
- else
- entity = (T) getSession().load(getPersistentClass(), id);
- return entity;
- }
- @SuppressWarnings("unchecked")
- public List<T> findAll() {
- return findByCriteria();
- }
- @SuppressWarnings("unchecked")
- public List<T> findByExample(T exampleInstance, String[] excludeProperty) {
- Criteria crit = getSession().createCriteria(getPersistentClass());
- Example example = Example.create(exampleInstance);
- for (String exclude : excludeProperty) {
- example.excludeProperty(exclude);
- }
- crit.add(example);
- return crit.list();
- }
- @SuppressWarnings("unchecked")
- public T makePersistent(T entity) {
- getSession().saveOrUpdate(entity);
- return entity;
- }
- public void makeTransient(T entity) {
- getSession().delete(entity);
- }
- public void flush() {
- getSession().flush();
- }
- public void clear() {
- getSession().clear();
- }
- /**
- * Use this inside subclasses as a convenience method.
- */
- @SuppressWarnings("unchecked")
- protected List<T> findByCriteria(Criterion... criterion) {
- Criteria crit = getSession().createCriteria(getPersistentClass());
- for (Criterion c : criterion) {
- crit.add(c);
- }
- return crit.list();
- }
- }
public abstract class GenericHibernateDAO<T, ID extends Serializable>
implements GenericDAO<T, ID> {
private Class<T> persistentClass;
private Session session;
public GenericHibernateDAO() {
this.persistentClass = (Class<T>) ((ParameterizedType) getClass() .getGenericSuperclass()).getActualTypeArguments()[0];
}
@SuppressWarnings("unchecked")
public void setSession(Session s) {
this.session = s;
}
protected Session getSession() {
if (session == null) throw new IllegalStateException("Session has not been set on DAO before usage");
return session; }
public Class<T> getPersistentClass() {
return persistentClass;
}
@SuppressWarnings("unchecked")
public T findById(ID id, boolean lock) {
T entity;
if (lock) entity = (T) getSession().load(getPersistentClass(), id, LockMode.UPGRADE);
else entity = (T) getSession().load(getPersistentClass(), id);
return entity;
}
@SuppressWarnings("unchecked") public List<T> findAll() {
return findByCriteria();
}
@SuppressWarnings("unchecked")
public List<T> findByExample(T exampleInstance, String[] excludeProperty) {
Criteria crit = getSession().createCriteria(getPersistentClass());
Example example = Example.create(exampleInstance);
for (String exclude : excludeProperty) {
example.excludeProperty(exclude);
}
crit.add(example);
return crit.list();
}
@SuppressWarnings("unchecked")
public T makePersistent(T entity) {
getSession().saveOrUpdate(entity);
return entity;
}
public void makeTransient(T entity) {
getSession().delete(entity);
} public void flush() {
getSession().flush();
}
public void clear() {
getSession().clear();
}
/**
* Use this inside subclasses as a convenience method.
*/
@SuppressWarnings("unchecked")
protected List<T> findByCriteria(Criterion... criterion) {
Criteria crit = getSession().createCriteria(getPersistentClass());
for (Criterion c : criterion) {
crit.add(c);
}
return crit.list();
} }
在这个实现里面有几个有趣的东西. 第一,很明显它需要一个Sesssion来支撑,并且为这个Session提供了Setter注入.也可以用构造方法注入.你怎么设置Session或者 这个Session的作用域(Scope,在这里应该是指Session的生命周期,接下来将它翻译作"生命周期"),都跟具体的DAO实现无关.DAO 不应该控制事务或者Session的生命周期.
我们需要禁止一些未检查转换(unchecked casts)编译时警告.因为Hibernate的接口是基于JDK1.4的.接下来是泛型CRUD操作的实现,很简单,最后一个方法(设计得)很好,它 用了另一个JDK5.0的新特性-varargs(不定参数),它帮助我们在具体实体DAO里面创建Criteria查询.下面是一个继承了用 Hibernate实现的泛型DAO的具体DAO例子:
- public class ItemDAOHibernate
- extends GenericHibernateDAO<Item, Long>
- implements ItemDAO {
- public Bid getMaxBid(Long itemId) {
- Query q = getSession().getNamedQuery(ItemDAO.QUERY_MAXBID);
- q.setParameter("itemid", itemId);
- return (Bid) q.uniqueResult();
- }
- public Bid getMinBid(Long itemId) {
- Query q = getSession().getNamedQuery(ItemDAO.QUERY_MINBID);
- q.setParameter("itemid", itemId);
- return (Bid) q.uniqueResult();
- }
- }
public class ItemDAOHibernate extends GenericHibernateDAO<Item, Long> implements ItemDAO { public Bid getMaxBid(Long itemId) { Query q = getSession().getNamedQuery(ItemDAO.QUERY_MAXBID); q.setParameter("itemid", itemId); return (Bid) q.uniqueResult(); } public Bid getMinBid(Long itemId) { Query q = getSession().getNamedQuery(ItemDAO.QUERY_MINBID); q.setParameter("itemid", itemId); return (Bid) q.uniqueResult(); } }
下面是另外一个使用超类中具有不定参数的findByCriteria()方法的例子:
- public class CategoryDAOHibernate
- extends GenericHibernateDAO<Category, Long>
- implements CategoryDAO {
- public Collection<Category> findAll(boolean onlyRootCategories) {
- if (onlyRootCategories)
- return findByCriteria( Expression.isNull("parent") );
- else
- return findAll();
- }
- }
public class CategoryDAOHibernate extends GenericHibernateDAO<Category, Long> implements CategoryDAO { public Collection<Category> findAll(boolean onlyRootCategories) { if (onlyRootCategories) return findByCriteria( Expression.isNull("parent") ); else return findAll(); } }
为DAO准备工厂
- DAO泛型使用
- 解决SSh中公共Dao使用泛型且Dao层无其他Dao,Service直接继承公共Dao,部署到tomcat可能会出现的错误。
- 不要重复DAO!使用Hibernate 和Spring AOP 构建泛型类型安全的DAO
- 不要重复DAO!使用Hibernate 和Spring AOP 构建泛型类型安全的DAO
- 不要重复 DAO! 使用 Hibernate 和 Spring AOP 构建泛型类型安全的 DAO
- 使用泛形定义DAO
- DAO泛型设计
- 使用AOP实现类型安全的泛型DAO
- 使用getGenericSuperclass()和getActualTypeArguments()将DAO做成泛型
- 使用getGenericSuperclass()和getActualTypeArguments()将DAO做成泛型
- 使用getGenericSuperclass()和getActualTypeArguments()将DAO做成泛型
- 使用getGenericSuperclass()和getActualTypeArguments()将DAO做成泛型
- 使用getGenericSuperclass()和getActualTypeArguments()将DAO做成泛型
- 使用getGenericSuperclass()和getActualTypeArguments()将DAO做成泛型
- 使用getGenericSuperclass()和getActualTypeArguments()将DAO做成泛型
- 使用泛型定义一个可重用的Dao
- DAO层使用泛型的两种方式
- DAO层使用泛型的两种方式
- 菜单处理API函数(转)
- WINDOW 7 安装AHCI驱动的方法和简单测试
- 汇编语言冒泡排序法
- Windows Socket 网络编程(二) —— 套接字编程原理
- isNaN
- DAO泛型使用
- 学习的乐趣
- 学习编程语言
- 文件操作之:fstat、stat和lstat 区别
- 开始博客
- 面试后的反思
- 2010.1.4 高级分页查询和session加强
- 日记一则
- atl键盘钩子函数用法