浏览 3699 次
锁定老帖子 主题:业务逻辑能否不依赖于持久层?
精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
|
|
---|---|
作者 | 正文 |
发表时间:2007-05-14
其中manager实现业务逻辑,提供事务,action调用service service中仅获取session,控制事务,load对象,然后调用manager,所以我可以单独的测试业务而不依赖于持久层 目前有这么个场景:一张地图,分成小块。给我一个坐标和半径,然后判断这个范围内是否有水。 因为地图是上下相通,左右相通,所以我要算出这个范围内所有地块的id,然后load出来,再逐格判断 于是代码就得类似这样: List<Integer> idList=manager.computeIdList(int x,int y); Query query = session.createQuery("from Field where id in (:list)"); query.setParameterList("list", idList); boolean hasWater=manager.fieldHasWater(query.list()); 我想把这些东西都封到manage里,于是我定义了一个MyMap,与地块是一对多,内部用map,key为地块的id 这时会多个MyMap表,里面只有一行数据,地块表会多一列,以对应MyMap 于是manager就能写成: boolean hasWater(int x,int y,MyMap map); 然后在内部用may.getField(int id)来得到地块 地块的数量有几十万,所以我用了lazy="extra"。 这种设计是否合理,是否会产生某些问题? PS:<map-key type="int" formula="id" />,这种情况下不能用extra,hibernate生成的查询条件会出现null 再PS:以前看过一篇文章,select * from table where id in(1,2)的性能不如select * from table where id=1 union select * from table where id=2 因为in查询不能很好的利用索引,所以我觉得hibernate在缓存命中高的情况下,用循环load对象比用in查询要好一点,这个没测试过,高手有经验请说说 声明:ITeye文章版权属于作者,受法律保护。没有作者书面许可不得转载。
推荐链接
|
|
返回顶楼 | |
发表时间:2007-05-15
1.建议事务控制与业务调用一致,否则会造成业务异常而无法完全回滚。
2.当你在设计业务调用接口时,需要考虑持久化相关的问题,那么可以肯定要不就是该业务不是业务,或者后者完全是多虑。 |
|
返回顶楼 | |
发表时间:2007-05-15
wolfsquare 写道 1.建议事务控制与业务调用一致,否则会造成业务异常而无法完全回滚。
2.当你在设计业务调用接口时,需要考虑持久化相关的问题,那么可以肯定要不就是该业务不是业务,或者后者完全是多虑。 多谢回复,不过这两点我不是很明白。 这是不使用MyMap的代码 public class Field { private Integer id; private int x; private int y; private boolean hasWater; } public class CoreManage { public static List<Integer> getIdList(int x, int y, int radius) { // .... } public static boolean hasWater(List<Field> list) { for (Field tmp : list) { if (tmp.isHasWater()) { return true; } } return false; } } public class CoreService { private SessionFactory sessionFactory; public boolean hasWater(int x, int y, int radius) { Session session = sessionFactory.openSession(); try { session.beginTransaction(); List idList = CoreManage.getIdList(x, y, radius); Query query = session.createQuery("from Field where id in (:list)"); query.setParameterList("list", idList); List<Field> list = (List<Field>) query.list(); return CoreManage.hasWater(list); } catch (Exception e) { session.getTransaction().rollback(); return false; } finally { session.close(); } } } 使用MyMap后可以改成如下的,Field不变 public class MyMap { private Map<Integer, Field> map = new HashMap<Integer, Field>(); public Field getField(int id) { return map.get(id); } } public class CoreManage { public static List<Integer> getIdList(int x, int y, int radius) { // .... } public static boolean hasWater(int x, int y, int radius, MyMap map) { List<Integer> idList = CoreManage.getIdList(x, y, radius); for (int r : idList) { if (map.getField(r).isHasWater()) { return true; } } return false; } } public class CoreService { private SessionFactory sessionFactory; public boolean hasWater(int x, int y, int radius) { Session session = sessionFactory.openSession(); try { session.beginTransaction(); MyMap map=(MyMap)session.get(MyMap.class, 1); return CoreManage.hasWater(x,y,radius,map); } catch (Exception e) { session.getTransaction().rollback(); return false; } finally { session.close(); } } } 像上面的代码那样,manage可以封上全部的业务,service只提供事务,这样我可以脱离持久层测试业务,我可以伪造一个MyMap用来测试,而从逻辑上讲,从地图上获取某一格,也比较自然 而按第一段的写法,service里是有业务逻辑的,测试的话,就得搭上数据库才行 把hibernate作为DAO来使用,不使用DAO层,service里不实现业务,只提供事务,这种用法在个别帖子里也出现过,不过特别少,所以我拿不准这种用法有什么缺点,所以还是希望能得到一些指点。 |
|
返回顶楼 | |