我的BaseDAO如下:

java 代码
  1. public class BaseDAO   
  2. {   
  3.        
  4.     Session session;   
  5.            
  6.        
  7.     /**  
  8.      * @author   insKy  
  9.      * @time     2007-6-17  下午03:06:17  
  10.      * @version  1.0  
  11.      * @param t  
  12.      */  
  13.        
  14.   
  15.         public void create (T t) {   
  16.          try {   
  17.              session = SessionFactory.getSession();   
  18.              Transaction tx = session.beginTransaction();   
  19.                          session.save( t );   
  20.   
  21.              session.flush();   
  22.              tx.commit();   
  23.                     }catch(HibernateException e){   
  24.                 throw e;   
  25.             }finally{   
  26.           }   
  27.     }   
  28.     //update delete操作类似 此处代码略     
  29.     public void update (T t)   
  30.     public void delete(T t)   
  31. }  

 

其余Dao继承这个BaseDAO:

java 代码
  1. public class ColumnsDAO extends BaseDAO{   
  2.        
  3. //某些操作。。。  此处不显式调用父类的creat函数   
  4. }  
ColumnsAction中调用ColumnsDAO的create函数完成增加操作
  
然而Dao中出现事务操作是不合适的,所以这里想分出BO层处理session以及事务的处理,修改完后的BaseBO应该大体如下:
java 代码
  1. public void create (T t) {   
  2.          try {   
  3.              session.save( t );   
  4.               }catch(HibernateException e){   
  5.                 throw e;   
  6.             }finally{   
  7.           }   
  8.     }  

我的问题是

1,对应的BO应该如何处理?BaseDAO中的session应该如何获取?BO中如何传递过来?(没用Spring之用到Struts+Hibernate)session的获取是SessionFactory通过ThreadLocal获取的
//看了别人的程序,感觉如果用Spring来管理,不会遇到这些问题,这里没用Spring改如何来最好的管理session的传递?

2,是否也应该写一个BaseBO来对应处理BaseDAO中的各个操作以避免每个BO中处理crud操作?
请各位指教

评论
zzm_fly2004 2008-03-30
不知道可以不可以用类似与sping的opensessioninview的方式,在过滤器中打开session,把这个session用ThreadLocal保存起来,在本次请求方法内都任何地方都可以使用!具体实现可能大家都会了,这里就只说一下思路,呵呵,不知道可以否!!!!
kakaluyi 2008-03-28
用动态代理 在你的getlist的方法用动态代理包装下,加入事务
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

import org.hibernate.*

import com.strutslet.demo.service.SystemException;

public final class TransactionWrapper {

/**
* 装饰原始的业务代表对象,返回一个与业务代表对象有相同接口的代理对象
*/
public static Object decorate(Object delegate) {
return Proxy.newProxyInstance(delegate.getClass().getClassLoader(),
delegate.getClass().getInterfaces(), new XAWrapperHandler(
delegate));
}

//动态代理技术
static final class XAWrapperHandler implements InvocationHandler {
private final Object delegate;

XAWrapperHandler(Object delegate) {
this.delegate = delegate;
}

//简单起见,包装业务代表对象所有的业务方法
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
Object result = null;
session = SessionFactory.getSession();
try {
//开始一个事务
Transaction tx = session.beginTransaction();
//调用原始业务对象的业务方法
result = method.invoke(delegate, args);
session.flush();
tx.commit();
} catch (Throwable t) {
//回滚
ta.rollback();
throw new SystemException(t);
}

return result;
}
}
}
bo层事务就不用写了直接写个工厂,return
TransactionWrapper.decorate(new ColumnsDao())
这样就生成把事务封装进去的Dao了,如果不用事务也行,工厂类直接返回不事务处理的dao,我觉的可行
cindy_taozhiang 2008-03-28
晕掉. 楼上的在做什么

看的让我茫然了. 难道非Spring不行了?
yl3118436 2007-07-25
<html><head><title>2222222</title></head><body>123123</body></html>
yl3118436 2007-07-25
public  List getColList1(){    
         session = SessionFactory.getSession();    
         Transaction tx = session.beginTransaction();    
         colDao = new ColumnsDAO(session);    
         try {    
             List colList = new ArrayList();    
             colList = colDao.getColList1();    
             tx.commit();    
             return colList;    
          }catch(HibernateException e){    
           throw e;    
          }finally{    
          }    
     }
