读 banq的帖子Domain Events异步应用 有疑惑

看了这个帖子 http://www.jdon.com/jivejdon/thread/37712/15,深受启发。

因为我也正好碰到这个问题。比如一堆分类,每个分类需要统计其下Product的数量。

这是我的回帖:
但是我有疑问,如果使用Hibernate,没法对二级缓存直接进行修改,我即便是更改了内存的值,比如messageCount改成1,下次从二级缓存取,仍然是-1。

不知有没有什么解决方案。请教banq。

我仔细研究了一下Hibernate的二级缓存,跟了源码。

Hibernate其实还是面向数据库的。而且其二级缓存存储的对象都是数组结构,并不是真正的对象。大量使用二级缓存后,看上去有点NoSQL的意思,其实本质上不是。我们无法修改其二级缓存中对象状态,如果要修改,那么必须同步数据库了。Hibernate还是以数据库为中心的东西,只是一个ORM,很牵强的一个东西。

我想到了直接做业务层缓存,在Entity基础上套一层Model,面向对象的Model做业务层缓存,面向表的Hibernate Entity做二级缓存,但这样的方案似乎太重了。

我们现在主要使用spring3+spring3mvc+hibernate框架结合开发,大量用了ehcache做缓存和二级缓存,在这种组合下,我们如何实现Domain Events呢?

请教banq以及论坛各位高手。


现在很多公司都是struts2+spring+hibernate或springmvc hibernate或类似这种组合,本论坛貌似很少介绍在这种组合下的Domain Model设计,能否介绍多些,毕竟我们很多人思路一下转不过来,国内软件环境即是如此,适应起来有点慢,呵呵,只是建议。希望能多多向大家学习。
[该贴被fnet于2011-04-20 16:03修改过]

2011年04月20日 15:59 "@fnet"的内容
在很多公司都是struts2+spring+hibernate或springmvc hibernate或类似这种组合,本论坛貌似很少介绍在这种组合下的Domain Model设计, ...

这实际我在Spring 3.1 终于加入了Cache支持中说了,根本目标期盼Spring变成MDD框架。但是Spring和JavaEE7通过引入可伸缩的缓存走向云计算架构,虽然这两个方向本质不冲突,但是到底是两个方向,他们试图通过云计算一步到位解决可伸缩性问题,而且有商业模式。而MDD则是面向开发者的,云计算普及后,可能对普通程序员的高可伸缩性架构要求不太高了。

有点远,说回来,现在问题关键是:领域模型到底应该归Spring边界内,还是Hibernate边界内?

如果归Hibernate边界,实则是面向关系数据库思维,而且Spring就成了只管理业务服务的框架(这实际是受过去落后的SOA影响)。

现在大家都开始重新思考SOA和DDD,当这场讨论尘埃落定,达成共识:对外部暴露服务,对内注重领域模型,这样相应的框架包括Spring等估计有所行动。

当然,不是我们骄傲Jdonframework又一次走到前面(以前JF的IOC开始就采取Autowiring自动配对比Spring 1.x强,后来Spring 2.x才支持这个,现在已经成为默认缺省功能,IOC或DI的代名词了),这说明中国人个人脑子不笨(合起来是另外一回事了)。

那么在现有的架构下,如何实现Domain Events呢?因为Hibernate的不透明性,如果Hibernate内核都使用IOC来管理,那么我们就可以改造它,其实它和数据库一样,铁板一块,改造很难,等待吧。

这就是为什么在Jdon没有讨论SSH这些所谓主流框架实现DDD或MDD,或Domain Events的原因,因为他们的路子就不对。所以DDD作者还有MF都比较失望,对.NET推行DDD,因为只有在.NET世界,业务模型和技术组件架构都是统一的(由微软一家推出),也反映Java世界的根本问题所在。

当然,不排斥有人会在Spring 或Hibernate上加工,包括楼主这样努力还是值得赞赏的。


感谢banq,也感谢banq的jdonframework以及jdonlive论坛案例。这两天翻了一下关于domain events的帖子,啃了jdonframework的一些代码,包括com.jdon.async.channel包的代码,得到不少启发。对“领域模型”应该有更多行为有了更深的认识,的确以前项目里所谓的模型大都是被动的,纯粹表示数据。
考虑到重构成本,现在手头上这个项目没法实现了,打算在下一个项目将这种思路引入。

目前分类数量这个功能暂时用缓存单独保存,缓存更新时机是在用户浏览一个界面时,自动做了数目缓存,因为此界面分页查询时已经获得了当前分类下所有内容的数目,正好缓存下,当他返回上级分类时即可浏览到,使用了Freemarker的自定义标签直接调业务组件读缓存显示,我们的分类比较少大约四百多个,这个做法比较牵强,暂时先这么做了,呵呵。

而另一个论坛主题数目和帖子数目的实现。
主题数目设计同上面,浏览版块下主题时,记录了此版块所有主题数目,返回即给予显示。
而帖子数目则分类两块:
1. 主题帖子总数,这个以类似上面的做法解决。
2. 版块帖子总数,在用户发帖时,检查cache中本版总数,如果总数没有缓存,则查询数据库,然后设置缓存,如果有缓存则在缓存基础上加1。

想请教一下banq,如果我不抛弃Hibernate,利用Hibernate的entity实体类,将其作为领域模型,赋予其行为,在Hibernate那面向表的二级缓存之外,单独对其做真正意义上的对象缓存,那么在操作此对象缓存时,遇到延迟加载出错怎么办,因为也碰到了这个问题,也没想到什么好的解决方式。希望能得到banq的指点,非常感谢。


[该贴被fnet于2011-04-28 00:55修改过]

2011年04月28日 00:09 "@fnet"的内容
单独对其做真正意义上的对象缓存,那么在操作此对象缓存时,遇到延迟加载出错怎么办,因为也碰到了这个问题 ...

我目前想到的办法是:把领域模型和Hibernate的实体对象分离;Hibernate的实体对象作为领域模型的影子,也就是两个实体对象,将领域模型从Hibernate绑架中解放出来(如果直接使用IBatis就没有这些问题)。

还有一种方式,是失效延迟加载,将Hibernate加载的对象缓存在Spring的缓存中,失效Hibernate的二级缓存。

至于网上现在盛传的使用ehcache的集群方案如terracotta兵马俑对Hibernate二级缓存进行集群,这还是基于关系数据库的集群,扩展性以及伸缩性没有memcache强,不是弹性的分布式缓存,只有将领域模型解放出来,直接放到memcached之类弹性缓存,才有性能上真正突破。

2011年04月28日 07:57 "@banq"的内容
...

感谢banq,我明白了。。。
Repository那一层还是拿领域模型,
而DAO则是拿领域模型转换成实体进行入库操作了。

[该贴被fnet于2011-04-28 11:12修改过]