Java Webシリーズ:JDBCベース

18148 ワード

ADO.NETのJavaにおける対応技術はJDBC,エンタープライズ・ライブラリDataAccessApplicationBlockモジュールのJavaにおける対応はspring-jdbcモジュール,EntityFrameworkのJavaにおけるORMはHibernateである.リレーショナル・データベース、SQL、データベース・トランザクション、分散トランザクションの概念は共通です.
1.JDBC
JDBCコードはADO.NETコードと同様、学習時にdemoを書いてコアオブジェクトを把握する以外は、プロジェクトで直接使用するのに適していません.また、Javaの中で万年変わらない学術派抽象インタフェースは、TomcatやSpringで定義されている抽象タイプのように、属性や方法は.NETとよく似ていますが、Javaの基礎インタフェースと適切に合わなければなりません.抽象はJavaのように操作インタフェースだけに注目して基礎のデータ構造に注目することはできず、正しいタイプの抽象は方法の抽象よりも重要であるが、Javaの抽象的なやり方には操作だけに注目するのではなく、異なる原則があるようだ.
(1)コアオブジェクト
ADO.NETの4つのコア抽象クラスは、DbConnection、DbCommand、DbParameter、DbTransaction.DataAdapter、DataSetがコアオブジェクト上に構築されています.
JDBCの4つのコアインタフェースDataSource、Connection、Statement、ResultSet.PreparedStatementはStatementのサブタイプです.
両者は完全に一致しませんが、データベース・オペレーションのコア・オペレーションは一貫しており、リンクを開く、コマンドを送信する、接続を閉じるプロセスです.
(2)パラメータ処理
 パラメータのコアはインデックスとパラメータ値です.ADO.NETでは、DbDataParameterタイプがパラメータの抽象化に使用されます.JDBCではパラメータの抽象タイプは提供されず、PreparedStatementで定義された方法でパラメータを設定し、Connectionオブジェクトでそのタイプのオブジェクトを取得できます.
(3)取引
トランザクションの核心的な操作は、コミットとロールバックです.ADO.NETでは、DbTransactionタイプがトランザクションの抽象化に使用されます.DbConnectionのBeginTransactionメソッドで明示的なトランザクションを開くことができます.JDBCでは、トランザクションの抽象タイプは提供されず、Connectionで定義されたsetAutomit、commit、rollbackメソッドでトランザクションを操作できます.暗黙的トランザクションの自動コミットと明示的トランザクションの手動制御の両方が一致します.
(4)データソース
JDBCのConnectionは接続プールなどの高度な機能を備えていません.DataSourceは、データ・ソース・インタフェースを定義し、接続管理、接続プール、分散トランザクションなどの高度な機能に使用されます.接続プールの重要性は強調されません.Apache Commons DBPP 2やC 3 P 0(Hibernate)などのサードパーティ製のデータソースを使用して実現できます.Springフレームワークには、SimpleDriverDataSource、SingleConnectionDataSource、DriverManagerDataSourceなどの簡単なデータソースが内蔵されています.
DriverManager、commons-dbcp 2(1参照)、c 3 p 0(2参照)、h 2 database(3参照)を使用して、接続プールなし、dbcp 2接続プール、c 3 p 0接続プールの使用を説明します.
 1 package test.jdbc;
 2 
 3 import java.beans.PropertyVetoException;
 4 import java.sql.Connection;
 5 import java.sql.DriverManager;
 6 import java.sql.PreparedStatement;
 7 import java.sql.ResultSet;
 8 import java.sql.SQLException;
 9 import javax.sql.DataSource;
