Your SlideShare is downloading. ×
0
Springでdao 20070413
Springでdao 20070413
Springでdao 20070413
Springでdao 20070413
Springでdao 20070413
Springでdao 20070413
Springでdao 20070413
Springでdao 20070413
Springでdao 20070413
Springでdao 20070413
Springでdao 20070413
Springでdao 20070413
Springでdao 20070413
Springでdao 20070413
Springでdao 20070413
Springでdao 20070413
Springでdao 20070413
Springでdao 20070413
Springでdao 20070413
Springでdao 20070413
Springでdao 20070413
Springでdao 20070413
Springでdao 20070413
Springでdao 20070413
Springでdao 20070413
Springでdao 20070413
Springでdao 20070413
Springでdao 20070413
Springでdao 20070413
Springでdao 20070413
Springでdao 20070413
Springでdao 20070413
Springでdao 20070413
Springでdao 20070413
Springでdao 20070413
Springでdao 20070413
Springでdao 20070413
Springでdao 20070413
Springでdao 20070413
Springでdao 20070413
Springでdao 20070413
Springでdao 20070413
Springでdao 20070413
Springでdao 20070413
Springでdao 20070413
Springでdao 20070413
Springでdao 20070413
Springでdao 20070413
Springでdao 20070413
Springでdao 20070413
Springでdao 20070413
Springでdao 20070413
Springでdao 20070413
Springでdao 20070413
Springでdao 20070413
Springでdao 20070413
Springでdao 20070413
Upcoming SlideShare
Loading in...5
×

Thanks for flagging this SlideShare!

Oops! An error has occurred.

×
Saving this for later? Get the SlideShare app to save on your phone or tablet. Read anywhere, anytime – even offline.
Text the download link to your phone
Standard text messaging rates apply

Springでdao 20070413

1,436

Published on

大昔の資料が出てきた

大昔の資料が出てきた

0 Comments
3 Likes
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total Views
1,436
On Slideshare
0
From Embeds
0
Number of Embeds
0
Actions
Shares
0
Downloads
8
Comments
0
Likes
3
Embeds 0
No embeds

Report content
Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
No notes for slide