yl3118436 2007-07-25
Session session;
ColumnsDAO colDao;
public List getColList1(){ session = SessionFactory.getSession(); Transaction tx = session.beginTransaction();
colDao = new ColumnsDAO(session);
try { List colList = new ArrayList();
colList = colDao.getColList1();
tx.commit();
return colList;
}catch(HibernateException e){
throw e;
}finally{
}
}
yl3118436 2007-07-25
Session session;
ColumnsDAO colDao;
public List getColList1(){
session = SessionFactory.getSession();
Transaction tx = session.beginTransaction();
colDao = new ColumnsDAO(session);
try {
List colList = new ArrayList();
colList = colDao.getColList1();
tx.commit();
return colList;
}catch(HibernateException e){
throw e;
}finally{
}
}
kafka0102 2007-07-20
johnl 写道
动态代理如何?


简单的情况下可行。可以对Service做动态代理,统一管理事务的开启和关闭(诚如Spring的AOP实现)。然后通过工厂模式向上提供访问Service的接口。
kafka0102 2007-07-20
我想楼主真的应该用用Spring。在传统的三层架构下,DAO中的操作应该是单元性的;也就说,一个DAO对应一个领域对象(在事务脚本中就是一个DAO对应一个DTO)。而业务层的领域服务(似乎大家也称为业务对象)并不是和DAO一一对应的,因此会出现一个Service方法中包含多个DAO操作。因此,事务控制不应该在DAO层而是在Service层。但是,事务管理本身是与业务无关的横切性功能,因此使用Spring的声明式事务管理是很好的选择。在没有Spring的情况下,可以自己写一个简单的事务管理工具(但这样也是要代码耦合的,但比起在Service调用Hibernate代码要好很多)。如果是web程序,可以考虑Open Session in View,这样就是每个web请求一个事务了,也不用将事务代码耦合在Service中。
johnl 2007-07-20
动态代理如何?
insky 2007-07-06

我现在修改后的Dao中完全不包含事务处理操作    如下ColumnsDAO中某一个函数

ColumnsDAO:

 
java 代码
  1. public class ColumnsDAO extends BaseDAO{   
  2.      Session session;   
  3.   
  4.      public ColumnsDAO(){   
  5.          //something need to be done   
  6.      }   
  7.         
  8.      public ColumnsDAO(Session session){   
  9.          this.session=session;   
  10.      }   
  11.             
  12.      //示例函数    
  13.          public List<Columns> getColList1() throws HibernateException {   
  14.   
  15.       try {   
  16.   
  17.        String hql = "from .....";   
  18.        List<Columns> ColList=session.createQuery(hql)   
  19.         .list();   
  20.        return ColList;   
  21.       }catch(HibernateException e){   
  22.        throw e;   
  23.       }finally{   
  24.       }   
  25.      }   
  26. }  
事务操作都放在对应BO中处理,如ColumnsBO对应的函数

 ColumnsBO:

java 代码
  1. public  List<Columns> getColList1(){   
  2.          session = SessionFactory.getSession();   
  3.          Transaction tx = session.beginTransaction();   
  4.          colDao = new ColumnsDAO(session);   
  5.          try {   
  6.              List<Columns> colList = new ArrayList<Columns>();   
  7.              colList = colDao.getColList1();   
  8.              tx.commit();   
  9.              return colList;   
  10.           }catch(HibernateException e){   
  11.            throw e;   
  12.           }finally{   
  13.           }   
  14.      }  

 为了保证可以使用延迟加载,session的关闭不是在BO或Dao中而是放到过滤器中,只要请求一个新的action就关闭掉session。这样问题就来了,我在某一BO的方法中需要调用其他BO的方法或者多个Dao的方法时session就都没有关闭,不是引起No row with the given identifier exists:就是出现Null错误。这种情况改如何处理?session是否要单独处理?

yhb_4323 2007-07-03
cnpollux 写道
异常为什么要这样处理呢?
# catch(HibernateException e){
# throw e;
# }


这是数据层的操作,为的是向上抛出异常,让业务层捕捉,然后来处理。
楼主说的应该是三层结构,论坛有过这样的帖子。

我的理解是,封装数据层(持久层),数据层只对数据进行操作,不管理业务关系。

以增加用户为例子:
类名: UserDAO.java (User表DAO)
数据层的方法: public List findByUsername(String userName) throws Expection;
public void save(User user) throws Expection;
类名:SysBO.java (系统管理员BO)
业务层的方法: public boolean addUser(String userName,String Password) throws
ExistExpection,AddExpection;

下面简单的写下业务层的代码:
 try{
     List l = userDAO.findByUsername(userName);
     if(l==null||l.size()>0) throw new ExistExpection();
     User u = new User();
     u.setUsername("admin");
     u.setPassword("admin888");
     userDAO.save(u);
 }catch(Expection e){
     throw new AddExpection();
 } 


我也是刚刚在项目中使用,我在网吧发帖,所以这段代码没有在编辑器中调试,希望你能理解到我想说什么。
insky 2007-07-03
cnpollux 写道
异常为什么要这样处理呢?
# catch(HibernateException e){
# throw e;
# }