10 
11 import org.apache.commons.dbcp2.BasicDataSource;
12 import com.mchange.v2.c3p0.ComboPooledDataSource;
13 
14 public class Jdbc {
15     public static void main(String[] args) throws ClassNotFoundException, SQLException, PropertyVetoException {
16         String ddl = "create table user(id integer not null primary key,username varchar(64))";
17         String dml = "insert into user (id,username) values(1,'tom')";
18         String query = "select id,username from user where username=?";
19         String className = "org.h2.Driver";
20         String url = "jdbc:h2:mem:test";
21         // Connection conn = DriverManager.getConnection(url);
22         Connection conn = get_dbcp2_dataSource(className, url).getConnection();
23         // Connection conn = get_c3p0_dataSource(className,//
24         // url).getConnection();
25         conn.setAutoCommit(false);
26         conn.prepareStatement(ddl).execute();
27         conn.createStatement().execute(dml);
28         conn.commit();
29         conn.setAutoCommit(true);
30         PreparedStatement statement = conn.prepareStatement(query);
31         statement.setString(1, "tom");
32         ResultSet rs = statement.executeQuery();
33         User user = new User();
34         while (rs.next()) {
35             user.setId(rs.getInt(1));
36             user.setUsername("username");
37             break;
38         }
39         conn.close();
40         System.out.println(String.format("id:%d,username:%s", user.getId(), user.getUsername()));
41     }
42 
43     public static Connection getConnection(String driverClassName, String url) {
44         try {
45             Class.forName(driverClassName);
46         } catch (ClassNotFoundException e1) {
47             e1.printStackTrace();
48         }
49         Connection conn = null;
50         try {
51             conn = DriverManager.getConnection(url);
52         } catch (SQLException e) {
53             e.printStackTrace();
54         }
55         return conn;
56     }
57 
58     public static DataSource get_dbcp2_dataSource(String clssName, String url) {
59 
60         BasicDataSource dataSource = new BasicDataSource();
61         dataSource.setDriverClassName(clssName);
62         dataSource.setUrl(url);
63         return dataSource;
64     }
65 
66     public static DataSource get_c3p0_dataSource(String clssName, String url) throws PropertyVetoException {
67 
68         ComboPooledDataSource dataSource = new ComboPooledDataSource();
69         dataSource.setDriverClass(clssName);
70         dataSource.setJdbcUrl(url);
71         return dataSource;
72     }
73 }

 
ここで、2 dbcp、c 3 p 0およびh 2 databaseのMaven依存性は以下の通りである.
 1         <dependency>
 2             <groupId>com.h2database</groupId>
 3             <artifactId>h2</artifactId>
 4             <version>1.4.190</version>
 5         </dependency>
 6         <dependency>
 7             <groupId>org.apache.commons</groupId>
 8             <artifactId>commons-dbcp2</artifactId>
 9             <version>2.1.1</version>
10         </dependency>
11         <dependency>
12             <groupId>com.mchange</groupId>
13             <artifactId>c3p0</artifactId>
14             <version>0.9.5.2</version>
15         </dependency>

2.Spring Jdbc
JDBCはADO.NETのAPIと似ていて、直接使用するのに適していません.ORMフレームワークが適用されなければ、.NETではDataAccessApplicationBlockを使用し、JavaではSpring JDBCを使用することができます.Spring JDBCのコアクラスはJdbcTemplateです.
(1)Sprnigの依頼実現
Spring Jdbcの機能を使用するには、まずSpringでの委任の使用方法を理解し、Springはその委任署名を含むインタフェース(これらのインタフェースは通常内蔵実装されていない)を定義し、委任パラメータが必要な場合、このインタフェースをパラメータタイプとして使用し、Javaでの匿名クラス機能を利用して、インターフェース定義の委任をインラインコードで実現することができる.次に、一般的な委任インタフェースをいくつか挙げます.
Func:PreparedStatementインタフェースのcreatePreparedStatementメソッド.
1 public interface PreparedStatementCreator {
2 
3     PreparedStatement createPreparedStatement(Connection con) throws SQLException;
4 
5 }

Func:PreparedStatementCallback汎用インタフェースのdoInPreparedStatementメソッド.
1 public interface PreparedStatementCallback<T> {
2 
3     T doInPreparedStatement(PreparedStatement ps) throws SQLException, DataAccessException;
4 
5 }

Func:TransactionCallback汎用インタフェースのT doInTransaction(TransactionStatus status)メソッド.
1 public interface TransactionCallback<T> {
2 
3     T doInTransaction(TransactionStatus status);
4 
5 }

