DBFluteの紹介...» Torqueの便利さを感じつつ不足部分も痛感する。 »S2DaoのSQLコメント機能に感動し、Torqueの不足を埋められると感じる。
Apache Torqueについて
-
Upload
tako-pons -
Category
Technology
-
view
293 -
download
0
Transcript of Apache Torqueについて
Apache Torque について
Javaツール勉強会@福岡 2016/08~データベースツールとかいろいろ~
2016/08/26 TAKO
TAKO(たこ)
職業:個人事業主 はてなID:takopons
Java とか PHP とかを使って仕事してます。
仕事場は自宅だったり取引先だったり。
近ごろは JavaScript, jQuery, Ajax, D3.js らへんで
コーディングしてる時間が長いです(昨年比)。
最初は通信系のプログラマとしてデビューして
Solaris の UNIX-C で通信プロトコルの実装を
してました。普通に vi が使えます。
2 / 44
DB周りのフレームワークについて
DBアクセス関連のミドルウェアやフレームワークには
どんなものがあるの?
1. JDBC
2. EJB
3. O/Rマッピング(Hibernate, MyBatis, Torqueなど)
4. S2JDBC(Seasar2標準のDBアクセスフレームワーク)
5. Spring JDBC
6. JDO仕様の実装(Speedo, Apache JDOなど)
7. JPA(Java Persistence API)
3 / 44
1. JDBC
JDBC でがんばる?
僕が一番、SQLをうまく使えるんだ。
俺は JNDI と DataSourceと Connection Pooling と、
あと、Dao と DTOとヘルパーBean があれば戦えるぜ!
4 / 44
2. EJB(Enterprise JavaBeans)
まだ EJB で消耗してるの?
EJBは、その高すぎる理想のため参入障壁の壁もかなり高い。
要するに使いにくい。(EJBコンテナとか Home/Remote I/Fとか)
EJBは元々、分散環境のためのコンポーネントなので、
分散オブジェクトが必要ない場合(大抵は分散不要)、
ひたすら面倒くさいだけ。
EJB3.0以降は使いやすくなったらしいが、
もはや手遅れ感がある。
5 / 44
3. O/Rマッピング(Object/Relational Mapping)
O/Rマッピングを使えば SQL文を書かなくて済むらしい、
というインターネッツの噂はウソ。
1つのテーブルだけ触るマスタメンテ系の処理しかない
ならば、SQL文は書かなくて良い。
しかし、多くの業務処理は複数のテーブルを結合したり、
副問い合わせしたりしてデータを抽出する。
つまり、SQL文は必要。
Hibernate と MyBatisがデファクト・スタンダードの
座を争い中?
6 / 44
4. S2JDBC(Seasar2標準のDBアクセスフレームワーク)
S2JDBCは O/Rマッピング可能。普通に SQL文も書ける。
SQL文を外部ファイルで定義できる。(それって、Doma?)
実は、S2JDBC で充分なのだが・・・
昨年(2015/9/28)Seasar2開発者:ひがやすをさんが、
「2016/9/26 で Seasar2 のサポートを終了する」と
宣言したことによって、 Seasar2コミュニティのメンバや
コミッタの人達の士気が下がっただろうと思う。たぶん。
現在、SAStruts と S2JDBC を採用している Webシステムは
今後も使い続けて良いのか? (Yes / No)
7 / 44
5.~7. 簡単に
5. Spring JDBC
JDBC のラッパーAPI。SQL文を記述するタイプのフレームワーク。
6. JDO仕様の実装(Speedo, Apache JDOなど)
Java Data Objects:O/Rマッピングとオブジェクトの永続性に関する仕様。
7. JPA(Java Persistence API)
EJB2.0系の問題点を解消するべく策定された、永続性のAPI。
実装は、Hibernate, EclipseLink, Apache OpenJPAなど。
おまけ.
Domaどま? Domaは Seasarプロジェクトだが、メンテは継続の予定。
8 / 44
ここから本題
9 / 44
Apache Torque について
Torque(トルク)は、O/Rマッピングの一種。
Torque は元々、Jakarta プロジェクトの
Turbine フレームワークの一部として開発。
その後、独立パッケージとして提供。
ver 3.1以降、ジェネレータとランタイムが分割。
10 / 44
そもそも、O/Rマッピングって何?
ORM(Object/Relational Mapping)とは、
オブジェクト指向言語のオブジェクトと、RDBテーブルの
レコードとのマッピング(対応付け)。
int colKey;
String colValue;
Date colDatetime;
FugaTbl
COL_KEY INTEGER
COL_VALUE VARCHAR
COL_DATETIME TIMESTAMP
FUGA_TBL
O/Rマッピング
クラステーブル
ちなみに、EJB の EntityBeanも O/Rマッピング。Hibernate は Object 寄りで、MyBatisは RDB 寄りの設計思想。
11 / 44
今回のテスト環境
OS: Windows 8.1
ORM: torque-3.3
torque-gen-3.3
IDE: pleiades-e4.6
JDK: jdk1.8.0_91
Ant: apache-ant-1.9.7
Web: apache-tomcat-8.0.36
Servlet + JSP
DB: MySQL 5.7
A5:SQL Mk-2 ver 2.11.6 (x64)
12 / 44
環境設定&動作確認
1. ダウンロード
2. DBのXML定義
3. Ant実行(JavaクラスとSQLスクリプト生成)
4. 動作環境の構築
5. 実装
6. 動作確認
7. 既存DBからJavaソース生成
8. 型の対応表
9. その他、注意点など
10.テーブル結合13 / 44
1. ダウンロード(その1)
torque-3.3 (2008/02/28)
http://archive.apache.org/dist/db/torque/torque-3.3/binaries/
torque-3.3.zip と torque-gen-3.3.zip をダウンロード。
任意の場所に展開。
例)C:¥work¥torque-3.3 ← ランタイム
C:¥work¥torque-gen-3.3 ← ジェネレータ
※1 最新バージョンは torque-4.0 (2014/04/16)
※2 Ant実行時の生成ファイルは、
[展開先]¥torque-gen-3.3¥src以下に作成される。
14 / 44
1. ダウンロード(その2)
MySQL用JDBCドライバ
https://dev.mysql.com/downloads/connector/j/
mysql-connector-java-5.1.39.zip をダウンロード。
zip展開後、Torque ジェネレータの lib に
mysql-connector-java-5.1.39-bin.jar をコピー。
例)C:¥work¥torque-gen-3.3¥lib¥
mysql-connector-java-5.1.39-bin.jar
15 / 44
2. DBのXML定義
DB名:HOGE_DB
テーブル名:FUGA_TBL
テーブル定義:C:¥work¥torque-gen-3.3¥src¥schema¥hoge_db-schema.xml
<database name=“hoge_db">
<table name="fuga_tbl">
<column name="COL_KEY" primaryKey="true“
required="true" type="INTEGER"/>
<column name="COL_VALUE" size="50" type="VARCHAR"/>
<column name=“COL_DATETIME” type="TIMESTAMP"/>
</table>
</database>
※一部抜粋。
torque-gen は末尾が schema.xml のファイルを自動的に参照。
16 / 44
3. Ant実行(その1)
build.propertiesの変更
C:¥work¥torque-gen-3.3¥build.properties を
以下のように変更。(変更点のみ抜粋)torque.project = WebHello
torque.database = mysql
torque.targetPackage = pkg.hogedb
torque.database.createUrl = jdbc:mysql://127.0.0.1:3306/mysql
torque.database.buildUrl = jdbc:mysql://127.0.0.1:3306/hoge_db
torque.database.url = jdbc:mysql://127.0.0.1:3306/hoge_db
torque.database.driver = org.gjt.mm.mysql.Driver
torque.database.user = root
torque.database.password = [root password]
torque.database.host = 127.0.0.1
17 / 44
3. Ant実行(その2)
コマンドプロンプトで C:¥work¥torque-gen-3.3へ移動。
JavaソースとSQLスクリプトの生成
ant -f build-torque.xml
データベース作成:DBサーバにDB作成
ant -f build-torque.xml create-db
テーブル作成:DBサーバにテーブル作成
ant -f build-torque.xml insert-sql
18 / 44
3. Ant実行(その3)
生成された Java クラス
- int colKey;
- String colValue;
- Date colDatetime;
BaseFugaTbl
+ save()
+ copy()
+ toString()
FugaTbl
+ String COL_KEY;
+ String COL_VALUE;
+ String COL_DATETIME;
BaseFugaTblPeer
+ doSelect()
+ doUpdate()
+ doDelete()
FugaTblPeerレコードの登録、更新など
条件指定での抽出など
19 / 44
Baseで始まるクラスは、基本的に修正しないお約束。
4. 動作環境の構築(その1)
Torque.propertiesのコピー
C:¥work¥torque-3.3 の Torque.propertiesを
動作環境へコピーして変更。
コピー先 例) C:¥work¥pleiades-e4.6¥workspace¥WebHello¥src
※実際に動く時は、以下の場所に自動コピーされる。
ここに手動で置いても良いが、クリーンなどで消えるので注意。
例)C:¥work¥pleiades-e4.6¥workspace¥.metadata¥.plugins¥
org.eclipse.wst.server.core¥tmp0¥wtpwebapps¥
WebHello¥WEB-INF¥classes
20 / 44
4. 動作環境の構築(その2)
Torque.properties の変更(変更点のみ抜粋)
torque.database.default = hoge_db
torque.database.hoge_db.adapter = mysql
torque.dsfactory.hoge_db.factory =
org.apache.torque.dsfactory.SharedPoolDataSourceFactory
torque.dsfactory.hoge_db.pool.maxIdle = 8
torque.dsfactory.hoge_db.pool.maxActive = 10
torque.dsfactory.hoge_db.pool.testOnBorrow = true
torque.dsfactory.hoge_db.pool.validationQuery = SELECT 1
torque.dsfactory.hoge_db.connection.driver = org.gjt.mm.mysql.Driver
torque.dsfactory.hoge_db.connection.url =
jdbc:mysql://localhost:3306/hoge_db?useUnicode=true&characterEncoding=UTF8
torque.dsfactory.hoge_db.connection.user = [user name]
torque.dsfactory.hoge_db.connection.password = [user password]
21 / 44
エンコードの文字コード指定
このスライドでは改行してるが、実際は1行。
4. 動作環境の構築(その3)
生成されたJavaソースのコピー
3. Ant実行で生成されたJavaソースを動作環境へコピー。
コピー元
例)C:¥work¥torque-gen-3.3¥src¥java
org フォルダ
pkgフォルダ
コピー先
例) C:¥work¥pleiades-e4.6¥workspace¥WebHello¥src
3. Ant実行(その1)で設定したbuild.propertiesの
torque.targetPackage = pkg.hogedbをもとに作られる。
22 / 44
4. 動作環境の構築(その4)
実行時に必要となる jarファイルをコピー。
commons-beanutils-core-1.7.0.jar
commons-collections-3.2.jar
commons-configuration-1.4.jar
commons-dbcp-1.2.2.jar
commons-lang-2.3.jar
commons-logging-1.1.jar
commons-pool-1.3.jar
log4j-1.2.14.jar
mysql-connector-java-5.1.39-bin.jar
torque-3.3.jar
village-3.3.jar
コピー元の jar はC:¥work¥torque-gen-3.3¥lib
C:¥work¥torque-3.3¥lib
C:¥work¥torque-3.3
らへんに、だいたいあるハズ。
コピー先 例)C:¥work¥pleiades-e4.6¥workspace
¥WebHello¥WebContent¥WEB-INF¥lib
23 / 44
5. 実装(その1)
初期処理 TorqueTestServlet.javapublic void init() {
try {// Torque用プロパティファイルの読み込み
Class<? extends TorqueTestServlet> thisClass = this.getClass();
ClassLoader classLoader = thisClass.getClassLoader();
PropertiesConfiguration pConfig = new PropertiesConfiguration();
pConfig.load(classLoader.getResourceAsStream("Torque.properties"));
// Torqueの初期設定
Torque.init(pConfig);
} catch(Exception e) {
e.printStackTrace();
}
}
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
24 / 44
5. 実装(その2)
検索処理 TorqueTestServlet#doPost()String findKey = request.getParameter("findKey");
if (findKey != null && findKey.length() > 0) {
request.setAttribute("findKey", findKey);
try {
Criteria crit = new Criteria();
crit.add(FugaTblPeer.COL_KEY, Integer.parseInt(findKey));
List<FugaTbl> resultList = (List<FugaTbl>)FugaTblPeer.doSelect(crit);
request.setAttribute("resultList", resultList);
} catch(NumberFormatException nfe) {
;
} catch(Exception e) {
e.printStackTrace();
}
}
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
25 / 44
ブラウザから送信された検索キーを取得し、抽出条件に設定。
ブラウザから送信された検索キーを取得し、抽出条件に設定。
抽出結果を設定。
5. 実装(その3)
登録/更新処理 TorqueTestServlet#doPost()
String setKey = request.getParameter("setKey");
String setValue = request.getParameter("setValue");
Date currDate = new Date();
String setDatetime = currDate.toString();
FugaTbl fugaTbl = new FugaTbl();
fugaTbl.setColKey(Integer.parseInt(setKey));
fugaTbl.setColValue(setValue);
fugaTbl.setColDatetime(currDate);
01
02
03
04
05
06
07
08
09
26 / 44
次ページに続く。
ブラウザから送信された値を取得し、レコード登録用オブジェクトに設定。
ブラウザから送信された値を取得し、レコード登録用オブジェクトに設定。
5. 実装(その4)
登録/更新処理(続き)Criteria crit = new Criteria();
crit.add(FugaTblPeer.COL_KEY, Integer.parseInt(setKey));
List<FugaTbl> resultList = (List<FugaTbl>)FugaTblPeer.doSelect(crit);
if (resultList != null && resultList.size() > 0) {
// UPDATE
FugaTblPeer.doUpdate(fugaTbl);
} else {
// INSERT
fugaTbl.save();
// UPDATE
fugaTbl.setColValue(setValue + “ UPDATE!”);
fugaTbl.save();
}
実際のコードは、全体をtry ~ catch で囲んでいる。
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
27 / 44
6. 動作確認(検索)
28 / 44
6. 動作確認(登録)
29 / 44
6. 動作確認(一覧)
30 / 44
7. 既存DBから Javaソース生成
①データベースからテーブル定義のスキーマ.xml生成
ant -f build-torque.xml jdbc
②schema.xml が生成される
例)C:¥work¥torque-gen-3.3¥src¥schema フォルダ下
③生成された schema.xml を DB名-schema.xml に
リネーム 例)hoge_db-schema.xml
④JavaソースとSQLスクリプトの生成
ant -f build-torque.xml
31 / 44
8. 型の対応表(その1)
No. COLUMN_NAME DATA_TYPE schema.xml Java
1 COL_TINYINT tinyint(4) TINYINT byte
2 COL_SMALLINT smallint(6) SMALLINT short
3 COL_MEDIUMINT mediumint(9) INTEGER int
4 COL_INTEGER int(11) INTEGER int
5 COL_INT int(11) INTEGER int
6 COL_BIGINT bigint(20) BIGINT long
7 COL_NUMERIC decimal(10,0) DECIMAL BigDecimal
8 COL_DECIMAL decimal(10,0) DECIMAL BigDecimal
9 COL_DEC decimal(10,0) DECIMAL BigDecimal
10 COL_FLOAT float REAL float
11 COL_DOUBLE double(10,5) DOUBLE double
12 COL_REAL double DOUBLE double
13 COL_DATE date DATE Date
14 COL_DATETIME datetime TIMESTAMP Date
15 COL_TIMESTAMP timestamp TIMESTAMP Date
32 / 44
8. 型の対応表(その2)
No. COLUMN_NAME DATA_TYPE schema.xml Java
16 COL_TIME time TIME Date
17 COL_YEAR year(4) DATE Date
18 COL_CHAR char(50) CHAR String
19 COL_VARCHAR varchar(50) VARCHAR String
20 COL_TINYTEXT tinytext VARCHAR String
21 COL_TEXT text LONGVARCHAR String
22 COL_MEDIUMTEXT mediumtext LONGVARCHAR String
23 COL_LONGTEXT longtext LONGVARCHAR String
24 COL_TINYBLOB tinyblob BINARY byte[]
25 COL_BLOB blob LONGVARBINARY byte[]
26 COL_MEDIUMBLOB mediumblob LONGVARBINARY byte[]
27 COL_LONGBLOB longblob LONGVARBINARY byte[]
28 COL_ENUMenum('enum1','enum2','en
um3')CHAR String
29 COL_SET set('set1','set2','set3') CHAR String
33 / 44
9. その他、注意点など(その1)
DBカラム名の予約語
BY_NAM, BY_PEER_NAME, CATEGORY, PRIMARY_KEY
などが Torque の予約語。
schema.xml の文字コード
DB名-schema.xml 内で、コメントなどに日本語を
使う場合、文字コードはUTF-8で保存すること。
ShiftJISだと、ant -f build-torque.xml でエラーになる。
34 / 44
9. その他、注意点など(その2)カラム型の DATETIME は、 schema.xml では TIMESTAMP になる。
そして、
カラム型に TIMESTAMP を指定して A5:SQL Mk-2でテーブル作成すると、
`COL_TIMESTAMP` timestamp,
↓
`COL_TIMESTAMP` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
となる。この CURRENT_TIMESTAMP の部分が、自動生成された Javaソースでコンパイルエラーになってしまう。
なので、DBのテーブル定義から XMLスキーマを生成した場合、XMLファイルを一部修正するか、または、Javaソースを修正する必要がある。
private Date colDatetime = new Date(CURRENT_TIMESTAMP);
↑ 定数:CURRENT_TIMESTAMP がない、というエラー発生。
たぶん、Torque のバグ。
35 / 44
10. テーブル結合(その1)
テーブル結合のSELECT
結合条件:PIYO_TBL.COL_TINYINT = FUGA_TBL.COL_KEY
COL_KEY INTEGER
COL_VALUE VARCHAR
COL_DATETIME TIMESTAMP
FUGA_TBL
COL_TINYINT TINYINT
COL_SMALLINT SMALLINT
COL_TIMESTAMP TIMESTAMP
PIYO_TBL
36 / 44
10. テーブル結合(その2)
PiyoTbl.java に手動で項目追加
- int fugaTblColKey;
- String fugaTblColValue;
PiyoTbl
+ getFugaTblColKey()
+ setFugaTblColKey()
+ getFugaTblColValue()
+ setFugaTblColValue()
37 / 44
項目名は任意。今回は、他テーブルのカラムであることを明示するため、この名前にした。
Getter と Setter を追加。
※Eclipse の「getter およびsetter の生成」機能を使うと自動生成できて便利。
10. テーブル結合(その3)
PiyoTblPeer.java に getData() メソッド追加public static List getData() throws TorqueException {
// SQL文作成
StringBuffer sb = new StringBuffer();
sb.append(“ select ”);
sb.append(“ py.col_tinyint ”);
sb.append(“ , py.col_smallint ”);
sb.append(“ , fg.col_key ”);
sb.append(“ , fg.col_value ”);
sb.append(“ from ”);
sb.append(“ piyo_tbl py ”);
sb.append(“ left join fuga_tbl fg ”);
sb.append(“ on ( ”);
sb.append(“ py.col_tinyint = fg.col_key ”);
sb.append(“ ) ”);
sb.append(“ order by py.col_tinyint ASC ”);
String sql = sb.toString();
return populateObjects2(executeQuery(sql));
}
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
1838 / 44
取得する項目と結合条件、および、並び順を指定したSELECT文を書く。
10. テーブル結合(その4)
PiyoTblPeer.java に row2Object2() メソッド追加public static PiyoTbl row2Object2(Record row, int offset, Class cls)
throws TorqueException
{
try{
PiyoTbl obj = (PiyoTbl) cls.newInstance();
populateObject2(row, offset, obj);
obj.setModified(false);
obj.setNew(false);
return obj;
} catch (InstantiationException e){
throw new TorqueException(e);
} catch (IllegalAccessException e){
throw new TorqueException(e);
}
}
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
39 / 44
row2Object() が PiyoTblPeer.java
にあるので、コピペして修正。
※39~41ページに「コピペして修正」と書いたが、おおまかな処理はコピペ元と同じなので、共通パターン化できるかも?
10. テーブル結合(その5)
PiyoTblPeer.java に populateObject2() メソッド追加
public static void populateObject2(Record row, int offset, PiyoTbl obj)
throws TorqueException
{
try{
obj.setColTinyint(row.getValue(offset + 0).asByte());
obj.setColSmallint(row.getValue(offset + 1).asShort());
obj.setFugaTblColKey(row.getValue(offset + 2).asInt());
obj.setFugaTblColValue(row.getValue(offset + 3).asString());
} catch (DataSetException e) {
throw new TorqueException(e);
}
}
01
02
03
04
05
06
07
08
09
10
11
12
13
40 / 44
38ページの 5~8行目に対応。オフセットと型を指定して値を設定。
void populateObjects() が PiyoTblPeer.java
にあるので、コピペして修正。
10. テーブル結合(その6)
PiyoTblPeer.java に populateObjects2() メソッド追加
public static List populateObjects2(List records)
throws TorqueException
{
List results = new ArrayList(records.size());
for (int i = 0; i < records.size(); i++){
Record row = (Record) records.get(i);
results.add(PiyoTblPeer.row2Object2(
row, 1, PiyoTblPeer.getOMClass()));
}
return results;
}
01
02
03
04
05
06
07
08
09
10
11
41 / 44
List populateObjects(List) がPiyoTblPeer.javaにあるので、コピペして修正。
10. テーブル結合(その7)
一覧取得 TorqueTestServlet#doGet()// FUGA_TBL 一覧取得
Criteria fugaCrit = new Criteria();
fugaCrit.addAscendingOrderByColumn(FugaTblPeer.COL_KEY);
List fugaList = FugaTblPeer.doSelect(fugaCrit);
request.setAttribute("fugaList", fugaList);
// PIYO_TBL 一覧取得
Criteria piyoCrit = new Criteria();
piyoCrit.addAscendingOrderByColumn(PiyoTblPeer.COL_TINYINT);
List piyoList = PiyoTblPeer.doSelect(piyoCrit);
request.setAttribute("piyoList", piyoList);
// 複数テーブル結合
List joinList = PiyoTblPeer.getData();
request.setAttribute("joinList", joinList);
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
実際のコードは、全体をtry ~ catch で囲んでいる。
42 / 44
38ページの getData() を呼び、抽出結果を取得。
Torque - Torqueユーザガイド
http://www.jajakarta.org/turbine/jp/turbine/torque/user-guide.html
Torqueのプログラム開発手順書 - UTL sites
http://www.utl.co.jp/?p=Torque%E3%81%AE%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%A0%E9%96%8B%E7%99%BA%E6%89%8B%E9%A0%86%E6%9B%B8
「Seasar2が終わる!」と慌てるべきではない理由。 - Java EE 事始め!
http://masatoshitada.hatenadiary.jp/entry/2016/01/27/181139
Torque
http://muimi.com/j/jakarta/torque/
JavaのORM、Domaの話 +α
http://backpaper0.github.io/uragamiorm/#/
43 / 44
Seasar2徹底入門 SAStruts/S2JDBC対応
Spring3入門
―Javaフレームワーク・より良い設計と
アーキテクチャ
Jakartaプロジェクト徹底攻略
―WEB+DB PRESS Special Issue
(Javaエキスパート・シリーズ)
44 / 44