论坛首页 Java企业应用论坛

关于Domain Object中业务逻辑的事务处理的疑问?

浏览 14383 次
精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
作者 正文
   发表时间:2004-10-30  
不好意思,又一次提起了domain model.疏于对domain model的理解,不得不让硝烟再次弥漫domain model...

我现在对domain model的理解是这样的,对于通用的业务逻辑,应该写到domain object中,而对于非通用的业务逻辑应该写到domain logic中,现在举个简单的例子:

一个银行账号的例子(Account),这个Account毫无疑问应该作为domain object 出现,而且一般也不需要继承任何东西,一般来说对于一个银行账号,deposit(存款),withdraw(取款),transfer(转帐)等操作,我想够通用了吧,所以我现在设计过程中把这些操作放到了Account这个pojo中,而且这也符合OO的编程思维,而对于insertAccount操作放到AccountService中,我现在使用的spring声明式事务操作,target我指向的是AccountService,这样对于AccountService中的操作可以使用事务处理,但此时deposit(存款),withdraw(取款),transfer(转帐)等操作如何才可以享受事务处理呢?
难道需要把target也指向Account吗?但是target似乎只能指向一个吧?对与这点我甚感疑惑,还是我domain model的设计有问题?

看部分代码:

pojo的代码,很简单,很多东西没包含在内,比如RuntimeException的处理

引用
public class Account
{
    private String id;
    private String accountname;
    private String passwd;
    private String gender;
    private String email;
    private int amount;

    //业务逻辑
    public int deposit(int amount)
    {
        return this.amount + amount;
    }
    public int withdraw(int amount)
    {
        return this.amount - amount;
    }
    public int transfer(int amount,String receiver)
    {
        this.amount = this.amount - amount;
        AccountService as = ...
        Account account2 = as.findByAccountname("receiver");
        account2.deposit("amount");
        as.updateAccount(account2);
        return this.amount;
    }
    public int checkleft()
    {
        return amount;
    }
}


domain logic代码:

引用
public interface AccountService
{
    public void insertAccount(Account account);
    public Account findByAccountname(String accountname);
    public void updateAccount(Account account);
}


现在只有AccountService里的代码可以享受事务,但是Account里的业务逻辑如何享受事务呢?用domain model应该如何设计呢?
   发表时间:2004-10-30  
我不知道你为什么要把它想得那么复杂。你只要确定在什么地方划定用例边界就行了。如果你认为WebWork action是用例边界,那么用WebWork interceptor来管理事务;如果你认为business facade是用例边界,那么给facade加一个dynamic proxy管理事务。就这么简单的一件事。至于domain object还是transaction script,那完全是你的实现细节,跟facade以上的东西没关系。
0 请登录后投票
   发表时间:2004-10-30  
gigix 写道
我不知道你为什么要把它想得那么复杂。你只要确定在什么地方划定用例边界就行了。如果你认为WebWork action是用例边界,那么用WebWork interceptor来管理事务;如果你认为business facade是用例边界,那么给facade加一个dynamic proxy管理事务。就这么简单的一件事。至于domain object还是transaction script,那完全是你的实现细节,跟facade以上的东西没关系。


怎么能说与domain object还是transaction script实现没有关系呢?如果用Transaction script的话,那么我所有的业务逻辑可能全在service里面,这样的话,我可以用dynamic proxy或是spring的声明式事务出来(其实原理一样),也就是说我在webwork层的话就不需要考虑事务处理了,这样的事务处理全部不用我们用代码显示处理了,而如果是domain model的话,domain中包含有业务逻辑,而这部分业务逻辑应该如何处理事务,按照你的思路的话,就是webwork层用interceptor来管理事务,因为就上面的例子来说,无论是withdraw 还是transfer都应该是得到Account后在webwork层来调用的,所以这部分事务只能由interceptor来处理,OK,这样可以实现事务处理,但是毕竟还是要我们手写代码来实现事务,这样就失去了事务作为infrastructure的意义。再在EJB中来看这个例子,如果domain中的业务逻辑也在客户端来处理的话,那不是还要lookup transaction吗?那如何交由Container来处理事务呢?我想这仍是个问题
0 请登录后投票
   发表时间:2004-10-30  
引用

现在只有AccountService里的代码可以享受事务,但是Account里的业务逻辑如何享受事务呢?用domain model应该如何设计呢?

      把通用的逻辑放入domain model是合理的,在domain上不用实现事务,而是在在service上来提供事务功能,我 现在就是这样做的,通过动态代理,threadlocal来实现事务管理,事务自然在model中传播;如果直接把domain传到表示层,那么domain object的逻辑是没有事务的,那么必须规定:domain
object 不能做vo穿到表示层;或者在表示层只通过service层调用业务逻辑;
后者是比较合理得,应为通常facade层来界定用例是比较合理得,web层得action就应该做得很薄,不实现或者几乎不实现业务逻辑,这样就没有理由需要事务了
0 请登录后投票
   发表时间:2004-10-30  
Jolin 写道
引用

