メンバーが誰かより、誰をどこに配置するかが重要
今までプロジェクトとの体制について思うことといえば、
誰がメンバーにいるかだったが、
それよりも、誰をどこに配置するかが重要だと今回のプロジェクトで思った。
みんながみんな声が大きいわけではない。
どこに配置されるかによっていいたいことがいえなかったり、
自由に動けなかったりしてしまうもの。
用語は明確に定義する
用語集だけを見ても、書いていることは理解できるが、頭に入ってこない。
難しい概念は、具体例などを沿えた用語の定義資料があればよいと思う。
推奨のパッケージ構成は?
SAStrutsを使用した場合の、パッケージ構成はどれがいいのだろう?
まず、HOT Deploy対象・非対象は分けておいたほうがよさそう。(公式ページには書いてないが)
では、HOT Deploy対象配下はどのようにするべきか?
考えられるパターンとしては、以下のどちらかになるかと思っている。
- <ルートパッケージ>.<サブパッケージ>.action.xxxAction
- <ルートパッケージ>.action.<サブパッケージ>.xxxAction
メーリングリストでは基本的に2を推奨するが、どちらでもよいとの回答がある。
[Seasar-user:15429] Re: [SAStruts] パッケージ構成の規約について
ただし、1の構成の場合NamingConventionを修正する必要があるとのこと。
あまり標準に手を入れたくないので、2の方法が無難かな。
findByIdで論理削除を除く
findByIdで論理削除されているレコードを除くには、AbstractServiceでやるのがいいみたい。
S2JDBC の弱点を補完するS2AbstractService - 出羽ブログ
けどこの方法は、DBの主キーにIDが導入されている場合なら、
作成するメソッドが一つでいいが、IDが導入されていないと主キーのパターンだけメソッドが必要となってしまう。
もっとスマートな方法はないですかね。。
楽観的ロック発生時の例外処理
楽観的ロック発生時には自画面を表示し、"既に変更されてます"というエラーメッセージを出したい。
Serviceクラスがトランザクション境界の場合は、ActionでSOptimisticLockExceptionをキャッチして、
自画面へreturnすればいいのだが、Actionクラスがトランザクション境界の場合はそうもいかない。
Actionでthrowした例外を、ExceptionHandlerかInterceptorで補足すればうまくできそうだが、
"自画面"を示すJSPがうまくとれるか?
こういうのは一般的な要件の気もするが、みんなどうやってるんだろ?
一律システムエラー画面へ遷移?
2010/08/23追記
Actionクラスがトランザクション境界の場合、Actionから例外スローしないと
ロールバックされないと思っていましたが、Serviceで例外スローしてもされるのですね。。
ActionでSOptimisticLockExceptionをcatchして、自画面へ遷移すればいいだけの話でした。
DBアクセス時の共通処理の実装
DBアクセス時に共通化したい処理はいくつかあるが、まずは、"INSERT時に更新日時をセットする"という単純なものをS2JDBCで作ってみた。
(以下の記事を非常に参考にさせていただきました。)
S2JDBC の弱点を補完するS2AbstractService - 出羽ブログ
テーブル構造
下記のようなシンプルなテーブルを用意。
CREATE TABLE EMP_TEST( ID INT(3), NAME VARCHAR(20), UPDATE_TIME TIMESTAMP );
エンティティの作成
全てのテーブルに共通に存在するカラムを、共通のスーパークラスとして定義。
@MappedSuperclassをつけないと、サブクラスの永続プロパティと見なされないので注意。
@MappedSuperclass public abstract class AbstractEntity { @Temporal(TemporalType.TIMESTAMP) public Date updateTime; }
次に、共通のスーパクラスを継承したサブクラスを作成。
@Entity public class EmpTest extends AbstractEntity { @Id public Integer id; public String name; }
サービスの作成
S2AbstractServiceを継承して、共通のスーパークラスを作成。引数に先ほど作成した、共通のエンティティクラスを持つ、insertメソッドを作成。ここに共通の処理を実装。
public abstract class AbstractService<ENTITY> extends S2AbstractService<ENTITY> { public int insert(AbstractEntity entity) { //updateTimeにシステム時間をセット Date currentDate = new Date(System.currentTimeMillis()); entity.updateTime = currentDate; return jdbcManager.insert(entity).execute(); } }
次に、共通のスーパクラスを継承したサブクラスを作成。
特に固有の処理が必要なければ、空っぽにする。
public class EmpTestService extends AbstractService<AbstractEntity> { }
呼び出し部分の作成
... emp.id=1; emp.name="TEST"; empTestService.insert(emp); ...
これで完成。
他にも"登録者のユーザIDをセットする"ということもやりたいのだが、ユーザIDはセッションから取得したいのでサービスクラスでは取得できない。皆さんどのように実装しているのか?いい方法があれば、教えてください。