SlideShare une entreprise Scribd logo
1  sur  62
Spring 概要 データアクセスとトランザクション処理 for Beginner 2012/2/27
前回までのお話 ,[object Object],[object Object],[object Object],プレゼン テーション ビジネス ロジック データベース アクセス RDB ブラウザ 表示の仕組み 永続化の仕組み 業務の仕組み DI x AOP Spring MVC
今日お話しする部分 ,[object Object],[object Object],プレゼン テーション ビジネス ロジック データベース アクセス RDB ブラウザ 表示の仕組み 永続化の仕組み 業務の仕組み DI x AOP Spring MVC ココの部分
データアクセス層の一般的な話と Spring
デーアクセス層の役割 ,[object Object],[object Object],[object Object],プレゼン テーション ビジネス ロジック データベース アクセス RDB ブラウザ 表示の仕組み 永続化の仕組み 業務の仕組み
データアクセスの処理が混在した業務ロジック (1/3) ,[object Object],[object Object],業務ロジック 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 public void transfer(Account from, Account to, int furikomigaku) { Connection con = null; PreparedStatement ps = null; ResultSet rs = null; try { con = dataSource.getConnection(); con.setTransactionIsolation(Connection.TRANSACTION_SERIALIZABLE); // 振込元の残高が足りてるか確認 int zandaka = -1; ps = con.prepareStatement( &quot;select zandaka from account where account_num=?&quot;); ps.setString(1, from.getAccountNumnber()); rs = ps.executeQuery(); if (rs.next() == true) { zandaka = rs.getInt(&quot;zandaka&quot;); } else { throw new BussinessException(&quot; データがありません &quot;); } int newZandaka = zandaka - furikomigaku; if (newZandaka < 0) { throw new BussinessException(&quot; 残高が足りません &quot;); } from.setZandaka(newZandaka);
データアクセスの処理が混在した業務ロジック (2/3) 業務ロジック 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 //  振込先の口座の残高を計算 ps.clearParameters(); ps.setString(1, to.getAccountNumnber()); rs = ps.executeQuery(); if (rs.next() == true) { zandaka = rs.getInt(&quot;zandaka&quot;); } else { throw new BussinessException(&quot; データがありません &quot;); }  newZandaka = zandaka + furikomigaku; to.setZandaka(newZandaka); //  振込元の残高を更新 ps = con.prepareStatement( &quot;update account set zandaka=? where account_num=?&quot;); ps.setInt(1, from.getZandaka()); ps.setString(2, from.getAccountNumnber()); ps.execute(); //  振込先の残高を更新 ps.clearParameters(); ps.setInt(1, to.getZandaka()); ps.setString(2, to.getAccountNumnber()); ps.execute(); con.commit();
データアクセスの処理が混在した業務ロジック (3/3) 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 } catch (SQLException sqle) { try { con.rollback(); } catch (Exception e) { System.out.println(&quot; システムエラー &quot;+e); } int errorCode = sqle.getErrorCode(); if (errorCode == ERR_DEADLOCK) { throw new BussinessException(&quot; デッドロック発生 &quot;, sqle); } else { throw new SystemException(&quot; システムエラー &quot;, sqle); } } finally { try { con.close(); } catch (Exception e) { System.out.println(&quot; システムエラー &quot;+e); } } }
データアクセスの処理を分離させた業務ロジック ,[object Object],・データアクセス専用の部品 ・業務ロジックを含まない ・ DAO (Data Access Object) と呼ばれる 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 public void transfer(Account from, Account to, int furikomigaku) { //  振込元の残高を確認 int zandaka =  accountDao.getZandaka(from.getAccountNumnber()); int newZandaka = zandaka - furikomigaku; if (newZandaka < 0) { throw new BussinessException(&quot; 残高が足りません &quot;); } from.setZandaka(newZandaka); //  振込先の口座の残高を計算 zandaka =  accountDao.getZandaka(to.getAccountNumnber()); newZandaka = zandaka + furikomigaku; to.setZandaka(newZandaka); //  振込元の残高を更新 accountDao.updateZandaka(from); //  振込先の残高を更新 accountDao.updateZandaka(to); } AccountDao + getZandaka(accountNumber:String):int + updateZandaka(account:Account):void
DAO パターンとは? ,[object Object],[object Object],[object Object],[object Object],データ ベース アクセス ビジネス ロジック 使う AccountDao BankDao UserDao など CRUD が一通り 揃っている インターフェースを 用意 挿入メソッド 取得メソッド 更新メソッド 削除メソッド XXXDao
データアクセス技術のいろいろ ,[object Object],[object Object],データ ベース JDBC Hibernate iBATIS(mybatis) JPA JDO 自社フレームワーク ・ ・ S2Dao 挿入メソッド 取得メソッド 更新メソッド 削除メソッド XXXDao
データアクセスの Spring の機能 ,[object Object],データ ベース Spring JDBC JDBC Hibernate 連携 Hibernate JPA 連携 JPA iBATIS 連携 iBATIS(2.x) JDO 連携 JDO 挿入メソッド 取得メソッド 更新メソッド 削除メソッド XXXDao
Spring のデータアクセスの機能を使う利点 ,[object Object],[object Object],[object Object]
Spring JDBC
JDBC の問題 (1/3) ,[object Object],JDBC データ ベース + getZandaka(accountNumber:String):int + updateZandaka(account:Account):void AccountDao
JDBC の問題 (2/3) ,[object Object],・コード量が多い   Connection 、 PreparedStatement ・・  リソースの取得・解放が面倒 解放漏れの危険も getZandaka メソッド 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 public int getZandaka(String accountNumber) { Connection con = null; PreparedStatement ps = null; ResultSet rs = null; try { con = dataSource.getConnection(); int zandaka = -1; ps = con.prepareStatement(&quot;select zandaka from account where account_num=?&quot;); ps.setString(1, accountNumber); rs = ps.executeQuery(); if (rs.next() == true) { zandaka = rs.getInt(&quot;zandaka&quot;); } else { throw new BussinessException(&quot; データがありません &quot;); } return zandaka; } catch (SQLException sqle) { throw new SystemException(&quot; システムエラー &quot;, sqle); } finally { try { con.close(); } catch (Exception e) { System.out.println(&quot; システムエラー &quot;+e); } } }
JDBC の問題 (3/3) ・例外 SQLException の解釈が必要  原因を特定するためのエラーコードが    DB 製品毎に異なる updateZandaka メソッド 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 public void updateZandaka(Account account) { Connection con = null; PreparedStatement ps = null; ResultSet rs = null; try { con = dataSource.getConnection(); con.setTransactionIsolation(Connection.TRANSACTION_SERIALIZABLE); ps = con.prepareStatement(&quot;update account set zandaka=? where account_num=?&quot;); ps.setInt(1, account.getZandaka()); ps.setString(2, account.getAccountNumnber()); ps.execute(); con.commit(); } catch (SQLException sqle) { try { con.rollback(); } catch (Exception e) { System.out.println(&quot; システムエラー &quot; + e); } int errorCode = sqle.getErrorCode(); if (errorCode == ERR_DEADLOCK) { throw new BussinessException(&quot; デッドロック発生 &quot;, sqle); } else { throw new SystemException(&quot; システムエラー &quot;, sqle); } } finally { try { con.close(); } catch (Exception e) { System.out.println(&quot; システムエラー &quot; + e); } } }
Spring JDBC による解決 ,[object Object],[object Object],[object Object],[object Object],[object Object],Spring JDBC JDBC データ ベース 挿入メソッド 取得メソッド 更新メソッド 削除メソッド XXXDao
Template クラスを使ってコードをシンプルに ,[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object]
Template クラスの使い方 ,[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object]
Template クラスの Bean の準備 ・・・ <bean class=&quot;org.springframework.jdbc.core.JdbcTemplate&quot;> <property name=&quot;dataSource&quot; ref=&quot;dataSource&quot; /> </bean> <bean class=&quot;org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate&quot;> <property name=&quot;dataSource&quot; ref=&quot;dataSource&quot; /> </bean> <bean id=&quot;dataSource&quot; class=&quot;com.mchange.v2.c3p0.ComboPooledDataSource&quot;> <property name=&quot;driverClass&quot; value=&quot;oracle.jdbc.driver.OracleDriver&quot;/> <property name=&quot;jdbcUrl&quot; value=&quot;jdbc:oracle:thin:@localhost:1521:sample&quot;/> <property name=&quot;user&quot; value=&quot;spring3&quot;/> <property name=&quot;password&quot; value=&quot;spring3&quot;/> </bean> ・・・ ・・・ @Repository public class AccountDaoSpringJdbc implements AccountDao { @Autowired private JdbcTemplate jdbcTemplate; @Autowired private NamedParameterJdbcTemplate npJdbcTemplate; ・・・
クエリ ~エンティティクラスへ変換しない場合 (1/2) ,[object Object],[object Object],[object Object],int count = jdbcTemplate.queryForInt( &quot;select count(*) from pet&quot; ); int count = jdbcTemplate.queryForInt( &quot;select count(*) from pet where owner_name=?“  , ownerName); ・・・ public int getZandaka(String accountNumber) { int zandaka = jdbcTemplate.queryForInt( &quot;select zandaka from account where account_num=?&quot; , accountNumber); return zandaka; } ・・・ 【 AccountDao の getZandaka メソッドの場合】
クエリ ~エンティティクラスへ変換しない場合 (2/2) ,[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],String petName = jdbcTemplate.queryForObject( &quot;select pet_name from pet where pet_id=?&quot; , String.class, id); Date birthDate = jdbcTemplate.queryForObject( &quot;select birth_date from pet where pet_id=?&quot; , Date.class, id); Map<String, Object> pet = jdbcTemplate.queryForMap( &quot;select * from pet where pet_id=?&quot; , id); String petName = (String)pet.get(&quot;pet_name&quot;); List<Map<String, Object>> petList = jdbcTemplate.queryForList( &quot;select * from pet where owner_name=?&quot; , ownerName);
クエリ ~エンティティクラスへ変換する場合 (1/2 ) ,[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],※ 匿名クラス ※ 匿名クラス:「その場限り」のサブクラスもしくは実装クラス。名前が無い
≪ 補足≫匿名クラスを使わない書き方 class MyRowMapper implements RowMapper<Pet> { public Pet mapRow(ResultSet rs, int rowNum) throws SQLException { Pet p = new Pet(); p.setPetId(rs.getInt(&quot;pet_id&quot;)); p.setPetName(rs.getString(&quot;pet_name&quot;)); p.setOwnerName(rs.getString(&quot;owner_name&quot;)); return p; } } Pet pet = jdbcTemplate.queryForObject( &quot;select * from pet where pet_id=?&quot; ,new MyRowMapper() ,id);
RowMapper とシーケンス図
クエリ ~エンティティクラスへ変換する場合 (2/2) ,[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object]
インサート・アップデート・デリート ,[object Object],[object Object],[object Object],[object Object],jdbcTemplate.update( &quot;insert into pet (pet_id, pet_name, owner_name) values (?, ?, ?)&quot; , pet.getPetId(), pet.getPetName(), pet.getOwnerName()); jdbcTemplate.update( &quot;update pet set pet_name=?, owner_name=? where pet_id=?&quot; , pet.getPetName(), pet.getOwnerName(), pet.getPetId()); jdbcTemplate.update( &quot;delete from pet where pet_id=?“ , pet.getPetId());
NamedParameterJdbcTemplate を使った場合 ,[object Object],[object Object],npJdbcTemplate.update( &quot;insert into pet (pet_id, pet_name, owner_name)&quot; + &quot; values (:pet_id, :pet_name, :owner_name)&quot; ,new MapSqlParameterSource() .addValue(&quot;pet_id&quot;, pet.getPetId()) .addValue(&quot;pet_name&quot;, pet.getPetName()) .addValue(&quot;owner_name&quot;, pet.getOwnerName()) ); ※ メソッドチェーン:複数のメソッド呼び出しを1センテンスで記述するテクニック ※ メソッドチェーン
≪ 補足≫メソッドチェーンを使わないやり方 MapSqlParameterSource map = new MapSqlParameterSource(); map.addValue(&quot;pet_id&quot;, pet.getPetId()); map.addValue(&quot;pet_name&quot;, pet.getPetName()); map.addValue(&quot;owner_name&quot;, pet.getOwnerName()); npJdbcTemplate.update( &quot;insert into pet (pet_id, pet_name, owner_name)&quot; + &quot; values (:pet_id, :pet_name, :owner_name)&quot; ,map );
バッチアップデート ,[object Object],List<Object[]> args = new ArrayList<Object[]>(); for (Pet pet : petList) { args.add(new Object[]{pet.getOwnerName(), pet.getPetId()}); } int[] num = jdbcTemplate.batchUpdate( &quot;update pet set owner_name=? where pet_id=?“ , args);
プロシージャコール ,[object Object],[object Object],[object Object],[object Object],SimpleJdbcCall call = new SimpleJdbcCall(jdbcTemplate.getDataSource()); call.withProcedureName( &quot;calc_pet_price&quot; ); MapSqlParameterSource args = new MapSqlParameterSource() .addValue(&quot;pet_id&quot;, petId); Map<String, Object> out = call.execute(args); int price = (Integer)out.get(&quot;price&quot;);
汎用データアクセス例外で SQLException の解釈を不要に ,[object Object],[object Object],[object Object],[object Object],・・・ } catch (SQLException sqle) { int errorCode = sqle.getErrorCode(); if (errorCode == ERR_DATAINTEGRITY) { throw new DataIntegrityException(&quot; 整合性違反エラー発生 &quot;, sqle); } else if (errorCode == ERR_PERMISSION) { throw new DataPermissionException(“ 権限が不正 &quot;, sqle); } else if (errorCode ==  ・・・ ・・・
Spring の汎用データアクセス例外 ,[object Object],[object Object],[object Object],[object Object],【例外クラスの例 ( 全部で 20 個以上存在する ) 】 CannotAcquireLockException ロックの取得に失敗 ConcurrencyFailureException 同時実行時のエラー DataIntegrityViolationException 整合性違反エラー DeadlockLoserDataAccessException デッドロックが発生 EmptyResultDataAccessException 取得しようとしたデータが存在しない IncorrectResultSizeDataAccessException 取得したレコードの数が不正 OptimisticLockingFailureException 楽観的ロックに失敗 PermissionDeniedDataAccessException 権限エラー
汎用データアクセス例外のハンドリングの方針 ,[object Object],[object Object],[object Object],プレゼン テーション ビジネス ロジック データベース アクセス RDB ブラウザ サービス DAO コントローラ 共 通 対応可能な例外のみ catch 対応可能な例外のみ catch 対処できない例外は一元的に処理
データソース ,[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object]
データソースの使い方 ,[object Object],[object Object],・・・ <bean id=&quot;dataSource&quot; > ・・・ </bean> ・・・ ・・・ <bean id=“foo&quot; > <property name=&quot;dataSource&quot; ref=&quot;dataSource&quot; /> </bean> ・・・ ・・・ @Autowired private DataSource dataSource; ・・・
Spring が提供する DataSource ,[object Object],[object Object],[object Object],[object Object],注意) テスト用途で用意されたものなので本番で使用するものではない <bean id=&quot;dataSource&quot; class=&quot;org.springframework.jdbc.datasource.DriverManagerDataSource&quot;> <property name=&quot;driverClassName&quot; value=&quot;org.postgresql.Driver&quot; /> <property name=&quot;url&quot; value=&quot;jdbc:postgresql://localhost/samaple&quot; /> <property name=&quot;username&quot; value=&quot;spring3&quot; /> <property name=&quot;password&quot; value=&quot;spring3&quot; /> </bean> 【 DriverManagerDataSource の 設定の例 】
サードパーティ が提供する DataSource ,[object Object],[object Object],[object Object],[object Object],<bean id=&quot;dataSource&quot; class=&quot;com.mchange.v2.c3p0.ComboPooledDataSource&quot; destroy-method=&quot;close&quot;> <property name=&quot;driverClass&quot; value=&quot;org.postgresql.Driver&quot; /> <property name=&quot;jdbcUrl&quot; value=&quot;jdbc:postgresql://localhost/sample&quot; /> <property name=&quot;user&quot; value=&quot;spring3&quot; /> <property name=&quot;password&quot; value=&quot;spring3&quot; /> <property name=&quot;maxPoolSize&quot; value=&quot;20&quot;/> </bean> 【 c3p0 の 設定の例 】
AP サーバ が提供する DataSource ,[object Object],[object Object],[object Object],[object Object],<bean id=&quot;dataSource&quot; class=&quot;org.springframework.jndi.JndiObjectFactoryBean&quot;> <property name=&quot;jndiName&quot; value=&quot;jdbc/MyDataSource&quot;/> </bean> <jee:jndi-lookup id=&quot;dataSource&quot;  jndi-name=&quot;jdbc/MyDataSource&quot; /> <bean class=&quot;org.springframework.context.annotation.CommonAnnotationBeanPostProcessor&quot;> <property name=&quot;alwaysUseJndiLookup&quot; value=&quot;true&quot;/> </bean> @Resource(name=“jdbc/MyDataSource”) private DataSource dataSource; Common Anotations(JSR250) 用の 設定が必要
トランザクション機能
トランザクションとは? ,[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],ACID 意味 解説 Atomic トランザクションの原子性 トランザクション内の全ての処理は、全ておこなわれたか、もしくは何もおこなわれなかったかのどちらかだけであること。 Consistent  データの一貫性 データに一貫性があること。一貫性を守ってない例:親テーブルがないのに子テーブルがある。 Isolated  トランザクションの独立性 平行して走るトランザクションが互いに独立していること。 Durable データの永続性 データが永続化されていること。永続化されているデータが読み出せること。
Web アプリのトランザクション処理 ,[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object]
トランザクションの境界 ,[object Object],[object Object],[object Object],[object Object],[object Object],プレゼン テーション ビジネス ロジック データベース アクセス RDB ブラウザ サービス DAO コントローラ トランザクションの開始 トランザクションの終了
実装する場所の問題 ,[object Object],[object Object],[object Object],[object Object],[object Object],:ビジネスロジック : AccountDao transfer updateZandaka( 振込元 ) updateZandaka( 振込先 )
問題 ,[object Object],[object Object],[object Object]
AOP を使用したトランザクション処理 ,[object Object],クライアント トランザクション 処理 サービス DAO RDB トランザクションの開始 トランザクションのコミット サービスの Proxy
トランザクションマネージャ ,[object Object],[object Object],[object Object],[object Object],[object Object],[object Object]
トランザクション定義情報 ,[object Object],[object Object],[object Object],[object Object],[object Object],[object Object]
伝搬属性 ,[object Object],サービス2 サービス1 DAO 1 DAO 2 コントローラ2 コントローラ1 ① ② 伝搬 属性 サービス1に対して設定を行ったとき ① の場合 ② の場合 PROPAGATION_REQUIRED トランザクションを開始 サービス2のトランザクションを利用 PROPAGATION_REQUIRES_NEW トランザクションを開始 新しいトランザクションを開始 PROPAGATION_SUPPORTS トランザクションを行わない サービス2のトランザクションを利用 PROPAGATION_MANDATORY 例外を投げる サービス2のトランザクションを利用 PROPAGATION_NESTED トランザクションを開始 部分的なトランザクションを開始 (save ポイント ) PROPAGATION_NEVER トランザクションを行わない 例外を投げる PROPAGATION_NOT_SUPPORTED トランザクションを行わない トランザクションを行わない
独立性レベル ,[object Object],トランザクション1 トランザクション2 独立性レベル 解説 ISOLATION_READ_COMMITTED 他のトランザクションが変更したがまだコミットしていないデータは読み出せない。 ISOLATION_READ_UNCOMMITTED 他のトランザクションが変更したがまだコミットしていないデータを読み出せる。 ISORATION_REPEATABLE_READ トランザクション内で複数回データを読み込んだ場合、他のトランザクションが途中でデータを変更しても同じ値が読み込まれる ISORATION_SERIALIZABLE トランザクションを完全に独立させる ISOLATION_DEFAULT データベースが提供するデフォルトの独立性レベルを利用する。
データが矛盾した状態と独立性レベル ,[object Object],[object Object],○ :許す  × :許さない Dirty Read 他のトランザクションが変更したがまだコミットしていないデータを読み出してしまう Unrepeatable Read トランザクションの中で同じデータを複数回読み出す際、他のトランザクションが当該データを変更すると、以前に読み出したときと違ったデータを読み出してしまう。 Phantom Read トランザクションの中で同じデータを複数回読み出す際、他のトランザクションが新しくレコードを追加すると、以前に読み出したときに無かったレコードを読み出してしまう。 独立性レベル Dirty Read Unrepeatable Read Phantom Read ISOLATION_READ_UNCOMMITTED ○ ○ ○ ISOLATION_READ_COMMITTED × ○ ○ ISORATION_REPEATABLE_READ × × ○ ISORATION_SERIALIZABLE × × ×
その他のトランザクション定義情報 ,[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object]
トランザクションマネージャの実装 ≪ Interface≫ PlatformTransactionManager DataSourceTransactionManager HibernateTransactionManager JtaTransactionManager JpaTransactionManager JdoTransactionManager データアクセス技術に合わせて 適切なトランザクションマネージャを 選択する
トランザクションマネージャの登録 ,[object Object],・・・ <bean id=&quot;transactionManager&quot; class=&quot;org.springframework.jdbc.datasource.DataSourceTransactionManager&quot;> <property name=&quot;dataSource&quot; ref=&quot;dataSource&quot; /> </bean> ・・・ DataSourceTransactionManager の例
2種類の使い方 ,[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object]
宣言的トランザクションの設定 (Bean 定義ファイル ) ,[object Object],[object Object],<aop:config> <aop:advisor advice-ref=&quot;transactionAdvice&quot; pointcut=&quot;execution(* *..*Service.*(..))&quot; /> </aop:config> <tx:advice id=&quot;transactionAdvice&quot; transaction-manager=&quot;transactionManager&quot;> <tx:attributes> <tx:method name=&quot;get*&quot; read-only=&quot;true&quot; /> <tx:method name=&quot;update*&quot;  propagation=&quot;REQUIRED&quot;  isolation=&quot;READ_COMMITTED&quot; timeout=&quot;10&quot;  read-only=&quot;false&quot; rollback-for=“SystemException&quot; /> </tx:attributes> </tx:advice>
宣言的トランザクションの設定 ( アノテーション ) ,[object Object],[object Object],@Transactional( propagation=Propagation.REQUIRED,  isolation=Isolation.READ_COMMITTED,  timeout=10,  readOnly=false,  rollbackForClassName=&quot;BusinessException&quot; ) public void updatePet(Pet pet) throws BusinessException { ・・・省略 }
明示的トランザクションの使い方 ,[object Object],@Autowired private PlatformTransactionManager txManager; public void transfer(Account from, Account to, int furikomigaku) { DefaultTransactionDefinition def = new DefaultTransactionDefinition(); def.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED); def.setIsolationLevel(TransactionDefinition.ISOLATION_READ_COMMITTED); def.setTimeout(10); def.setReadOnly(false); TransactionStatus status = txManager.getTransaction(def); try { //  業務ロジック・・・ } catch (RuntimeException e) { txManager.rollback(status); throw e; } txManager.commit(status); }
明示的トランザクションの利用シーンの例 ,[object Object],[object Object],:クライアント : Proxy :サービス updatePet updatePet トランザクション開始 トランザクション終了 「○」 Proxy を介すためトランザクション処理が行われる 「 × 」 Proxy を介さないためトランザクション処理が行われない updateInternal
ご清聴ありがとうございました
ライセンスについて ,[object Object],[object Object],[object Object]

Contenu connexe

Tendances

Tendances (20)

Java ORマッパー選定のポイント #jsug
Java ORマッパー選定のポイント #jsugJava ORマッパー選定のポイント #jsug
Java ORマッパー選定のポイント #jsug
 
SPAセキュリティ入門~PHP Conference Japan 2021
SPAセキュリティ入門~PHP Conference Japan 2021SPAセキュリティ入門~PHP Conference Japan 2021
SPAセキュリティ入門~PHP Conference Japan 2021
 
さくっと理解するSpring bootの仕組み
さくっと理解するSpring bootの仕組みさくっと理解するSpring bootの仕組み
さくっと理解するSpring bootの仕組み
 
怖くないSpring Bootのオートコンフィグレーション
怖くないSpring Bootのオートコンフィグレーション怖くないSpring Bootのオートコンフィグレーション
怖くないSpring Bootのオートコンフィグレーション
 
決済サービスのSpring Bootのバージョンを2系に上げた話
決済サービスのSpring Bootのバージョンを2系に上げた話決済サービスのSpring Bootのバージョンを2系に上げた話
決済サービスのSpring Bootのバージョンを2系に上げた話
 
Spring Fest 2018 Spring Bootで作るRESTful Web Service
Spring Fest 2018 Spring Bootで作るRESTful Web ServiceSpring Fest 2018 Spring Bootで作るRESTful Web Service
Spring Fest 2018 Spring Bootで作るRESTful Web Service
 
Dockerfileを改善するためのBest Practice 2019年版
Dockerfileを改善するためのBest Practice 2019年版Dockerfileを改善するためのBest Practice 2019年版
Dockerfileを改善するためのBest Practice 2019年版
 
Spring Day 2016 - Web API アクセス制御の最適解
Spring Day 2016 - Web API アクセス制御の最適解Spring Day 2016 - Web API アクセス制御の最適解
Spring Day 2016 - Web API アクセス制御の最適解
 
Spring Bootをはじめる時にやるべき10のこと
Spring Bootをはじめる時にやるべき10のことSpring Bootをはじめる時にやるべき10のこと
Spring Bootをはじめる時にやるべき10のこと
 
Kubernetesのしくみ やさしく学ぶ 内部構造とアーキテクチャー
Kubernetesのしくみ やさしく学ぶ 内部構造とアーキテクチャーKubernetesのしくみ やさしく学ぶ 内部構造とアーキテクチャー
Kubernetesのしくみ やさしく学ぶ 内部構造とアーキテクチャー
 
REST API のコツ
REST API のコツREST API のコツ
REST API のコツ
 
人生がときめくAPIテスト自動化 with Karate
人生がときめくAPIテスト自動化 with Karate人生がときめくAPIテスト自動化 with Karate
人生がときめくAPIテスト自動化 with Karate
 
初心者向けMongoDBのキホン!
初心者向けMongoDBのキホン!初心者向けMongoDBのキホン!
初心者向けMongoDBのキホン!
 
オススメのJavaログ管理手法 ~コンテナ編~(Open Source Conference 2022 Online/Spring 発表資料)
オススメのJavaログ管理手法 ~コンテナ編~(Open Source Conference 2022 Online/Spring 発表資料)オススメのJavaログ管理手法 ~コンテナ編~(Open Source Conference 2022 Online/Spring 発表資料)
オススメのJavaログ管理手法 ~コンテナ編~(Open Source Conference 2022 Online/Spring 発表資料)
 
ドメイン駆動設計のための Spring の上手な使い方
ドメイン駆動設計のための Spring の上手な使い方ドメイン駆動設計のための Spring の上手な使い方
ドメイン駆動設計のための Spring の上手な使い方
 
単なるキャッシュじゃないよ!?infinispanの紹介
単なるキャッシュじゃないよ!?infinispanの紹介単なるキャッシュじゃないよ!?infinispanの紹介
単なるキャッシュじゃないよ!?infinispanの紹介
 
Keycloak入門
Keycloak入門Keycloak入門
Keycloak入門
 
Spring bootでweb セキュリティ(ログイン認証)編
Spring bootでweb セキュリティ(ログイン認証)編Spring bootでweb セキュリティ(ログイン認証)編
Spring bootでweb セキュリティ(ログイン認証)編
 
今さら聞けないDiとspring
今さら聞けないDiとspring今さら聞けないDiとspring
今さら聞けないDiとspring
 
Fluentdのお勧めシステム構成パターン
Fluentdのお勧めシステム構成パターンFluentdのお勧めシステム構成パターン
Fluentdのお勧めシステム構成パターン
 

En vedette (7)

Spring3.1概要 AOP & MVC
Spring3.1概要 AOP & MVCSpring3.1概要 AOP & MVC
Spring3.1概要 AOP & MVC
 
Spring3.1概要x di
Spring3.1概要x diSpring3.1概要x di
Spring3.1概要x di
 
Sevletとjsp
SevletとjspSevletとjsp
Sevletとjsp
 
Javaの基本 基本データ型編
Javaの基本 基本データ型編Javaの基本 基本データ型編
Javaの基本 基本データ型編
 
システムアーキテクト~My batis編~
システムアーキテクト~My batis編~システムアーキテクト~My batis編~
システムアーキテクト~My batis編~
 
O/Rマッパーによるトラブルを未然に防ぐ
O/Rマッパーによるトラブルを未然に防ぐO/Rマッパーによるトラブルを未然に防ぐ
O/Rマッパーによるトラブルを未然に防ぐ
 
SXSW 2016 takeaways
SXSW 2016 takeawaysSXSW 2016 takeaways
SXSW 2016 takeaways
 

Similaire à Spring3.1概要 データアクセスとトランザクション処理

データマイニング+WEB勉強会資料第6回
データマイニング+WEB勉強会資料第6回データマイニング+WEB勉強会資料第6回
データマイニング+WEB勉強会資料第6回
Naoyuki Yamada
 
Tech Ed 2010 Japan T1-310 Microsoft Online Services 展開時の実践テクニック
Tech Ed 2010 Japan T1-310 Microsoft Online Services 展開時の実践テクニックTech Ed 2010 Japan T1-310 Microsoft Online Services 展開時の実践テクニック
Tech Ed 2010 Japan T1-310 Microsoft Online Services 展開時の実践テクニック
kumo2010
 

Similaire à Spring3.1概要 データアクセスとトランザクション処理 (20)

データマイニング+WEB勉強会資料第6回
データマイニング+WEB勉強会資料第6回データマイニング+WEB勉強会資料第6回
データマイニング+WEB勉強会資料第6回
 
Let's build a simple app with .net 6 asp.net core web api, react, and elasti...
Let's build a simple app with  .net 6 asp.net core web api, react, and elasti...Let's build a simple app with  .net 6 asp.net core web api, react, and elasti...
Let's build a simple app with .net 6 asp.net core web api, react, and elasti...
 
Inside mobage platform
Inside mobage platformInside mobage platform
Inside mobage platform
 
Develop Web Application with Node.js + Express
Develop Web Application with Node.js + ExpressDevelop Web Application with Node.js + Express
Develop Web Application with Node.js + Express
 
PowerShellを使用したWindows Serverの管理
PowerShellを使用したWindows Serverの管理PowerShellを使用したWindows Serverの管理
PowerShellを使用したWindows Serverの管理
 
リアルFacebookガジェットを作った(ロングバージョン)
リアルFacebookガジェットを作った(ロングバージョン)リアルFacebookガジェットを作った(ロングバージョン)
リアルFacebookガジェットを作った(ロングバージョン)
 
[db tech showcase Tokyo 2017] D15: ビッグデータ x 機械学習の高速分析をVerticaで実現!by ヒューレット・パッ...
[db tech showcase Tokyo 2017] D15: ビッグデータ x 機械学習の高速分析をVerticaで実現!by ヒューレット・パッ...[db tech showcase Tokyo 2017] D15: ビッグデータ x 機械学習の高速分析をVerticaで実現!by ヒューレット・パッ...
[db tech showcase Tokyo 2017] D15: ビッグデータ x 機械学習の高速分析をVerticaで実現!by ヒューレット・パッ...
 
Apache Torqueについて
Apache TorqueについてApache Torqueについて
Apache Torqueについて
 
Seasarプロジェクト徹底攻略
Seasarプロジェクト徹底攻略Seasarプロジェクト徹底攻略
Seasarプロジェクト徹底攻略
 
仕事で使うちょっとしたコードをOSSとして開発メンテしていく - Django Redshift Backend の開発 - PyCon JP 2016
仕事で使うちょっとしたコードをOSSとして開発メンテしていく- Django Redshift Backend の開発 - PyCon JP 2016仕事で使うちょっとしたコードをOSSとして開発メンテしていく- Django Redshift Backend の開発 - PyCon JP 2016
仕事で使うちょっとしたコードをOSSとして開発メンテしていく - Django Redshift Backend の開発 - PyCon JP 2016
 
Metaprogramming Universe in C# - 実例に見るILからRoslynまでの活用例
Metaprogramming Universe in C# - 実例に見るILからRoslynまでの活用例Metaprogramming Universe in C# - 実例に見るILからRoslynまでの活用例
Metaprogramming Universe in C# - 実例に見るILからRoslynまでの活用例
 
Spark Analytics - スケーラブルな分散処理
Spark Analytics - スケーラブルな分散処理Spark Analytics - スケーラブルな分散処理
Spark Analytics - スケーラブルな分散処理
 
DB Tech showcase Tokyo 2015 Works Applications
DB Tech showcase Tokyo 2015 Works ApplicationsDB Tech showcase Tokyo 2015 Works Applications
DB Tech showcase Tokyo 2015 Works Applications
 
WebRTC getStats - WebRTC Meetup Tokyo 5 LT
WebRTC getStats - WebRTC Meetup Tokyo 5 LTWebRTC getStats - WebRTC Meetup Tokyo 5 LT
WebRTC getStats - WebRTC Meetup Tokyo 5 LT
 
Tech Ed 2010 Japan T1-310 Microsoft Online Services 展開時の実践テクニック
Tech Ed 2010 Japan T1-310 Microsoft Online Services 展開時の実践テクニックTech Ed 2010 Japan T1-310 Microsoft Online Services 展開時の実践テクニック
Tech Ed 2010 Japan T1-310 Microsoft Online Services 展開時の実践テクニック
 
[Cloud OnAir] 最新アップデート Google Cloud データ関連ソリューション 2020年5月14日 放送
[Cloud OnAir] 最新アップデート Google Cloud データ関連ソリューション 2020年5月14日 放送[Cloud OnAir] 最新アップデート Google Cloud データ関連ソリューション 2020年5月14日 放送
[Cloud OnAir] 最新アップデート Google Cloud データ関連ソリューション 2020年5月14日 放送
 
AppExchangeパートナー&デベロッパー第2部:20070523版
AppExchangeパートナー&デベロッパー第2部:20070523版AppExchangeパートナー&デベロッパー第2部:20070523版
AppExchangeパートナー&デベロッパー第2部:20070523版
 
EC-CUBEプラグイン講義
EC-CUBEプラグイン講義EC-CUBEプラグイン講義
EC-CUBEプラグイン講義
 
zozotown real time linkage infrastructure
zozotown real time linkage infrastructurezozotown real time linkage infrastructure
zozotown real time linkage infrastructure
 
クラウド時代の並列分散処理技術
クラウド時代の並列分散処理技術クラウド時代の並列分散処理技術
クラウド時代の並列分散処理技術
 

Plus de 土岐 孝平

試験にでるSpring
試験にでるSpring試験にでるSpring
試験にでるSpring
土岐 孝平
 

Plus de 土岐 孝平 (10)

What's new in Spring Boot 2.6 ?
What's new in Spring Boot 2.6 ?What's new in Spring Boot 2.6 ?
What's new in Spring Boot 2.6 ?
 
SpringベースのCloud Native Application
SpringベースのCloud Native ApplicationSpringベースのCloud Native Application
SpringベースのCloud Native Application
 
Spring fest2020 spring-security
Spring fest2020 spring-securitySpring fest2020 spring-security
Spring fest2020 spring-security
 
Microserviceの今どきのインフラを探る
Microserviceの今どきのインフラを探るMicroserviceの今どきのインフラを探る
Microserviceの今どきのインフラを探る
 
OpenID Connect入門
OpenID Connect入門OpenID Connect入門
OpenID Connect入門
 
Springを使ったwebアプリにリファクタリングしよう
Springを使ったwebアプリにリファクタリングしようSpringを使ったwebアプリにリファクタリングしよう
Springを使ったwebアプリにリファクタリングしよう
 
業務システムとマイクロサービス
業務システムとマイクロサービス業務システムとマイクロサービス
業務システムとマイクロサービス
 
エッセンシャルCore springハンズオン
エッセンシャルCore springハンズオンエッセンシャルCore springハンズオン
エッセンシャルCore springハンズオン
 
試験にでるSpring
試験にでるSpring試験にでるSpring
試験にでるSpring
 
vFabricを触ろう
vFabricを触ろうvFabricを触ろう
vFabricを触ろう
 

Dernier

Dernier (12)

Observabilityは従来型の監視と何が違うのか(キンドリルジャパン社内勉強会:2022年10月27日発表)
Observabilityは従来型の監視と何が違うのか(キンドリルジャパン社内勉強会:2022年10月27日発表)Observabilityは従来型の監視と何が違うのか(キンドリルジャパン社内勉強会:2022年10月27日発表)
Observabilityは従来型の監視と何が違うのか(キンドリルジャパン社内勉強会:2022年10月27日発表)
 
Amazon SES を勉強してみる その22024/04/26の勉強会で発表されたものです。
Amazon SES を勉強してみる その22024/04/26の勉強会で発表されたものです。Amazon SES を勉強してみる その22024/04/26の勉強会で発表されたものです。
Amazon SES を勉強してみる その22024/04/26の勉強会で発表されたものです。
 
LoRaWANスマート距離検出センサー DS20L カタログ LiDARデバイス
LoRaWANスマート距離検出センサー  DS20L  カタログ  LiDARデバイスLoRaWANスマート距離検出センサー  DS20L  カタログ  LiDARデバイス
LoRaWANスマート距離検出センサー DS20L カタログ LiDARデバイス
 
Utilizing Ballerina for Cloud Native Integrations
Utilizing Ballerina for Cloud Native IntegrationsUtilizing Ballerina for Cloud Native Integrations
Utilizing Ballerina for Cloud Native Integrations
 
知識ゼロの営業マンでもできた!超速で初心者を脱する、悪魔的学習ステップ3選.pptx
知識ゼロの営業マンでもできた!超速で初心者を脱する、悪魔的学習ステップ3選.pptx知識ゼロの営業マンでもできた!超速で初心者を脱する、悪魔的学習ステップ3選.pptx
知識ゼロの営業マンでもできた!超速で初心者を脱する、悪魔的学習ステップ3選.pptx
 
論文紹介:Selective Structured State-Spaces for Long-Form Video Understanding
論文紹介:Selective Structured State-Spaces for Long-Form Video Understanding論文紹介:Selective Structured State-Spaces for Long-Form Video Understanding
論文紹介:Selective Structured State-Spaces for Long-Form Video Understanding
 
論文紹介:Video-GroundingDINO: Towards Open-Vocabulary Spatio-Temporal Video Groun...
論文紹介:Video-GroundingDINO: Towards Open-Vocabulary Spatio-Temporal Video Groun...論文紹介:Video-GroundingDINO: Towards Open-Vocabulary Spatio-Temporal Video Groun...
論文紹介:Video-GroundingDINO: Towards Open-Vocabulary Spatio-Temporal Video Groun...
 
Amazon SES を勉強してみる その32024/04/26の勉強会で発表されたものです。
Amazon SES を勉強してみる その32024/04/26の勉強会で発表されたものです。Amazon SES を勉強してみる その32024/04/26の勉強会で発表されたものです。
Amazon SES を勉強してみる その32024/04/26の勉強会で発表されたものです。
 
NewSQLの可用性構成パターン(OCHaCafe Season 8 #4 発表資料)
NewSQLの可用性構成パターン(OCHaCafe Season 8 #4 発表資料)NewSQLの可用性構成パターン(OCHaCafe Season 8 #4 発表資料)
NewSQLの可用性構成パターン(OCHaCafe Season 8 #4 発表資料)
 
LoRaWAN スマート距離検出デバイスDS20L日本語マニュアル
LoRaWAN スマート距離検出デバイスDS20L日本語マニュアルLoRaWAN スマート距離検出デバイスDS20L日本語マニュアル
LoRaWAN スマート距離検出デバイスDS20L日本語マニュアル
 
新人研修 後半 2024/04/26の勉強会で発表されたものです。
新人研修 後半        2024/04/26の勉強会で発表されたものです。新人研修 後半        2024/04/26の勉強会で発表されたものです。
新人研修 後半 2024/04/26の勉強会で発表されたものです。
 
論文紹介: The Surprising Effectiveness of PPO in Cooperative Multi-Agent Games
論文紹介: The Surprising Effectiveness of PPO in Cooperative Multi-Agent Games論文紹介: The Surprising Effectiveness of PPO in Cooperative Multi-Agent Games
論文紹介: The Surprising Effectiveness of PPO in Cooperative Multi-Agent Games
 

Spring3.1概要 データアクセスとトランザクション処理

  • 2.
  • 3.
  • 5.
  • 6.
  • 7. データアクセスの処理が混在した業務ロジック (2/3) 業務ロジック 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 // 振込先の口座の残高を計算 ps.clearParameters(); ps.setString(1, to.getAccountNumnber()); rs = ps.executeQuery(); if (rs.next() == true) { zandaka = rs.getInt(&quot;zandaka&quot;); } else { throw new BussinessException(&quot; データがありません &quot;); } newZandaka = zandaka + furikomigaku; to.setZandaka(newZandaka); //  振込元の残高を更新 ps = con.prepareStatement( &quot;update account set zandaka=? where account_num=?&quot;); ps.setInt(1, from.getZandaka()); ps.setString(2, from.getAccountNumnber()); ps.execute(); // 振込先の残高を更新 ps.clearParameters(); ps.setInt(1, to.getZandaka()); ps.setString(2, to.getAccountNumnber()); ps.execute(); con.commit();
  • 8. データアクセスの処理が混在した業務ロジック (3/3) 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 } catch (SQLException sqle) { try { con.rollback(); } catch (Exception e) { System.out.println(&quot; システムエラー &quot;+e); } int errorCode = sqle.getErrorCode(); if (errorCode == ERR_DEADLOCK) { throw new BussinessException(&quot; デッドロック発生 &quot;, sqle); } else { throw new SystemException(&quot; システムエラー &quot;, sqle); } } finally { try { con.close(); } catch (Exception e) { System.out.println(&quot; システムエラー &quot;+e); } } }
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 15.
  • 16.
  • 17. JDBC の問題 (3/3) ・例外 SQLException の解釈が必要  原因を特定するためのエラーコードが    DB 製品毎に異なる updateZandaka メソッド 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 public void updateZandaka(Account account) { Connection con = null; PreparedStatement ps = null; ResultSet rs = null; try { con = dataSource.getConnection(); con.setTransactionIsolation(Connection.TRANSACTION_SERIALIZABLE); ps = con.prepareStatement(&quot;update account set zandaka=? where account_num=?&quot;); ps.setInt(1, account.getZandaka()); ps.setString(2, account.getAccountNumnber()); ps.execute(); con.commit(); } catch (SQLException sqle) { try { con.rollback(); } catch (Exception e) { System.out.println(&quot; システムエラー &quot; + e); } int errorCode = sqle.getErrorCode(); if (errorCode == ERR_DEADLOCK) { throw new BussinessException(&quot; デッドロック発生 &quot;, sqle); } else { throw new SystemException(&quot; システムエラー &quot;, sqle); } } finally { try { con.close(); } catch (Exception e) { System.out.println(&quot; システムエラー &quot; + e); } } }
  • 18.
  • 19.
  • 20.
  • 21. Template クラスの Bean の準備 ・・・ <bean class=&quot;org.springframework.jdbc.core.JdbcTemplate&quot;> <property name=&quot;dataSource&quot; ref=&quot;dataSource&quot; /> </bean> <bean class=&quot;org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate&quot;> <property name=&quot;dataSource&quot; ref=&quot;dataSource&quot; /> </bean> <bean id=&quot;dataSource&quot; class=&quot;com.mchange.v2.c3p0.ComboPooledDataSource&quot;> <property name=&quot;driverClass&quot; value=&quot;oracle.jdbc.driver.OracleDriver&quot;/> <property name=&quot;jdbcUrl&quot; value=&quot;jdbc:oracle:thin:@localhost:1521:sample&quot;/> <property name=&quot;user&quot; value=&quot;spring3&quot;/> <property name=&quot;password&quot; value=&quot;spring3&quot;/> </bean> ・・・ ・・・ @Repository public class AccountDaoSpringJdbc implements AccountDao { @Autowired private JdbcTemplate jdbcTemplate; @Autowired private NamedParameterJdbcTemplate npJdbcTemplate; ・・・
  • 22.
  • 23.
  • 24.
  • 25. ≪ 補足≫匿名クラスを使わない書き方 class MyRowMapper implements RowMapper<Pet> { public Pet mapRow(ResultSet rs, int rowNum) throws SQLException { Pet p = new Pet(); p.setPetId(rs.getInt(&quot;pet_id&quot;)); p.setPetName(rs.getString(&quot;pet_name&quot;)); p.setOwnerName(rs.getString(&quot;owner_name&quot;)); return p; } } Pet pet = jdbcTemplate.queryForObject( &quot;select * from pet where pet_id=?&quot; ,new MyRowMapper() ,id);
  • 27.
  • 28.
  • 29.
  • 30. ≪ 補足≫メソッドチェーンを使わないやり方 MapSqlParameterSource map = new MapSqlParameterSource(); map.addValue(&quot;pet_id&quot;, pet.getPetId()); map.addValue(&quot;pet_name&quot;, pet.getPetName()); map.addValue(&quot;owner_name&quot;, pet.getOwnerName()); npJdbcTemplate.update( &quot;insert into pet (pet_id, pet_name, owner_name)&quot; + &quot; values (:pet_id, :pet_name, :owner_name)&quot; ,map );
  • 31.
  • 32.
  • 33.
  • 34.
  • 35.
  • 36.
  • 37.
  • 38.
  • 39.
  • 40.
  • 42.
  • 43.
  • 44.
  • 45.
  • 46.
  • 47.
  • 48.
  • 49.
  • 50.
  • 51.
  • 52.
  • 53.
  • 54. トランザクションマネージャの実装 ≪ Interface≫ PlatformTransactionManager DataSourceTransactionManager HibernateTransactionManager JtaTransactionManager JpaTransactionManager JdoTransactionManager データアクセス技術に合わせて 適切なトランザクションマネージャを 選択する
  • 55.
  • 56.
  • 57.
  • 58.
  • 59.
  • 60.
  • 62.

Notes de l'éditeur

  1. というところで、時間も迫ってまいりましたので、 これで、発表を終わります。 ご清聴ありがとうございました。