2

メールIDをパラメーターとして受け取り、そのIDを持つユーザーのトークンを生成する単純なWebアプリケーションを作成しようとしています。私のコードは一目瞭然だと思うので、ここに貼り付けて、詳細を説明する必要がないようにします。

これは私のコントローラー/サーブレットコードです

    User user = userManager.getUserByEmailId("xyz@gmail.com");
    if (user == null) {
        //TODO handle this
    }
    if (user.getIssuedTokens() == user.getMaxTokens()) {
        // TODO handle this
    }
    String token = tokenService.createToken();
    user.setToken(token);
    user.setIssuedTokens(user.getIssuedTokens() + 1);
    userManager.updateUser(user);

userManager と tokenService はサービス層の実装です。

@Service("tokenService")
public class TokenizationServiceImpl implements TokenizationService {

    @Autowired
    private TokenDAO tokenDAO;

    @Transactional
    public String createToken() {
        String uuid = UUID.randomUUID().toString();
        tokenDAO.createToken(uuid);
        return uuid;
    }
}


@Service("usermanager")
public class UserInterfaceImpl implements UserInterface {

    @Autowired
    private UserDAO userDAO;

    @Transactional
    public void createUser() {
        userDAO.createUser();
    }

    public User getUserByEmailId(String emailID) {
        return userDAO.getUserByEmailId(emailID);
    }

    @Transactional
    public void updateUser(User user) {
        userDAO.updateUser(user);

    }

}

私の春の構成はこのようなものです

<tx:annotation-driven />

    <context:component-scan base-package="com.myapp.dao" />
    <context:component-scan base-package="com.myapp.service" />

    <bean id="dataSource"
        class="org.springframework.jdbc.datasource.DriverManagerDataSource">

        <property name="driverClassName" value="com.mysql.jdbc.Driver" />
        <property name="url" value="jdbc:mysql://localhost:3306/mydb" />
        <property name="username" value="root" />
        <property name="password" value="root" />
    </bean>

    <!-- dataSource TransactionManager -->
    <bean id="transactionManager"
        class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource" />
    </bean>

ここに私の質問があります:

  1. 2 つのサービス (usermanager と tokenService) をコントローラー/サーブレットに挿入し、それらを次々と呼び出すことは理にかなっていますか? または、usermanager サービスまたは UserDAO を直接利用する 1 つのメソッドを TokenServiceImpl に直接記述する必要がありますか?
  2. トランザクション属性は私にはうまくいかないようでした。updateUser メソッドが失敗すると、createToken() メソッドからトークンがデータベースに作成されました。ここで何が間違っていますか?トランザクションがロールバックされなかったのはなぜですか?
  3. 自分のサービスが複数の DAO を使用するか、他のサービスを使用するかを一般的にどのように決定すればよいですか?
4

2 に答える 2

2

さて、あなたの 2 番目の質問についての私の考えは、最初の質問にも答えるかもしれません。スニペットを見ると、メソッドの外部から呼び出しているためtokenService.createToken()、 との 2 つの異なるトランザクションを作成していることがわかります。この動作を修正するには、次のようにする必要があります。userManager.updateUser(user)@Transaction

public class UserService {

    ...

    @Transactional
    public void assignToken() {
        User user = userManager.getUserByEmailId("xyz@gmail.com");
        if (user == null) {
        //TODO handle this
        }
        if (user.getIssuedTokens() == user.getMaxTokens()) {
        // TODO handle this
        }
        String token = tokenService.createToken();
        user.setToken(token);
        user.setIssuedTokens(user.getIssuedTokens() + 1);
        userManager.updateUser(user);
    }
}

この新しいトランザクション動作を考慮するために、 という新しいビジネス コンポーネントを作成したことに気付くでしょうUserService。私はあなたのアプリケーションを本当に知っているわけではありませんが、何が最善のアプローチであるかを言うことはできませんが、私は間違いなくあなたのコントローラーにそれを入れません. 私の意見では、この動作を次のように分離する必要があります。

  • 新しいビジネス コンポーネント (この例で行ったように)
  • UserManagerまたは、たとえばインスタンス内にカプセル化します

さて、それに結合UserServiceする価値があるか、それともTokenizationService新しいビジネス クラスを作成する価値があるかは、あなた次第です。あなたが提供したコードを読むとUserServiceTokenizationServiceトークンは別のコンテキストでは使用されないため、

ご意見をお聞かせください。

于 2013-10-07T21:45:24.563 に答える
2
  1. はい、コントローラー内のすべてのコードは、トランザクション サービス内にある必要があります。あなたのサービスは、DAOのメソッドに委譲する以外に何もしません。このサービスには、ビジネス ロジックが含まれ、トランザクションを区別することが想定されています。

  2. 各サービスはトランザクションです。したがって、 を呼び出すcreateToken()と、トランザクションが開始され、戻るとすぐにコミットされcreateToken()ます。が呼び出されると、別のトランザクションが開始され、リターン/失敗updateUser()するとすぐにコミットまたはロールバックされます。updateUser()これが、すべてのコントローラー コードを単一のトランザクション サービスに含める必要がある理由の 1 つです。その場合、両方の呼び出しが 1 つのトランザクションで行われ、2 番目の呼び出しが失敗すると、トークン生成を含むトランザクション全体がロールバックされます。

  3. 私のルールは次のとおりです。サービスがデータベースからデータを取得する必要がある場合は、DAO を使用する必要があります。別のサービスで既に定義されているビジネス ロジックを再利用する必要がある場合は、そのサービスに委任する必要があります。

于 2013-10-07T21:40:12.643 に答える