这里只是想说明BaseDao是否处理得当的问题,没太注意异常,实际代码中是由上层专门异常类来捕获处理的,您说这里是应该如何处理?
insky 2007-07-03
pypcjs 写道
请看这篇文章《不要重复DAO》
http://www.ibm.com/developerworks/cn/java/j-genericdao.html

又仔细看了下这篇,有地方还是有点模糊:
===============
泛型 DAO 接口

public interface GenericDao <T, PK extends Serializable> {
T read(PK id);

。。。。
}

第一个泛型 DAO 实现

public class GenericDaoHibernateImpl <T, PK extends Serializable>
implements GenericDao<T, PK>, FinderExecutor {
private Class<T> type;

public GenericDaoHibernateImpl(Class<T> type) { 《===这里type从哪里获取?
this.type = type;
}

public T read(PK id) {
return (T) getSession().get(type, id); 《===这里的type如何获取的?初始化GenericDaoHibernateImpl 要指明T的类型吗?应该不用吧?
}

}
============================
参考了江南白衣的文章 可以写成:
public GenericHibernateDAO() {
this.clazz = (Class<E>) ((ParameterizedType) getClass()
.getGenericSuperclass()).getActualTypeArguments()[0];
}
我加到我的BaseDao中报错 取不到正确类型

究竟如何才能在BaseDao中轻松的实现 public T read(PK id) {
}方法呢?
cnpollux 2007-07-02
异常为什么要这样处理呢?
# catch(HibernateException e){
# throw e;
# }
pypcjs 2007-06-26
请看这篇文章《不要重复DAO》
http://www.ibm.com/developerworks/cn/java/j-genericdao.html
insky 2007-06-25
晕...发现所有范型有关的尖括号都被过滤掉了
insky 2007-06-25
java 代码

其实我的主要疑问是当Dao中的session,事务操作都放到BO中后,BaseDao的crud操作改如何处理?是否也写个BaseBO做对应的操作?

其余的dao方法很容易处理,比如我ColumnsDao中有个取出所有一级栏目的操作getColList1()方法,改写后ColumnsDao对应的方法如下:

java 代码
  1. public List<Columns> getColList1() throws HibernateException {   
  2.   
  3.       try {   
  4.   
  5.        String hql = "from Columns where parentColumn is null and colStatus=1 order by colOrder";   
  6.        List<Columns> Collist=session.createQuery(hql)   
  7.         .list();   
  8.        return Collist;   
  9.       }catch(HibernateException e){   
  10.        throw e;   
  11.       }finally{   
  12.       }   
  13.      }  

 

对应ColumnsBO如下:

java 代码
  1. Session session;   
  2.  ColumnsDAO colDao;   
  3.  public List<Columns> getColList1(){   
  4.      session = SessionFactory.getSession();   
  5.      Transaction tx = session.beginTransaction();   
  6.      colDao = new ColumnsDAO(session);   
  7.      try {   
  8.          List<Columns> colList = new ArrayList<Columns>();   
  9.          colList = colDao.getColList1();   
  10.          tx.commit();   
  11.          return colList;   
  12.       }catch(HibernateException e){   
  13.        throw e;   
  14.       }finally{   
  15.       }   
  16.  }  

这样似乎很顺畅,但是遇到BaseDao里的crud方法,因为ColumnsDao根本就没出现过crud方法,ColumnsBO该如何处理?也写个BaseBO对应处理BaseDao的方法?感觉怪怪的...

BTW:不知道我是否能把我的意思表达清楚,语言表达能力有限,给各位舔堵了:(

insky 2007-06-25
yongyuan.jiang 写道
BaseDao后还需要各自entity的dao,写代码不写死了,要是有20个类,还得去copy 20个xxxDAO?

何不直接使用一个BaseDao,提供save,delete,update,query,findById方法。

使用:
User user = (User)baseDao.findById('123');

不知道您是否没仔细看,或者是我的代码没表达清楚我的意思,我的BaseDao中已经提供了crud方法,写BaseDao就是为了其余entity的dao中避免copy重复的crud方法
比如ColumnAction中直接调用ColumnDao的creat方法(继承父类BaseDao)就可以,而不用再在ColumnDao处理crud方法
yongyuan.jiang 2007-06-25
BaseDao后还需要各自entity的dao,写代码不写死了,要是有20个类,还得去copy 20个xxxDAO?

何不直接使用一个BaseDao,提供save,delete,update,query,findById方法。

使用:
User user = (User)baseDao.findById('123');
insky
搜索本博客
博客分类
最近加入圈子
存档
最新评论