现在只有AccountService里的代码可以享受事务,但是Account里的业务逻辑如何享受事务呢?用domain model应该如何设计呢?

      把通用的逻辑放入domain model是合理的,在domain上不用实现事务,而是在在service上来提供事务功能,我 现在就是这样做的,通过动态代理,threadlocal来实现事务管理,事务自然在model中传播;如果直接把domain传到表示层,那么domain object的逻辑是没有事务的,那么必须规定:domain
object 不能做vo穿到表示层;或者在表示层只通过service层调用业务逻辑;
后者是比较合理得,应为通常facade层来界定用例是比较合理得,web层得action就应该做得很薄,不实现或者几乎不实现业务逻辑,这样就没有理由需要事务了


只在service上提供事务处理,如何在model中传播?现在我也只是在service上提供事务处理,所以service上的方法都可以享受事务,没问题。web层我是这样写的:
引用
AccountService as = ...
Account account  = as.findByAccountname("hpq852");
account.deposit("10000");
as.updateAccount(account);


所以此时如果我只是做deposit 和 withdraw时候,可能没问题,因为整个过程只是一个update。但如果我进行transfer操作的时候:

引用
AccountService as = ...
Account account  = as.findByAccountname("hpq852");
account.transfer("10000","jolin");//此时transfer由于也是调用service上的方法,所以同样享受事务处理
as.updateAccount(account);


如果是这样的话,问题来了,转帐的操作必须原子性,也就是说transfer的事务应该和as.updateAccount(account);的事务是同一个才可以保证正确,而此时两个事务是分开的,所以此时应该如何处理呢?难道还需要在web层调用interceptor在开一个事务?把两个方法包在一起?
0 请登录后投票
   发表时间:2004-10-30  
引用
AccountService as = ...
Account account  = as.findByAccountname("hpq852");
account.deposit("10000");
as.updateAccount(account);

web层不应该跨过service直接去调用donmain层的东西

引用
AccountService as = ...
Account account  = as.findByAccountname("hpq852");
account.transfer("10000","jolin");//此时transfer由于也是调用service上的方法,所以同样享受事务处理
as.updateAccount(account);


怎么能让transerfer 去调用上一层service层的的东西呢?
引用

如果是这样的话,问题来了,转帐的操作必须原子性,也就是说transfer的事务应该和as.updateAccount(account);的事务是同一个才可以保证正确,而此时两个事务是分开的,所以此时应该如何处理呢?难道还需要在web层调用interceptor在开一个事务?把两个方法包在一起?

既然transfer是事物的,为什么不把转帐业务在一个service方法 提供呢?web中的action中是不该出现下面的代码
Account account  = as.findByAccountname("hpq852");
account.transfer("10000","jolin");//此时transfer由于也是调用service上的方法,所以同样享受事务处理
as.updateAccount(account)
0 请登录后投票
   发表时间:2004-10-30  
我上面的那个例子如果要是挑毛病,恐怕无数,我只是为了想了解一下domain model到底应该如何设计。

jolin 写道
既然transfer是事物的,为什么不把转帐业务在一个service方法 提供呢?web中的action中是不该出现下面的代码
Account account = as.findByAccountname("hpq852");
account.transfer("10000","jolin");//此时transfer由于也是调用service上的方法,所以同样享受事务处理
as.updateAccount(account)


如果我把transfer,withdraw,deposit等方法都放到service里面的话,那不是又回到了transaction script了吗?我就是不想使用ts才这样来做的。transfer这个业务逻辑够通用了吧,所以我才放到domain object里。

jolin 写道
web层不应该跨过service直接去调用donmain层的东西


web层不能直接调用domain层的东西吗?那domain object怎么传到web层呢?难道还需要加一层dto?而且domain上的业务逻辑应该如何调用呢?由谁来调用呢?
0 请登录后投票
   发表时间:2004-11-10  
Hibernate的interceptor和spring:
http://forum.springframework.org/viewtopic.php?t=301&postdays=0&postorder=asc&start=0
0 请登录后投票
   发表时间:2004-11-11  
我做法很极端。
1.每个business object对应一个表,不包含任何业务逻辑。
2.用hibernate做持久化,但不用它的任何关联关系。
3.DAO层只有一个类,继承spring的HibernateDAOSupport类,完成对数据库的所有操作。
4.业务逻辑全部写在Service层,调用DAO的那个类来处理数据库交互。
5.用spring的事务包装Service层。

丢失了很多OO的特性,但让我的工作变得简单了,你要不要考虑下?
0 请登录后投票
   发表时间:2004-11-12  
towjzhou 写道
我做法很极端。
1.每个business object对应一个表,不包含任何业务逻辑。
2.用hibernate做持久化,但不用它的任何关联关系。
3.DAO层只有一个类,继承spring的HibernateDAOSupport类,完成对数据库的所有操作。
4.业务逻辑全部写在Service层,调用DAO的那个类来处理数据库交互。
5.用spring的事务包装Service层。

丢失了很多OO的特性,但让我的工作变得简单了,你要不要考虑下?


呵呵,典型的Transaction Script做法。
0 请登录后投票
论坛首页 Java企业应用版

跳转论坛:
Global site tag (gtag.js) - Google Analytics