BO,DAO如何来分层清晰以及Session何处关闭的问题
我的BaseDAO如下:
- public class BaseDAO
- {
- Session session;
- /**
- * @author insKy
- * @time 2007-6-17 下午03:06:17
- * @version 1.0
- * @param t
- */
- public void create (T t) {
- try {
- session = SessionFactory.getSession();
- Transaction tx = session.beginTransaction();
- session.save( t );
- session.flush();
- tx.commit();
- }catch(HibernateException e){
- throw e;
- }finally{
- }
- }
- //update delete操作类似 此处代码略
- public void update (T t)
- public void delete(T t)
- }
其余Dao继承这个BaseDAO:
- public class ColumnsDAO extends BaseDAO{
- //某些操作。。。 此处不显式调用父类的creat函数
- }
然而Dao中出现事务操作是不合适的,所以这里想分出BO层处理session以及事务的处理,修改完后的BaseBO应该大体如下:
- public void create (T t) {
- try {
- session.save( t );
- }catch(HibernateException e){
- throw e;
- }finally{
- }
- }
我的问题是
1,对应的BO应该如何处理?BaseDAO中的session应该如何获取?BO中如何传递过来?(没用Spring之用到Struts+Hibernate)session的获取是SessionFactory通过ThreadLocal获取的
//看了别人的程序,感觉如果用Spring来管理,不会遇到这些问题,这里没用Spring改如何来最好的管理session的传递?
2,是否也应该写一个BaseBO来对应处理BaseDAO中的各个操作以避免每个BO中处理crud操作?
请各位指教
评论
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,我觉的可行
看的让我茫然了. 难道非Spring不行了?
<html><head><title>2222222</title></head><body>123123</body></html>
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{
}
}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{
}
}
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{
}
}
简单的情况下可行。可以对Service做动态代理,统一管理事务的开启和关闭(诚如Spring的AOP实现)。然后通过工厂模式向上提供访问Service的接口。
我现在修改后的Dao中完全不包含事务处理操作 如下ColumnsDAO中某一个函数
ColumnsDAO:
- public class ColumnsDAO extends BaseDAO{
- Session session;
- public ColumnsDAO(){
- //something need to be done
- }
- public ColumnsDAO(Session session){
- this.session=session;
- }
- //示例函数
- public List<Columns> getColList1() throws HibernateException {
- try {
- String hql = "from .....";
- List<Columns> ColList=session.createQuery(hql)
- .list();
- return ColList;
- }catch(HibernateException e){
- throw e;
- }finally{
- }
- }
- }
ColumnsBO:
- public List<Columns> getColList1(){
- session = SessionFactory.getSession();
- Transaction tx = session.beginTransaction();
- colDao = new ColumnsDAO(session);
- try {
- List<Columns> colList = new ArrayList<Columns>();
- colList = colDao.getColList1();
- tx.commit();
- return colList;
- }catch(HibernateException e){
- throw e;
- }finally{
- }
- }
为了保证可以使用延迟加载,session的关闭不是在BO或Dao中而是放到过滤器中,只要请求一个新的action就关闭掉session。这样问题就来了,我在某一BO的方法中需要调用其他BO的方法或者多个Dao的方法时session就都没有关闭,不是引起No row with the given identifier exists:就是出现Null错误。这种情况改如何处理?session是否要单独处理?
# 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();
}
我也是刚刚在项目中使用,我在网吧发帖,所以这段代码没有在编辑器中调试,希望你能理解到我想说什么。
# catch(HibernateException e){
# throw e;
# }
这里只是想说明BaseDao是否处理得当的问题,没太注意异常,实际代码中是由上层专门异常类来捕获处理的,您说这里是应该如何处理?
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) {
}方法呢?
# catch(HibernateException e){
# throw e;
# }
http://www.ibm.com/developerworks/cn/java/j-genericdao.html
其实我的主要疑问是当Dao中的session,事务操作都放到BO中后,BaseDao的crud操作改如何处理?是否也写个BaseBO做对应的操作?
其余的dao方法很容易处理,比如我ColumnsDao中有个取出所有一级栏目的操作getColList1()方法,改写后ColumnsDao对应的方法如下:
- public List<Columns> getColList1() throws HibernateException {
- try {
- String hql = "from Columns where parentColumn is null and colStatus=1 order by colOrder";
- List<Columns> Collist=session.createQuery(hql)
- .list();
- return Collist;
- }catch(HibernateException e){
- throw e;
- }finally{
- }
- }
对应ColumnsBO如下:
- Session session;
- ColumnsDAO colDao;
- public List<Columns> getColList1(){
- session = SessionFactory.getSession();
- Transaction tx = session.beginTransaction();
- colDao = new ColumnsDAO(session);
- try {
- List<Columns> colList = new ArrayList<Columns>();
- colList = colDao.getColList1();
- tx.commit();
- return colList;
- }catch(HibernateException e){
- throw e;
- }finally{
- }
- }
这样似乎很顺畅,但是遇到BaseDao里的crud方法,因为ColumnsDao根本就没出现过crud方法,ColumnsBO该如何处理?也写个BaseBO对应处理BaseDao的方法?感觉怪怪的...
BTW:不知道我是否能把我的意思表达清楚,语言表达能力有限,给各位舔堵了:(
何不直接使用一个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方法
何不直接使用一个BaseDao,提供save,delete,update,query,findById方法。
使用:
User user = (User)baseDao.findById('123');
- 浏览: 9313 次
- 性别:

- 来自: 北京

- 详细资料
搜索本博客
最近加入圈子
最新评论
-
BO,DAO如何来分层清晰以及 ...
不知道可以不可以用类似与sping的opensessioninview的方式,在 ...
-- by zzm_fly2004 -
BO,DAO如何来分层清晰以及 ...
用动态代理 在你的getlist的方法用动态代理包装下,加入事务 import ...
-- by kakaluyi -
BO,DAO如何来分层清晰以及 ...
晕掉. 楼上的在做什么 看的让我茫然了. 难道非Spring不行了?
-- by cindy_taozhiang -
解释一句代码的含义(hasht ...
转成正整数求余
-- by dnglee -
Dao中如何取得HttpSessio ...
你这if判断没什么用,去了就行
-- by davis129






评论排行榜