答案是可以的。這裏我們接觸到JDK5.0裏面的一個新特性:泛型。
關於泛型的含義我這裏就不再解釋了。
下面我們以一個對用戶管理和新聞管理的來示範。
首先是2個POJO。我這裏只列出User POJO。
(基於註釋的Pojo)
- package com.oa;
- import javax.persistence.Column;
- import javax.persistence.Entity;
- import javax.persistence.GeneratedValue;
- import javax.persistence.GenerationType;
- import javax.persistence.Id;
- import javax.persistence.Table;
- @Entity
- @Table(name = "tb_user")
- public class User {
- @Id
- @GeneratedValue(strategy = GenerationType.IDENTITY)
- private int id;
- @Column(name = "username", length = 15)
- private String username;
- @Column(name = "password", length = 15)
- private String password;
- public int getId() {
- return id;
- }
- public void setId(int id) {
- this.id = id;
- }
- public String getUsername() {
- return username;
- }
- public void setUsername(String username) {
- this.username = username;
- }
- public String getPassword() {
- return password;
- }
- public void setPassword(String password) {
- this.password = password;
- }
- }
如果按照常規的Facade模式來設計,我們的思路是:
先創建一個UserDao的接口。
- package com.oa.dao;
- import java.util.List;
- import com.oa.User;
- public interface UserDao {
- public void save(User user);
- public void delete(int id);
- public void update(User user);
- public List<User> query();
- public User get(int id);
- }
然後實現這個接口:UserDaoImpl
- package com.oa.dao.impl;
- import java.util.List;
- import org.springframework.context.annotation.Scope;
- import org.springframework.stereotype.Repository;
- import com.oa.User;
- import com.oa.dao.MyHibernateDaoSupport;
- import com.oa.dao.UserDao;
- /**
- * 從Spring 2.0開始,引入了@Repository註解,
- * 用它來標記充當儲存庫(又稱 Data Access Object或DAO)角色或典型的類
- */
- /**
- * Spring 2.5引入了更多典型化註解(stereotype annotations): @Component、@Service和 @Controller。
- * @Component是所有受Spring管理組件的通用形式; 而@Repository、@Service和 @Controller則是@Component的細化,
- * 用來表示更具體的用例(例如,分別對應了持久化層、 服務層 和 表現層)。
- */
- //@Scope("singlton")
- @Repository("userDao")//聲明此類爲數據持久層的類
- public class UserDaoImpl extends MyHibernateDaoSupport implements UserDao {
- public void delete(int id) {
- super.getHibernateTemplate().delete(
- super.getHibernateTemplate().load(User.class, id));
- }
- public User get(int id) {
- return (User) super.getHibernateTemplate().get("from User", id);
- }
- @SuppressWarnings("unchecked")
- public List<User> query() {
- return super.getHibernateTemplate().find("from User");
- }
- public void save(User user) {
- super.getHibernateTemplate().save(user);
- }
- public void update(User user) {
- super.getHibernateTemplate().update(user);
- }
- }
持久化層完畢。
接下來的是事務層
先創建一個UserService的接口。
- package com.oa.service;
- import com.oa.User;
- public interface UserService {
- public void save(User user);
- public void update(User user);
- }
然後實現這個接口:UserServiceImpl。
在UserServiceImpl裏引用UserDao來實現業務邏輯。
- package com.oa.service.impl;
- import com.oa.User;
- import com.oa.service.UserService;
- import com.oa.dao.UserDao;
- import java.util.List;
- import org.springframework.beans.factory.annotation.Autowired;
- import org.springframework.stereotype.Service;
- /**
- * 聲明此類爲業務邏輯層的類
- * 默認bean名稱生成器會返回小寫開頭的非限定(non-qualified)類名
- * @Service
- * userServiceImpl
- */
- @Service("userService")
- public class UserServiceImpl implements UserService {
- /**
- * @Autowired
- *
- * @Autowired 註解可以用於"傳統的"setter 方法,如下例:
- * public void setUserDao(UserDAO userDao)
- {
- this.userDao = userDao;
- }
- */
- /**
- * @Resource有一個'name'屬性,缺省時,Spring 將這個值解釋爲要注射的 bean 的名字。
- * @Resource(name="userDao")
- */
- @Autowired // or @Resource(name="userDao")
- private UserDao userDao;
- public void save(User user) {
- userDao.save(user);
- }
- public void update(User user) {
- userDao.update(user);
- }
- }
按照上面的模式:新聞管理也這麼寫一遍。
重複的工作使得我們覺得好煩。
這個時候是泛型出場的時候了。
基於Facade的設計模式,dao和service還是要的。 這裏我們就要設計一個公共的Dao.. 我們稱之爲:GenericDao
- package com.oa.dao;
- import java.io.Serializable;
- import java.util.*;
- /**
- * *
- *
- * @param <T>
- * 泛型,指實體類 type
- * @param <PK>
- * 泛型,指實體類主鍵的數據類型,如Integer,Long
- */
- public interface GenericDao<T, PK> {
- /**
- * 保存指定實體類
- *
- * @param entityobj
- * 實體類
- */
- public void save(T entity);
- /**
- * 刪除指定實體
- *
- * @param entityobj
- * 實體類
- */
- public void delete(T entity);
- /** *
- * 刪除實體
- * @param entityClass 實體類名
- * @param id 實體的ID
- */
- public void deleteById(Class<T> entityClass,PK id);
- /**
- * 更新或保存指定實體
- *
- * @param entity 實體類
- */
- public void saveorupdate(T entity);
- /** *
- * 更新實體
- * 可用於添加、修改、刪除操作
- * @param hql 更新的HQL語句
- * @param params 參數,可有項目或多項目,代替Hql中的"?"號
- */
- public void update(final String hql,final Object[] params);
- /**
- * 模糊查詢指定條件對象集合 <br>
- * 用法:可以實例化一個空的T對象,需要查詢某個字段,就set該字段的條件然後調用本方法<br>
- * 缺點:目前測試貌似只能支持String的模糊查詢,雖然有辦法重寫,但沒必要,其他用HQL<br>
- *
- * @param entity
- * 條件實體
- * @return 結合
- */
- public List<T> findByExample(T entity);
- /**
- * 獲取所有實體集合
- *
- * @param entityClass
- * 實體
- * @return 集合
- */
- public List<T> findAll(Class<T> entityClass);
- public List<T> findAll(Class<T> entityClass,String hql,Object[] params,int start, int limit);
- /**
- * 查找指定PK實體類對象
- *
- * @param entityClass
- * 實體Class
- * @param id
- * 實體PK
- * @return 實體對象
- */
- public T findById(Class<T> entityClass, PK id);
- /** *
- * 按HQL條件查詢列表
- * @param hql 查詢語句,支持連接查詢和多條件查詢
- * @param params 參數數組,代替hql中的"?"號
- * @return 結果集List
- */
- public List<T> findByHql(String hql,Object[] params);
- /**
- * 查找指定屬性的實體集合
- *
- * @param entityClass
- * 實體
- * @param propertyName
- * 屬性名
- * @param value
- * 條件
- * @return 實體集合
- */
- public List<T> findByProperty(Class<T> entityClass, String propertyName,Object value);
- /**
- * 查詢指定HQL語句的分頁數據集合
- *
- * @param hsql
- * HQL語句
- * @param start
- * 開始記錄號
- * @param limit
- * 最大記錄號
- * @return 分頁數據集合
- * @throws Exception
- * 拋出異常
- */
- public List<T> findByPage(Class<T> entityClass,int start,int limit) ;
- /**
- * 獲得總記錄數
- */
- public T getTotalCount(Class<T> entityClass);
- public T getPageCount(String hql,Object[] params);
- }
看到,我們不再是具體的User , News
。。而是用 T 來取代實體。
因爲我這個是基於 註解的,所以附上MyHibernateDaoSupport的代碼。
- package com.oa.dao;
- import javax.annotation.Resource;
- import org.hibernate.SessionFactory;
- import org.springframework.orm.hibernate3.support.HibernateDaoSupport;
- /**
- * 我們之所以要改寫
- * HibernateDaoSupport,是因我爲,我們要爲DAO層的類注入SessionFactory這個屬性。
- * 以後,我們開發的DAO類,就可以直接重用這個MyHibernateDaoSupport了。
- * 其實,這樣做是相當於配置文件方式的代碼:
- * <bean id="userDao" class="com.oa.dao.UserDaoImpl">
- * <property
- * name="sessionFactory" ref="sessionFactory"/>
- * </bean>
- *
- * @author Administrator
- *
- */
- public class MyHibernateDaoSupport extends HibernateDaoSupport {
- @Resource(name="sessionFactory") //爲父類HibernateDaoSupport注入sessionFactory的值
- public void setSuperSessionFactory(SessionFactory sessionFactory){
- super.setSessionFactory(sessionFactory);
- }
- }
到現在位置genericdao的接口有了,也就是我們要做什麼。。現在就是實現它,就是怎麼做。
GenericDaoImpl 代碼:
- package com.oa.dao.impl;
- import java.io.Serializable;
- import java.util.List;
- import org.hibernate.Query;
- import org.springframework.stereotype.Repository;
- import com.oa.dao.GenericDao;
- import com.oa.dao.MyHibernateDaoSupport;
- @SuppressWarnings("unchecked")
- @Repository("genericDao") //聲明此類爲數據持久層的類
- public class GenericDaoImpl<T, PK extends Serializable> extends
- MyHibernateDaoSupport implements GenericDao<T, PK> {
- public void delete(T entity) {
- super.getHibernateTemplate().delete(entity);
- }
- public void deleteById(Class entityClass, PK id) {
- super.getHibernateTemplate().delete(findById(entityClass, id));
- }
- public void save(T entity) {
- super.getHibernateTemplate().save(entity);
- }
- public void saveorupdate(T entity) {
- super.getHibernateTemplate().saveOrUpdate(entity);
- }
- public void update(String hql, Object[] params) {
- Query query = super.getSession().createQuery(hql);
- for(int i=0; i<params.length; i++){
- query.setParameter(i, params[i]);
- }
- query.executeUpdate();
- }
- public List<T> findAll(Class entityClass) {
- return super.getHibernateTemplate().loadAll(entityClass);
- }
- public List<T> findAll(Class entityClass, String hql, Object[] params,int start, int limit) {
- Query query = super.getSession().createQuery(hql);
- if(params!=null&¶ms.length>0){
- for(int i = 0;i<params.length;i++){
- query.setParameter(i, params[i]);
- }
- }
- if(start!=0&&limit!=0){
- query.setFirstResult(start).setMaxResults(limit);
- }
- return query.list();
- }
- public List<T> findByExample(T entity) {
- return super.getHibernateTemplate().findByExample(entity);
- }
- public List<T> findByHql(String hql, Object[] params) {
- Query query = super.getSession().createQuery(hql);
- if(null!= params && params.length>0){
- for(int i = 0; i<params.length;i++){
- query.setParameter(i, params[i]);
- }
- }
- return query.list();
- }
- public T findById(Class entityClass, PK id) {
- return (T)super.getHibernateTemplate().get(entityClass, id);
- }
- public List<T> findByProperty(Class entityClass, String propertyName,Object value) {
- String queryString = "from "+entityClass.getName()+ " as model where model." + propertyName + "=?";
- return super.getHibernateTemplate().find(queryString, value);
- }
- //分頁使用
- public List<T> findByPage(Class<T> entityClass,int start,int limit) {
- Query query=super.getSession().createQuery("select o from "+entityClass.getName()+" o");
- query.setFirstResult(start).setMaxResults(limit);
- return query.list();
- }
- public T getTotalCount(Class entityClass) {
- return (T)super.getSession().createQuery("select count(o) from "+entityClass.getName()+" o").uniqueResult();
- }
- public T getPageCount(String hql, Object[] params) {
- Query query = super.getSession().createQuery(hql);
- if(null!= params && params.length>0){
- for(int i = 0; i<params.length;i++){
- query.setParameter(i, params[i]);
- }
- }
- return (T)query.list();
- }
- }
至此 泛型就告一個段落。
接下來日子就好過了。
我們不是有user news 等等一系列的curd管理。
以User爲例子;
定義一個user的接口,
UserDao.Java
- package com.oa.dao;
- import com.oa.User;
- public interface UserDao extends GenericDao<User, Integer> {
- public int login(User user);
- //其他的方法的
- }
- 然後就是實現它 UserDaoImpl
- package com.oa.dao.impl;
- import com.oa.User;
- import com.oa.dao.UserDao;
- public class UserDaoImpl extends GenericDaoImpl<User, Integer> implements UserDao {
- public int login(User user){
- //登陸判斷的方法
- return XX;
- };
- //其他的方法的實現
- }
持久化層就是這麼多了。
下面進入業務邏輯層,依然是先定義一個接口。
- package com.oa.service;
- import com.oa.User;
- public interface UserService {
- public void save(User user);
- public void update(User user);
- public int login(User user);
- //其他的方法
- }
接下來是實現
- package com.oa.service.impl;
- import com.oa.User;
- import com.oa.dao. UserDao;
- import com.oa.service.TestUserService;
- public class UserService implements UserService {
- private UserDao UserDao;
- public void save(User user) {
- UserDao.save(user);
- }
- public void updasaveorupdatete(User user) {
- UserDao.saveorupdate(user);
- }
- public int login(User user) {
- return UserDao.login(user);
- }
- //其他的方法。。。。
- }
Ok。。到現在我們就利用泛型dao來設計就完畢了
兩者相對比,發現dao層的代碼可以複用,少了不少。
對於大型管理系統,效果更明顯。