Fcun:ResultSet Extractor汎用メソッドのT extractData(ResultSet rs)メソッド.
1 public interface ResultSetExtractor<T> {
2 
3     T extractData(ResultSet rs) throws SQLException, DataAccessException;
4 
5 }

(1)JdbcTemplate
 JdbcTemplateはDataSourceと併用する必要があります.JdbcTemplateのコードの多くはIDEによる匿名クラスの自動生成によるものであり,手書きのコード量はそれほど多くない.
 1     public static void main(String[] args) throws ClassNotFoundException, SQLException, PropertyVetoException {
 2         String ddl = "create table user(id integer not null primary key,username varchar(64))";
 3         String dml = "insert into user (id,username) values(1,'tom')";
 4         String query = "select id,username from user where username=?";
 5         String className = "org.h2.Driver";
 6         String url = "jdbc:h2:mem:test";
 7 
 8         DataSource dataSource = get_dbcp2_dataSource(className, url);
 9         JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource);
10         PlatformTransactionManager tm = new DataSourceTransactionManager(dataSource);
11         TransactionTemplate tt = new TransactionTemplate(tm);
12         tt.execute(new TransactionCallback() {
13 
14             @Override
15             public Object doInTransaction(TransactionStatus status) {
16                 jdbcTemplate.execute(ddl);
17                 jdbcTemplate.execute(dml);
18                 return status;
19             }
20         });
21 
22         User user = jdbcTemplate.query(query, new Object[] { "tom" }, new ResultSetExtractor<User>() {
23             @Override
24             public User extractData(ResultSet rs) throws SQLException, DataAccessException {
25                 User user = new User();
26                 while (rs.next()) {
27                     user.setId(rs.getInt(1));
28                     user.setUsername(rs.getString("username"));
29                     break;
30                 }
31                 return user;
32             }
33         });
34         System.out.println(String.format("id:%d,username:%s", user.getId(), user.getUsername()));
35     }

(3)TransactionTemplate
トランザクション用にTransactionTemplateが上のコードに表示されます.TransactionTemplateはPlatformTransactionManagerに依存し、Spring Jdbcで定義されたDataSourceTransactionManagerインプリメンテーションクラスはデータベーストランザクションの処理に使用されます.Springのorm,jsm,txなどのモジュールでは他にも実装されている.
(4)JdbcDaoSupport
JdbcDaoSupportは、内部でJdbcTemplateフィールドを使用し、DaoSupportインタフェースを実装する抽象クラスであり、DAOクラスをカスタマイズする際に参照またはベースクラスとして使用できます.
 1 class MyDao extends JdbcDaoSupport {
 2     public MyDao(DataSource dataSource) {
 3         this.setJdbcTemplate(new JdbcTemplate(dataSource));
 4     }
 5 
 6     @SuppressWarnings("unchecked")
 7     public void init(String ddl, String dml) {
 8         PlatformTransactionManager tm = new DataSourceTransactionManager(this.getDataSource());
 9         TransactionTemplate tt = new TransactionTemplate(tm);
10 
11         tt.execute(new TransactionCallback() {
12 
13             @Override
14             public Object doInTransaction(TransactionStatus status) {
15                 getJdbcTemplate().execute(ddl);
16                 getJdbcTemplate().execute(dml);
17                 return status;
18             }
19         });
20     }
21 
22     public User getUser(String query, String username) {
23         return this.getJdbcTemplate().query(query, new Object[] { username }, new ResultSetExtractor<User>() {
24             @Override
25             public User extractData(ResultSet rs) throws SQLException, DataAccessException {
26                 User user = new User();
27                 while (rs.next()) {
28                     user.setId(rs.getInt(1));
29                     user.setUsername(rs.getString("username"));
30                     break;
31                 }
32                 return user;
33             }
34         });
35     }
36 }

リファレンス
(1)http://commons.apache.org/proper/commons-dbcp/download_dbcp.cgi
(2)http://sourceforge.net/projects/c3p0/
(3)http://www.h2database.com/html/cheatSheet.html
(4)http://commons.apache.org/proper/commons-dbcp/guide/jndi-howto.html