Transcript

  • 1. Spring で DAO船戸隆(エーティーエルシステムズ)鈴木雄介(アークランプ)
  • 2. 目的• Spring を使って DAO を使う方法を理解する• DAO を使う場合の注意点を理解する• 皆がどんな風に DAO を使っているのか共有する
  • 3. アジェンダ• DAO とは• DAO の設計• Spring で DAO – 実装 – 設定 – テスト• GenericDao with Spring• 気になること
  • 4. DAO とは
  • 5. DAO とは• Data Access Object の略 – J2EE パターンで 紹介 – 永続化層におい て様々なデータ ソースを抽象化 する – 今回は RDB ( JDBC) 前提 http://java.sun.com/blueprints/corej2eepatterns/Patterns/DataAccessObject.html
  • 6. DAO とは• メリット – SQL が集約されるためメンテナンス性が高い – TransferObject になるので Java コードから扱 いやすい。型重要• デメリット – 他層からデータアクセスの柔軟性が失われる – TransferObject を作成するコストが高い
  • 7. DAO の設計
  • 8. DAO の設計• DAO のインターフェース設計 – CRUD + Finder メソッド – パラメタオブジェクトを利用する – Tiger 便利 • TypeSafeEnum • Generics
  • 9. DAO の設計• CRUD + Finder メソッド – CRUD ( Create 、 Read 、 Update 、 Delete )は、 TransferObject をまるごとやりとり • Read は ID による検索 – ID 以外の検索は Finder メソッドとして、ある 程度の目的別に用意
  • 10. DAO の設計• パラメタオブジェクトを利用する – DAO の Finder メソッドにおいて、パラメタ が増えるたびにインターフェースが変わるの はいや – そこでパラメタオブジェクトとして抽象化 • パタメタが増えても、 DAO のインターフェースにpublic 影響を与えない interface BasicDao { List findByCriteria(BasicFindCriteria criteria);} public class BasicFindCriteria { private String someKey; }
  • 11. DAO の設計• Tiger 便利( JavaSE5 ) – 型重要 – TypeSafeEnum public enum AnyEnum { type1, type2 } – Generics public interface BasicDao { List<BasicTransferObject> findByCriteria(BasicFindCriteria criteria); }
  • 12. Spring で DAO
  • 13. Spring で DAO• 実装のコツ – 基本は ORM を使う – Spring の ORM サポートクラスを使う• 設定のコツ – AOP でトランザクション設定• テストのコツ – Spring で用意されたテストサポートクラスを 使う – DAO を使うクラスをテストする場合はモック を使う
  • 14. Spring で DAO – 実装
  • 15. Spring で DAO – 実装• 基本は ORM を使う – とりあえず便利 – でも無理に使うことはない• Spring の ORM サポートクラスを使う – Exception の違いを吸収 • Hibernate→HibernateException • iBATIS→SQLException – try catch を書かなくて済むのでコードがすっきり – 例外で処理を判定するコードは書かない • org.hibernate.NonUniqueObjectException で判定するな ど
  • 16. Spring で DAO – 実装• 実装の流れ – TransferObject を作る – DAO のインターフェースを作る – DAO の実装をする – マッピングファイル書く – Spring に Bean 定義する• ORM で実装サンプル – 今回は Hibernate 、 iBATIS そして・・・
  • 17. Spring で DAO – 実装• 実際に DAO を実装してみる CREATE TABLE ELECTRIC_GUITAR ( ID varchar(40) NOT NULL, NAME varchar(200) , MANUFACTURE varchar(20), CRAFTED_DATE datetime, PRICE int(11), PRIMARY KEY (ID) )
  • 18. Spring で DAO – 実装• TransferObject を作る public class ElectricGuitar { private String id; Java5 の Enum private String name; private ManufactureEnum manufacture; private Date craftedDate; private Integer price; ・ ・ ・
  • 19. Spring で DAO – 実装• DAO のインターフェースを作る public interface ElectricGuitarDao { List<ElectricGuitar> findAll(); ElectricGuitar load(String id); String insert(ElectricGuitar electricGuitar); void update(ElectricGuitar electricGuitar); void delete(ElectricGuitar electricGuitar); }
  • 20. Spring で DAO – 実装• Hibernate のサンプル public class ElectricGuitarHibernateDaoImpl extends HibernateDaoSupport implements ElectricGuitarDao { public List<ElectricGuitar> findAll() { return getHibernateTemplate().loadAll(ElectricGuitar.class); } ・ ・ ・
  • 21. Spring で DAO – 実装• マッピングファイルを書く – Hibernate のマッピングファイル src/main/resources/ElectricGuitar.hbm.xml<hibernate-mapping package="jp.springframework.vol2.domain"> <class name="ElectricGuitar" table="ELECTRIC_GUITAR"> <id name="id" column="ID" type="string" length="40"> <generator class="uuid" /> </id> <property name="name" column="NAME" type="string" length="200"/> <property name="manufacture" column="MANUFACTURE" type="jp.springframework.vol2.domain.enums.hibernate.ManufactureType“ length="20"/> <property name="craftedDate" column="CRAFTED_DATE" type="timestamp" /> <property name="price" column="PRICE" type="integer" /> </class>
  • 22. Spring で DAO – 実装 • Spring の設定をする –Spring の ApplicationContext の設定 src/main/resources/context/applicationContextHibernate.xml <bean id="electricGuitarDao" class="jp.springframework.vol2.dao.hibernate.ElectricGuitarHibernateDaoImpl"> <property name="sessionFactory" ref="sessionFactory"/> </bean> <bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean"> <property name="dataSource" ref="dataSource"/> <property name="mappingLocations"> <list> <value>classpath:hibernate/ElectricGuitar.hbm.xml</value> </list> </property>org.hibernate.SessionFactory を組み立てくれる
  • 23. Spring で DAO – 実装• iBATIS のサンプルpublic class ElectricGuitarIbatisDaoImpl extends SqlMapClientDaoSupport implements ElectricGuitarDao { public List<ElectricGuitar> findAll() { return getSqlMapClientTemplate().queryForList("ElectricGuitar.findAll"); } public ElectricGuitar load(String id) { return (ElectricGuitar) getSqlMapClientTemplate().queryForObject("ElectricGuitar.load", id); }   ・   ・   ・
  • 24. Spring で DAO – 実装• マッピングファイルを書く – iBATIS のマッピングファイル src/main/resources/ibatis/ElectricGuitar.sqlmap.xml <sqlMap namespace="ElectricGuitar"> <typeAlias alias="guitarParam" type="jp.springframework.vol2.domain.ElectricGuitar"/> <resultMap id="guitar" class="jp.springframework.vol2.domain.ElectricGuitar"> <result property="id" column="ID" /> <result property="name" column="NAME" /> <result property="manufacture" column="MANUFACTURE" typeHandler="ManufactureEnum"/> <result property="craftedDate" column="CRAFTED_DATE" /> <result property="price" column="PRICE" /> </resultMap> <select id="findAll" resultMap="guitar"> SELECT ID, NAME, MANUFACTURE, CRAFTED_DATE, PRICE FROM ELECTRIC_GUITAR </select>    ・    ・    ・
  • 25. Spring で DAO – 実装 • iBATIS の Spring 設定 src/main/resources/context/applicationContextIbatis.xml<bean id="sqlMapClient" class="org.springframework.orm.ibatis.SqlMapClientFactoryBean"> <property name="configLocation" value="classpath:ibatis/sqlmap-config.xml" /> <property name="dataSource" ref="dataSource" /></bean> com.ibatis.sqlmap.client. SqlMapClient を組み立てくれ る<bean id="electricGuitarDao" class="jp.springframework.vol2.dao.ibatis.ElectricGuitarIbatisDaoImpl"> <property name="sqlMapClient" ref="sqlMapClient"/></bean>
  • 26. Spring で DAO – 実装• Spring-S2DAO のサンプル – S2DAO はインターフェースのみで動作する ため実装クラスはありませんSpring-S2DaoVia:http://d.hatena.ne.jp/n-ichimura/
  • 27. Spring で DAO – 実装• S2DAO の設定 – 基本的に設定レス – Java ソースコードにメタデータを記述するだ け – メソッドを命名規則に合わせることで SQL 文 の記述が不要
  • 28. Spring で DAO – 実装• Spring-S2DAO の Spring の設定 <bean class="framework.autoregister.FileSystemBeanAutoRegister"> <property name="addPackageName"> <value>jp.springframework.vol2.dao</value> </property> <property name="addClassNames"> <value>.*Dao</value> </property> <property name="ignorePackageName"> <value>jp.springframework.vol2.dao</value> </property> <property name="ignoreClassNames"> <value>ElectricGuitarGenericDao,IteratorDao</value> </property> </bean> S2Container の AutoRegister に似た機能 ( org.seasar.framework.container.autoregister.FileSystemComponentAutoRegister ) なので個別に DAO の Bean 定義をしません
  • 29. Spring で DAO – 実装• ORM サポートクラスは他にもいろいろ – org.springframework.orm パッケージ以下 – Hibernate 、 iBATIS 、 TopLink 、 JPA 、 etc… 詳しくは
  • 30. Spring で DAO – 設定
  • 31. Spring で DAO – 設定 • AOP でトランザクション設定 – トランザクション単位を考えよう src/main/resources/context/applicationContext-transaction.xml <aop:config> <aop:advisor pointcut="execution(* *..*MyBusinessLogic.*(..))"     advice-ref="txAdvice"/> </aop:config> Spring 2.X から使え る <tx:advice id="txAdvice"> <tx:attributes> <tx:method name="calculateAmount" read-only="true"/> </tx:attributes> </tx:advice> ビジネスロジックにトランザクションをかけた場合その中の DAO のトランザクションはすべて同一になる
  • 32. Spring で DAO – テス ト
  • 33. Spring で DAO – テスト• Spring で用意されたテストサポートクラスを使う ( org.springframework.test.AbstractTransactionalDataS ourceSpringContextTests ) – Spring のコンテナを自動で初期化してくれる @Override protected String[] getConfigLocations() { return new String[] {"classpath:context/applicationContextHibernate.xml" }; } – Setter があれば自動で Inject してくれる private ElectricGuitarDao electricGuitarDao; public void setElectricGuitarDao(ElectricGuitarDao newElectricGuitarDao) { this.electricGuitarDao = newElectricGuitarDao; } – 自動でトランザクションの開始&ロールバック – テスト用 SQL 実行メソッドがある executeSqlScript("classpath:testdata.sql", false);
  • 34. Spring で DAO – テストHibernate 用 DAO のサンプルコード public class ElectricGuitarHibernateDaoImplTest extends AbstractTransactionalDataSourceSpringContextTests { private ElectricGuitarDao electricGuitarDao; public void setElectricGuitarDao(ElectricGuitarDao newElectricGuitarDao) { this.electricGuitarDao = newElectricGuitarDao; } @Override protected String[] getConfigLocations() { return new String[] {"classpath:context/applicationContextHibernate.xml" }; } public void testInsert() { ElectricGuitar guitar = new ElectricGuitar(); guitar.setManufacture(ManufactureEnum.fender); guitar.setName("56 Stratocaster"); guitar.setCraftedDate(new Date()); guitar.setPrice(264320); String id = this.electricGuitarDao.insert(guitar); assertEquals(id, this.electricGuitarDao.load(id).getId()); }        ・    ・
  • 35. Spring で DAO- テスト• DAO を使うクラスをテストする場 合はモックを使う – 圧倒的なパフォーマンスの差 • インテグレーションテストを行う際に 威力を発揮 • MyBusinessLogicDaoTest • MyBusinessLogicMockTest – 作業の非同期化 • DAO の実装なしでもビジネスロジック のテストを書ける
  • 36. Spring で DAO – テスト• モックを使った実装サンプル – ビジネスロジック( MyBusinessLogic )では、割 引入り合計金額計算( calcuateAmount )を行う
  • 37. Spring で DAO – テスト• easymock ( http://www.easymock.org/)• 手順 1. モックを準備 2.モックの動きを用意 3.テストを実施 4.モックの動きを確認
  • 38. Spring で DAO – テスト• 手順 1: モックを準備 private MyBusinessLogicImpl myBusinessLogicImpl; private ElectricGuitarDao mock; protected void setUp() { mock = createMock(ElectricGuitarDao.class); myBusinessLogicImpl = new MyBusinessLogicImpl(); myBusinessLogicImpl.setElectricGuitarDao(mock); }インターフェースを指定してモックを作る( static import も便利だよ) あとは普通に Inject するだ け
  • 39. Spring で DAO – テスト• 手順 2: モックの動きを用意 これを呼ばれる これが返るよ と、 ElectricGuitar a = new ElectricGuitar(); a.setManufacture(ManufactureEnum.gretsch); a.setPrice(100000); expect(mock.load("1")).andReturn(a); expectLastCall().times(2); それを 2 回 ElectricGuitar b = new ElectricGuitar(); b.setManufacture(ManufactureEnum.fender); b.setPrice(200000); expect(mock.load("2")).andReturn(b); これで用意完 replay(mock); 了
  • 40. Spring で DAO – テスト • 手順 3: テストを実施 – 普通にテストするだけlong amount = myBusinessLogicImpl.calculateAmount(new String[] {"1" });assertEquals(80000, amount);amount = myBusinessLogicImpl.calculateAmount(new String[] {"1", "2" });assertEquals(260000, amount);
  • 41. Spring で DAO – テスト• 手順 4: モックの動きを確認 – 用意した通りに動いたことを確認 verify(mock);
  • 42. GenericDao with Spring
  • 43. GenericDao with Spring• GenericDao とは – Generics と AOP を使った DAO 支援フレーム ワーク • http://www-06.ibm.com/jp/developerworks/java/060705/j_j-genericdao.shtml – 実装クラスレスで DAO が作れちゃう。 O/R マッパのラッパとして非常に便利 – Spring と一緒に使うべし • 今回は Hibernate を利用
  • 44. GenericDao with Spring• 実装サンプル – Generics を使うことで、型つきの CRUD メ ソッドが準備される – Finder メソッドは、メソッド名と同じ query を用意する
  • 45. GenericDao with Spring• インターフェースとマッピングファイル だけ interface ElectricGuitarGenericDao public extends GenericDao<ElectricGuitar, String>{ public ElectricGuitar findByName(String name); public List<ElectricGuitar> findAll(); } <hibernate-mapping package="jp.springframework.vol2.domain"> <class name="ElectricGuitar" table="ELECTRIC_GUITAR"> <id name="id" column="ID" type="string" length="40"> … </class> <query name="ElectricGuitar.findByName"> <![CDATA[select e from ElectricGuitar e where e.name = ? ]]> </query> <query name="ElectricGuitar.findAll"> <![CDATA[select e from ElectricGuitar e order by e.price]]> </query> </hibernate-mapping>
  • 46. GenericDao with Spring• 仕組み – CRUD の実装は普通 – Finder の実装は AOP• コード見てね
  • 47. 気になること
  • 48. 気になること• そもそも O/R マッパって遅い – マッピングコストが高い • 不必要な項目も取得してしまう• 現状では解決は難しい
  • 49. 気になること• 返値 List の Finder で OutOfMemory にな る – バッチ処理やファイルダウンロード処理であ りがち – レコードの数だけマッピングしてしまう• そういう場合は Iterator を使おう – next() するごとにマッピング
  • 50. 気になること• 複数レコードの更新・削除処理が遅い – CRUD しかないと、レコードの数だけ Update や Delete を繰り返し• 専用メソッドを用意しよう – Update 文や Delete 文 – StoredProcedure
  • 51. 気になること• キャッシュしたい – DAOでキャッシュ • Hibernate は自動でやってくれる • OSCache などで自分でキャッシュ
  • 52. 気になること• パフォーマンス計測したい – AOP をつかうと楽 • Bean 定義したクラスのメソッドの実行時間計測public class TraceInterceptor implements MethodInterceptor { private static Log log = LogFactory.getLog(TraceInterceptor.class); public static ThreadLocal<String> local = new ThreadLocal<String>(); public Object invoke(MethodInvocation invocation) throws Throwable { String key = local.get(); if ( StringUtils.isEmpty(key) || "null".equals(key) ) { key = UUID.randomUUID().toString(); local.set(key); } log.debug("," + key + "," + System.currentTimeMillis() + "," + getInvocationDescription(invocation) + ",start"); Object value = invocation.proceed(); log.debug("," + key + "," + System.currentTimeMillis() + "," + getInvocationDescription(invocation) + ",end"); return value; }
  • 53. 気になること• N+ 1問題 – 親レコードの数だけ子レコードを取得 する SQL が発行されてしまう • 注文と注文商品みたいな関係• Lazy ロードで回避できるが・・・ – トランザクション注意! • トランザクション終了前に子レコードを取 得する
  • 54. 気になること• SQL インジェクション攻撃• プリペアドステートメント推奨 – SQL の構造が変わらない – とはいっても素のステートメントも使 いたい・・・ • MySQL のクエリーキャッシュが効かない • 使う場合きちんとエスケープする
  • 55. 気になること• エンティティ露出問題 – ビュー層で必要とされるモデルとのミスマッチ • ビュー層でマスターデータ参照したい – マスターにある項目を表示したいのだけど TransferObject には ID しかはいっていない・・・ – 詰め替え問題 • DTO に誰がどこでつめなおすの? • ビジネスロジック層で泣きながら DTO につめる• 設計上の問題なので解決策があるわけではない
  • 56. Q&A
  • 57. ライセンスについて• JSUG マスコットアイコン(本スライド左下)が残されている場合に限り、本作品 (またそれを元にした派生作品)の複製・頒布・表示・上演を認めます。• 非商用目的に限り、本作品(またそれを元にした派生作品)の複製・頒布・表示・ 上演を認めます。• 本作品のライセンスを遵守する限り、派生作品を頒布することを許可します。

×