SHOEISHA iD

※旧SEメンバーシップ会員の方は、同じ登録情報(メールアドレス&パスワード)でログインいただけます

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

作りながら学ぶJavaアプリケーションフレームワーク

Struts 2入門(7)~データ連携の仕組み~

作りながら学ぶJavaアプリケーションフレームワーク (7)

  • X ポスト
  • このエントリーをはてなブックマークに追加

データベースとの連携

 Struts 2を用いたアプリケーションでデータベース(RDBMS)を利用するのも、基本的には、通常のJavaアプリケーションと変わりはありません。直接JDBCを使うこともできますし、いわゆるO/Rマッピングフレームワーク(Hibernateなど)を利用することもできます。

 また、DIコンテナであるSpringとの連携も可能で、Springを通して、データベースとの接続を行うこともできます。ただ、Springを利用すると、どうしてもXMLファイルでの設定項目が多くなってしまいます。また、ちょっとした処理でも前準備が必要で、ソースコードも長くなってしまいますので、今回は、XML設定が不要な、ActiveObjectsというO/Rマッピングフレームワークのみを用いて、データベース接続の基本を説明することにします。

O/RマッピングとDIコンテナ

 O/Rマッピングとは、オブジェクト指向でのObjectと、RDB(リレーショナルデータベース)をマッピングするということです。一般的なRDBでは、いわゆるオブジェクト指向言語で、直接データベースの値を操作することができません。そのため、オブジェクトをデータベースのレコードに関連付ける仕組みが必要になってきます。

 また、そのような機能をコンポーネント化したものを、O/Rマッピングフレームワークと呼び、HibernateiBATIS、JPA(Java Persistence API)などが有名です。

 一方、DIコンテナとは、「DI(Dependency Injection:依存性の注入)」と呼ばれる設計思想に沿って作られたコンポーネントを、管理するためのライブラリです。DIとは、コンポーネント間の依存関係をソースコードから排除して、実行時に依存するコードを「注入」するデザインパターンです。代表的なDIコンテナとしては、Spring Frameworkや、Seasarがあります。

 サンプルとしては、先ほどのBooks2Actionクラスを少し拡張して、データベースに登録する処理と、登録したデータを一覧表示する処理を追加してみます。

登録実行での一覧表示
登録実行での一覧表示

前準備

 今回のサンプルでは、ActiveObjectsフレームワークが対応しているデータベースの一つである、MySQLを利用します。MySQLのインストールについては、WINGSプロジェクトのサポートページを参照してください。

 まず、データベースとテーブルを作成しておきます。ここではデータベースはbooks、テーブルもbooksという名前にしました。テーブルを作成するSQLスクリプトは、次のようになります。ごく単純に、BooksModelオブジェクトのフィールドを文字列の項目とし、さらに、ActiveObjectsのデフォルトのプライマリーキーである、数値のIDカラムを追加しています。

[リスト12]booksテーブル作成SQL文
CREATE TABLE books (
    id INTEGER NOT NULL AUTO_INCREMENT,
    isbn VARCHAR(14),
    title VARCHAR(100),
    author VARCHAR(50),
    PRIMARY KEY (id)
) ENGINE=InnoDB;

 また、ActiveObjects(activeobjects-0.8.2.zip)をダウンロードし、解凍して得られるactiveobjects-0.8.2.jarと、MySQLのコネクタであるmysql-connector-java-5.1.7-bin.jarを、参照ライブラリーにコピーしておきます。

Actionクラス(BooksDBAction.java)

 まずは、Actionクラスの変更点を見ていきましょう。

