2013-03-05 9 views
10

私はmybatisを新しいプロジェクトに使用しようと決めました。私はまさにSQLに精通しており、私は最近、休止状態でいくつかの悪い経験をしてきましたので、私はDAOへのより低レベルのアプローチを探しています。mybatisでコレクションを保存/更新するのは一般的な方法ですか?

1つのこと以外はすごくいいと思われます。それはコレクションを処理しています。

私は多対多である2つのPOJO、グループとユーザーを持っています。コレクションを持つPOJOは、保存するときにテーブル間のM-M関係を更新するだけでよいという設計哲学を決めました。たとえば、ユーザーの集まりを持つグループオブジェクトを保存する場合、設計思想ではユーザーは既に保存されている必要があり、グループとgroup_userの関係をデータベースに保存するだけで済みます。

ので、インタフェースのセーブグループ機能のために、私はMyBatisのために、このXMLマッピングを行った。

<insert id="saveGroup" keyColumn="id" 
    parameterType="se.myapp.domain.Group"> 
    <choose> 
     <when test="id == null"> 
     INSERT INTO myapp_group (name, description) 
     VALUES 
     (#{username}, #{password}); 
     </when> 
     <otherwise> 
     UPDATE myapp_group set name=#{name}, description=#{description} 
     where id=#{id}; 
     </otherwise> 
    </choose> 

    <if test="users != null"> 
     create temporary table tmpnewgroups (group_id integer, user_id integer); 

     insert into tmpnewgroups (group_id, user_id) values (
     <foreach collection="users" item="user" open="" close="" separator="),()"> 
      #{id},#{user.id} 
     </foreach> 
     ); 

     insert into myapp_user_group(group_id, user_id) 
     select tmp.group_id, tmp.user_id 
     from tmpnewgroups tmp 
     left outer join myapp_user_group ug 
      on ug.group_id = tmp.group_id and ug.user_id = tmp.user_id 
     where ug.group_id is null; 

     delete from myapp_user_group 
     where group_id = #{id} and user_id not in (select user_id from tmpnewgroups); 
    </if> 

</insert> 

意図したとおりこれは、仕事をする(挿入/グループを更新し、関係として、ユーザーのコレクションを保存しますデータベース内で)。しかし、私はこれがベストプラクティスだとは思わない。必要に応じて休止状態に切り替えることができるようにアプリケーションが作られているので、コレクションを保存するためのロジックはデータベースレイヤーにあることが望ましいです。私が気付いていないマイバティスには、このような業務を合理化できるいくつかの「魔法」がありますか?

これを改善する方法についてのご意見はありますか?または、アプリケーションの設計を再考し、モデルのコレクションの処理をさらにモデル化する必要がありますか?

+0

」とその「」を使用して多くの関係を記述すると問題がありましたか? – Gus

+0

よくある結果マップは、データを取得するためのもので、データを保存するものではありません。コレクションを入手することは問題ありません。私は煩わしいことが分かっています。 – Dytut

+0

[MyBatis Generator](https://code.google.com/p/mybatis/wiki/Generator)を使用してみましたか?それはあなたのための基本的なCRUD操作を生成します。複雑な結合などを書くだけで済むように、大量の手作業でコード化されたSQLを保存します。DAOで生成されたコードを使用して、 DAOへのあなたのXML。 – clav

答えて

1

saveGroupデータマッピング操作の2番目の部分は、実際にアプリケーション設計を再考する理由です。デルタを挿入して削除するためにメモリ内のユーザーコレクションを一時テーブルに保存しておくと、デルタを挿入して削除するのは非常に重い作業です。グループの名前または説明だけを更新する必要がある場合は、すなわち、デルタが存在しないときである。これが当てはまるかどうかは、現在のソリューションであるデータベースサーバー、またはデータベースクライアント、アプリケーションによって決まります。

リンクテーブルを更新する必要があるかどうかをアプリケーションが判断するようにするには、グループと場合によっては最初の挿入が必要な場合を除いて、アプリケーションはユーザーコレクションはデータベースから取得されてから変更されました。残念なことに、MyBatisはアプリケーションの実行を支援するつもりはありません。

Hibernateとの比較MyBatisは、MyBatisがジョブを完了した後、オブジェクトとオブジェクトの関係をマッピングするのではなく、データマッピングであることに気付きません。 Hibernateはあなたのオブジェクトのいわゆる汚れた状態を自動的に検出することができます。MyBatisはそれが仕事の記述の一部ではないので、できません。だから、あなたは自分のデバイスに残されています。

非常に簡単なアプローチは、選択後にユーザーのハッシュコードを保存し、そのハッシュコードがisUserDirty()というメソッドを使用して変更されたかどうかをチェックすることです。 <if test="isUserDirty">を使用して、マッピング内からその条件を簡単にテストできます。もちろんこれは非常に一般的なアプローチではなく、まともなhashCode()実装に依存します。 leonbloyのanswerを見て、より一般的なアプローチについて同様の質問をしてください。もちろん、これはやや単純すぎるかもしれません。特に、多対多の関係を話しているからです。どのアプローチが最も良いかは、あなたのケースに左右されます。

ここで何をすべきかを知っておく必要があります。がんばろう!

PSデルタを挿入して削除する代わりに、私は単純な上書きを助言します:すべてを削除し、すべてをトランザクションに挿入します。一時テーブル戦略は、データベースのパフォーマンスを実際には向上させることのできない最適化戦略ですが、実際は私の推測ではおそらくそれが悪化する可能性があります。あなたがこの戦略を適切にプロファイリングして、あなたがしていることを知っているなら、この追伸を無視するかもしれません。

関連する問題