[リスト13]BooksDBAction.javaの一部
public class BooksDBAction extends ActionSupport
             implements ScopedModelDriven<BooksModel> {

    private BooksModel model;   // 本情報のModelクラス
    private String scopeKey;    // セッションでのModelオブジェクト識別キー

    List<BooksModel> books;     // 登録した本情報の一時格納用
    private String message;     // データベース例外メッセージ表示用

    @Action(
        value = "/registerDB",
        results = {
            @Result(name = "success", location = "booksRegisterDB.jsp" )
        }
    )
    public String register() throws Exception {

        try{
            // DAOオブジェクトの生成
            BooksDAO dao = new BooksDAO();

            // 入力値のデータベース登録
            dao.register(model.getIsbn(), model.getTitle(), model.getAuthor());

            // データベースから全登録データを取得
            books = dao.getAll();
        }
        catch(SQLException e) {
            setMessage(e.getMessage());
        }
        return "success";

    }

 フィールドを2つ追加しています。

 booksは、データベースに登録した本の情報を取得し、一時的に格納しておくListオブジェクトです。最後のデータ一覧画面では、このListオブジェクトの内容を表示しています。

 messageは、データベース処理で例外が発生した場合に、その例外メッセージを保持しておく文字列です。

 registerメソッドで、データベースの接続、登録/取得処理を行っています。といっても、Actionクラスでは、BooksDAOクラスのメソッドを呼んでいるだけです。データベースの実際の処理は、BooksDAOクラスが行っています。

 このような実装方法を、「DAO(Data Access Object)パターン」と呼びます。DAOパターンでは、データベースへのアクセスを専用のクラスでカプセル化します。それにより、データベースに依存する処理を、ビジネスロジックから排除することができます。

 なお、通常のDAOパターンでは、処理を抽象化したインターフェイスを定義して、DAOクラスで実装するようにします。そうしておけば、データベースへのアクセス手段や実装が異なるDAOクラスを使う場合でも、公開しているインターフェイスは変わりませんので、ビジネスロジックを変更する必要がありません。

DAOクラス(BooksDAO.java)

 では、次にBooksDAOクラスなのですが、その前に、Booksインターフェイスを説明しておきます。このインターフェイスは、booksテーブルに対応するオブジェクトのインターフェイスで、テーブルの項目に対して、Getter/Setterを定義しているだけです(IDカラムは、既にEntityインターフェイスで定義済み)。

 実装は、フレームワークのActiveObjectsが自動で生成してくれます。

[リスト14]Books.javaの一部
public interface Books extends Entity {
    public String getIsbn();
    public void setIsbn(String isbn);
    public String getTitle();
    public void setTitle(String title);
    public String getAuthor();
    public void setAuthor(String author);
}

 BooksDAOクラス本体は、次のようになります。

[リスト15]BooksDAO.javaの一部
public class BooksDAO {

    private static EntityManager manager;

    public BooksDAO(){

        manager =
            new EntityManager("jdbc:mysql://localhost/books", "root", "");
                    // ホスト/データベース名、ユーザー、パスワードを指定
    }

    // 登録
    public void register(String isbn, String title, String author ) throws SQLException{

        Books book = manager.create(Books.class);

        book.setIsbn(isbn);
        book.setTitle(title);
        book.setAuthor(author);
        book.save();
    }

    // 全データ取得
    public List<BooksModel> getAll() throws SQLException{

        List<BooksModel> b = new ArrayList<BooksModel>();
        Books[] books = manager.find(Books.class);
        for (Books element : books) {
            BooksModel tmp = new BooksModel();
            tmp.setIsbn(element.getIsbn());
            tmp.setTitleNoencode(element.getTitle());
            tmp.setAuthorNoencode(element.getAuthor());
            b.add(tmp);
        }
        return b;
    }
}
コンストラクタ

 BooksDAOクラスも、とてもシンプルです。コンストラクタで、net.java.ao.EntityManagerクラスをインスタンス化しています。EntityManagerクラスのコンストラクタで、MySQLのホスト名、データベース名、ユーザー名、パスワードを指定します。サンプルでは、それぞれ、"localhost"、"books"、"root"、なし、としています。

registerメソッド

 テーブルへの登録は、EntityManager.createメソッドでBooksオブジェクトを生成し、登録したい値をセットしたのち、EntityManager.saveメソッドを呼び出します。

getAllメソッド

 テーブルからの参照は、EntityManager.findメソッドを用います。findメソッドのパラメータで何も指定しなければ、テーブルからすべてのデータを、配列として取得することができます。

 サンプルでは、BooksModelオブジェクトのListを作り、取得した配列から一つずつデータを取りだして、Listコンテナに追加しています。

 なお、ActiveObjectsの詳細については、前述のサイトや、JavaDocを参照してください。

booksRegisterDB.jsp

 booksRegisterDB.jspファイルでは、<s:iterator>タグを用いて、BooksModelのListオブジェクト全内容の一覧を表示しています。

[リスト16]booksRegisterDB.jspの一部
<s:iterator value="books">
<p>
書名 : <s:property value="title" /><br />
著者 : <s:property value="author" /><br />
ISBN : <s:property value="isbn" /><br />
</p>
</s:iterator>

まとめ

 今回は、ActionクラスとViewレイヤーでデータをやりとりする仕組みを解説しました。データベースとの連携も、ActiveObjectsを利用すれば、ごくシンプルに記述できることが分かるかと思います。

 次回は、これまで紹介してきた機能をまとめて、より本格的なアプリケーションを作成することにしましょう。

参考資料

この記事は参考になりましたか?

  • X ポスト
  • このエントリーをはてなブックマークに追加
作りながら学ぶJavaアプリケーションフレームワーク連載記事一覧

もっと読む

この記事の著者

山田 祥寛(ヤマダ ヨシヒロ)

静岡県榛原町生まれ。一橋大学経済学部卒業後、NECにてシステム企画業務に携わるが、2003年4月に念願かなってフリーライターに転身。Microsoft MVP for Visual Studio and Development Technologies。執筆コミュニティ「WINGSプロジェクト」代表。主な著書に「独習シリーズ(Java・C#・Python・PHP・Ruby・JSP&サーブレットなど)」「速習シリーズ(ASP.NET Core・Vue.js・React・TypeScript・ECMAScript、Laravelなど)」「改訂3版JavaScript本格入門」「これからはじめるReact実践入門」「はじめてのAndroidアプリ開発 Kotlin編 」他、著書多数

※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です

WINGSプロジェクト 高江 賢(タカエ ケン)

WINGSプロジェクトについて> 有限会社 WINGSプロジェクトが運営する、テクニカル執筆コミュニティ(代表 山田祥寛)。主にWeb開発分野の書籍/記事執筆、翻訳、講演等を幅広く手がける。2018年11月時点での登録メンバは55名で、現在も執筆メンバを募集中。興味のある方は、どしどし応募頂きたい。著書記事多数。 RSS Twitter: @yyamada(公式)、@yyamada/wings(メンバーリスト) Facebook

※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です

この記事は参考になりましたか?

この記事をシェア

  • X ポスト
  • このエントリーをはてなブックマークに追加
CodeZine(コードジン)
https://codezine.jp/article/detail/4060 2009/07/14 14:00

おすすめ

アクセスランキング

アクセスランキング

イベント

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

新規会員登録無料のご案内

  • ・全ての過去記事が閲覧できます
  • ・会員限定メルマガを受信できます

メールバックナンバー

アクセスランキング

アクセスランキング