‘Java’ カテゴリーの投稿

はじめての JavaFX エンタープライズ・アプリケーション : JavaFX と JPA で実装するアプリケーション

本日は少しだけ JavaFX を触ってみました。正直 JavaFX は櫻庭大先生や、関谷さん、他の Embedded チームの皆様に助けて頂いているので、私自身あまり JavaFX に触っておらず自信もないのですが、今日は、JavaFX から JPA を使って DB に接続するクライアント・サーバのアプリケーションの作成してみました。

開発環境:

  • JDK 1.7 (Mac OSX 1.7.0_04)
  • NetBeans 7.1.1 or later (Mac OSX 1.7.0_04)
  • JavaDB (今回は GlassFish に付属の JavaDB を使用しました)

 

必要なライブラリ:

  • eclipselink-2.3.0.jar
  • javax.persistence-2.0.jar
  • org.eclipse.persistence.jpa.jpql_1.0.0.jar
  • derbyclient.jar (JavaDB 用のドライバ)

アプリケーションの概要:

このアプリケーションは DB に存在する顧客情報を参照するだけの簡単なアプリケーションです。JavaFX のアプリケーションから JPA を使用して DB に接続し顧客名とメールアドレスをアプリケーション上に表示します。「データの取得」ボタンを押下すると DB よりデータを取得し、テーブル内に表示し、「データのクリア」ボタンを押下すると表示内容をクリアします。

 

 

 

それでは実際に作成してみましょう。まず、NetBeans の「新規プロジェクト」を作成します。

次に、「JavaFX アプリケーション」のプロジェクトを選択します。

選択すると下記の画面が表示されますので、「プロジェクト名 (N) :」と「アプリケーションクラスを作成 (C)」を編集しプロジェクトに対して適切な名前、パッケージ、クラス名を指定します。

以上で JavaFX アプリケーションのプロジェクトが生成されました。この状態で「主プロジェクトを構築 (B)」を選択した後、「主プロジェクトを実行 (R)」を実行するとボタンが一つだけ表示される Window が表示されます。ボタンを押下すると標準出力に ”Hello World !”が表示されます。今回はこの自動生成されたJavaFX プロジェクトのひな形を改造しアプリケーションを作成します。

デフォルトで生成される Main クラスのひな形ソースコード

public class Main extends Application {

    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) {
        launch(args);
    }
    
    @Override
    public void start(Stage primaryStage) {
        primaryStage.setTitle("Hello World!");
        Button btn = new Button();
        btn.setText("Say 'Hello World'");
        btn.setOnAction(new EventHandler<ActionEvent>() {

            @Override
            public void handle(ActionEvent event) {
                System.out.println("Hello World!");
            }
        });
        
        StackPane root = new StackPane();
        root.getChildren().add(btn);
        primaryStage.setScene(new Scene(root, 300, 250));
        primaryStage.show();
    }
}

次にエンティティ・クラスを作成します。
※ 下記の方法は、既存で DB が存在し、既にテーブルが存在している場合の方法です。テーブルが存在しない状態でもエンティティクラスを生成できますが、簡単に説明するため今回は既存のテーブルを利用してエンティティクラスを生成します。
「新規」→「持続性」→「データベースからのエンティティクラス…」を選択します。

選択すると下記の画面が表示されます。ここで「関係する表を含める (I)」のチェックを外し「CUSTOMER」テーブルを選択した後、「次へ」ボタンを押下します。

ボタンを押下すると下記の画面が表示されます。ここでエンティティ・クラスのパッケージ名を適切に入力し「次へ」ボタンを押下します。

ボタンを押下すると下記の画面が表示されます。ここではデフォルトの設定のままで最後に「完了(F)」ボタンを押下します。

既存の DB テーブルを元に NetBeans で自動生成されたエンティティ・クラス

package jp.co.oracle.javafxsample.dao;

import java.io.Serializable;
import javax.persistence.*;
import javax.xml.bind.annotation.XmlRootElement;

/**
 *
 * @author Yoshio Terada
 */
@Entity
@Table(name = "CUSTOMER")
@XmlRootElement
@NamedQueries({
    @NamedQuery(name = "Customer.findAll", query = "SELECT c FROM Customer c"),
    @NamedQuery(name = "Customer.findByCustomerId", query = "SELECT c FROM Customer c WHERE c.customerId = :customerId"),
    @NamedQuery(name = "Customer.findByName", query = "SELECT c FROM Customer c WHERE c.name = :name"),
    @NamedQuery(name = "Customer.findByAddressline1", query = "SELECT c FROM Customer c WHERE c.addressline1 = :addressline1"),
    @NamedQuery(name = "Customer.findByAddressline2", query = "SELECT c FROM Customer c WHERE c.addressline2 = :addressline2"),
    @NamedQuery(name = "Customer.findByCity", query = "SELECT c FROM Customer c WHERE c.city = :city"),
    @NamedQuery(name = "Customer.findByState", query = "SELECT c FROM Customer c WHERE c.state = :state"),
    @NamedQuery(name = "Customer.findByPhone", query = "SELECT c FROM Customer c WHERE c.phone = :phone"),
    @NamedQuery(name = "Customer.findByFax", query = "SELECT c FROM Customer c WHERE c.fax = :fax"),
    @NamedQuery(name = "Customer.findByEmail", query = "SELECT c FROM Customer c WHERE c.email = :email"),
    @NamedQuery(name = "Customer.findByCreditLimit", query = "SELECT c FROM Customer c WHERE c.creditLimit = :creditLimit")})
public class Customer implements Serializable {
    private static final long serialVersionUID = 1L;
    @Id
    @Basic(optional = false)
    @Column(name = "CUSTOMER_ID")
    private Integer customerId;
    @Column(name = "NAME")
    private String name;
    @Column(name = "ADDRESSLINE1")
    private String addressline1;
    @Column(name = "ADDRESSLINE2")
    private String addressline2;
    @Column(name = "CITY")
    private String city;
    @Column(name = "STATE")
    private String state;
    @Column(name = "PHONE")
    private String phone;
    @Column(name = "FAX")
    private String fax;
    @Column(name = "EMAIL")
    private String email;
    @Column(name = "CREDIT_LIMIT")
    private Integer creditLimit;

    public Customer() {
    }

    public Customer(Integer customerId) {
        this.customerId = customerId;
    }

    public Integer getCustomerId() {
        return customerId;
    }

    public void setCustomerId(Integer customerId) {
        this.customerId = customerId;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getAddressline1() {
        return addressline1;
    }

    public void setAddressline1(String addressline1) {
        this.addressline1 = addressline1;
    }

    public String getAddressline2() {
        return addressline2;
    }

    public void setAddressline2(String addressline2) {
        this.addressline2 = addressline2;
    }

    public String getCity() {
        return city;
    }

    public void setCity(String city) {
        this.city = city;
    }

    public String getState() {
        return state;
    }

    public void setState(String state) {
        this.state = state;
    }

    public String getPhone() {
        return phone;
    }

    public void setPhone(String phone) {
        this.phone = phone;
    }

    public String getFax() {
        return fax;
    }

    public void setFax(String fax) {
        this.fax = fax;
    }

    public String getEmail() {
        return email;
    }

    public void setEmail(String email) {
        this.email = email;
    }

    public Integer getCreditLimit() {
        return creditLimit;
    }

    public void setCreditLimit(Integer creditLimit) {
        this.creditLimit = creditLimit;
    }

    @Override
    public int hashCode() {
        int hash = 0;
        hash += (customerId != null ? customerId.hashCode() : 0);
        return hash;
    }

    @Override
    public boolean equals(Object object) {
        // TODO: Warning - this method won't work in the case the id fields are not set
        if (!(object instanceof Customer)) {
            return false;
        }
        Customer other = (Customer) object;
        if ((this.customerId == null && other.customerId != null) || (this.customerId != null && !this.customerId.equals(other.customerId))) {
            return false;
        }
        return true;
    }

    @Override
    public String toString() {
        return "jp.co.oracle.javafxsample.dao.Customer[ customerId=" + customerId + " ]";
    }
    
}

これで、JPA のエンティティクラスが生成されましたので、これを元に JavaFX で DB のデータを参照するアプリケーションを作成します。

まず、DB に接続し全データを取得する部分ですが、getData() メソッドで実装します。GlassFish の Java DB を利用した場合、上記までの手続きにより、自動的に Persistence Unit (持続性ユニット) の設定が行われています(※ その他の DB を利用する場合、別途 NetBeans の「新規」→「持続性」→「持続性ユニット…」を選択し持続性ユニットの設定を行ってください)。
持続性ユニットの設定が適切に行われている場合、プロジェクト内に persistence.xml というファイルが生成されています。この persistence.xml 設定ファイルには DB サーバへ接続するための情報(JDBC ドライバ、接続 URL、ユーザ名、パスワード)等が記載されていますが、プログラム上からどの持続性ユニットを利用するかを指定できるように持続性ユニット名が記載されています(この例では JavaFX-JPA-SamplePU)。

persistence.xml 中の持続性ユニット名の設定(全設定は最後にまとめて記載)

<persistence-unit name="JavaFX-JPA-SamplePU" transaction-type="RESOURCE_LOCAL">

JavaFX のアプリケーションではこの持続性ユニット名を指定してエンティティを管理するための、EntityManager を生成します。EntityManager を生成した後、JPQL の NamedQuery (NetBeans では上記エンティティ・クラスに記載されているように、基本的な Named クエリが複数自動生成。ここではCustomer に記載されている @NamedQuery(name = “Customer.findAll”, query = “SELECT c FROM Customer c” ),) を使用して全データを取得します。取得したデータは List にコピーし返します。

getData() の EntityManager 生成部分(全ソースコードは最後にまとめて記載)

        EntityManagerFactory emf =
                Persistence.createEntityManagerFactory("JavaFX-JPA-SamplePU");
        EntityManager em = emf.createEntityManager();
        TypedQuery tquery = em.createNamedQuery("Customer.findAll", Customer.class);
        List<Customer> list = tquery.getResultList();

「データの取得」ボタンが押下された際に、DB に接続しデータを JavaFX のテーブルに表示するため、ボタンが押下された際のイベントをハンドリングします。この際 JavaFX では javafx.scene.control.TableView の setItems(ObservableList < S > value) を利用してプロパティを設定する事ができます。List から ObservableList を生成するために、JavaFX で用意されている便利なユーティリティクラス FXCollections を使用して変換します。変換後 TableView#setItems() メソッドの引数に代入し実行します。

        btn.setOnAction(new EventHandler<ActionEvent>() {
            @Override
            public void handle(ActionEvent event) {
                ObservableList<Customer> data = 
                FXCollections.observableArrayList(getData());
                table.setItems(data);
            }
        });

後は、説明の必要もないかと思いますが、TableColumn でどの項目を表示するかを記載して完了です。FXCollections という便利なユーティリティツールが用意されている事もあり、JPA のエンティティをとても簡単に扱う事ができます。もちろん昔ながらの JDBC で記載する事も可能かと思いますが、JPA の方がとても簡単に効率良く実装できる事がわかるかと思います。

さて実装が終わったので、プロジェクトを構築して実行するわけですが、実はこの状態でプログラムを実行するとエラーが発生します。なぜなら現時点で本プロジェクトに JDBC ドライバのライブラリを組み込んでいないためです。


[EL Severe]: 2012-05-24 18:42:32.336–ServerSession(1090664123)–Local Exception Stack:
Exception [EclipseLink-4003] (Eclipse Persistence Services – 2.3.0.v20110604-r9504): org.eclipse.persistence.exceptions.DatabaseException
Exception Description: Configuration error. Class [org.apache.derby.jdbc.ClientDriver] not found.

そこで、JavaDB 用の JDBC ドライバを組み込みます。ライブラリを選択し「JAR/フォルダを選択…」を選択してください。

選択すると下記の画面が表示されますので、JavaDB 用の JDBC ドライバを選択します(derbyclient.jar)。

ライブラリを組み込むと下記のように表示されます。

ドライバを組み込んだ後、プロジェクトを構築します。

次にアプリケーションを実行します。


 

最後に、今回は JavaFX アプリケーションとして、アプリケーションを作成しました。つまりこのアプリケーションでは、コネクション・プール等を利用していない為、ボタンを押下する度に DB に対して接続が発生します。そこでこのアプリケーションを大量に配布した場合、DBに対して高負荷を与える可能性もあります。
そのような場合、もちろんこのアプリケーションをアプリケーション・クライアント・コンテナを含めて作成する事も可能です。アプリケーション・クライアント・コンテナ上で作成すると、アプリケーション・サーバ上のリソースをアノテーションを利用して注入できるようになる他、アプリケーション・サーバ上で EJB を作成し、それを参照するようにする事でコネクション・プールの利用もできるようになるため、DB に対する負荷も軽減できるようなります。要件に応じてはクライアント・サーバ型のアプリケーションの実装が必要になる場合もあるかと思いますが、場合によってはアプリケーション・クライアント・コンテナ上でアプリケーションを実行する事もご検討ください。

Main クラスの全ソースコード:

package jp.co.oracle.javafxsample;

import java.util.List;
import javafx.application.Application;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.geometry.Insets;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
import javafx.scene.control.cell.PropertyValueFactory;
import javafx.scene.layout.VBox;
import javafx.scene.paint.Color;
import javafx.stage.Stage;
import javax.persistence.*;
import jp.co.oracle.javafxsample.dao.Customer;

/**
 *
 * @author Yoshio Terada
 */
public class Main extends Application {

    /**
     * @param args the command line arguments
     */
    
    private TableView table = new TableView();
    
    public static void main(String[] args) {
        launch(args);
    }

    @Override
    public void start(Stage primaryStage) {

        Scene scene = new Scene(new Group(), 500, 400, Color.LIGHTGRAY);
        primaryStage.setTitle("顧客情報参照アプリケーション");

        final Label label = new Label("顧客情報の参照");

        //テーブルの初期化
        TableView table = initTable();
        
        //ボタンの初期化
        Button getBtn = initGetButton();
        Button clrBtn = initClearButton();
        
        VBox vbox = new VBox();
        vbox.setSpacing(2);
        vbox.getChildren().addAll(label, table,getBtn,clrBtn);
        vbox.setPadding(new Insets(10, 0, 0, 10));
        vbox.setPrefSize(480, 380);

        ((Group) scene.getRoot()).getChildren().addAll(vbox);
        primaryStage.setScene(scene);
        primaryStage.show();

    }

    private TableView initTable() {
        TableColumn nameCol = new TableColumn("顧客名");
        nameCol.setMinWidth(200);
        nameCol.setCellValueFactory(new PropertyValueFactory<Customer, String>("name"));

        TableColumn emailCol = new TableColumn("電子メール");
        emailCol.setMinWidth(280);
        emailCol.setCellValueFactory(new PropertyValueFactory<Customer, String>("email"));

        table.setEditable(true);
        table.setPrefWidth(480);
        table.getColumns().addAll(nameCol, emailCol);

        return table;
    }

    private Button initGetButton() {
        Button btn = new Button();
        btn.setText("データの取得");
        btn.setOnAction(new EventHandler<ActionEvent>() {
            @Override
            public void handle(ActionEvent event) {
                ObservableList<Customer> data = 
                FXCollections.observableArrayList(getData());
                table.setItems(data);
            }
        });
        return btn;
    }
    
    private Button initClearButton() {
        Button btn = new Button();
        btn.setText("データのクリア");
        btn.setOnAction(new EventHandler<ActionEvent>() {

            @Override
            public void handle(ActionEvent event) {
                table.setItems(null);
            }
        });
        return btn;
    }

    // JPA を使用して DB よりデータの取得
    private List getData() {
        EntityManagerFactory emf =
                Persistence.createEntityManagerFactory("JavaFX-JPA-SamplePU");
        EntityManager em = emf.createEntityManager();
        TypedQuery tquery = em.createNamedQuery("Customer.findAll", Customer.class);
        List<Customer> list = tquery.getResultList();

        if(em != null)
            em.close();
        if(emf != null)
            emf.close();
        return list;
    }
}

persistence.xml の内容

<?xml version="1.0" encoding="UTF-8"?>
<persistence version="2.0" xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd">
  <persistence-unit name="JavaFX-JPA-SamplePU" transaction-type="RESOURCE_LOCAL">
    <provider>org.eclipse.persistence.jpa.PersistenceProvider</provider>
    <class>jp.co.oracle.javafxsample.dao.Customer</class>
    <properties>
      <property name="javax.persistence.jdbc.url" value="jdbc:derby://localhost:1527/sample"/>
      <property name="javax.persistence.jdbc.password" value="app"/>
      <property name="javax.persistence.jdbc.driver" value="org.apache.derby.jdbc.ClientDriver"/>
      <property name="javax.persistence.jdbc.user" value="app"/>
    </properties>
  </persistence-unit>
</persistence>

2012年5月24日 at 8:26 PM 1件のコメント

Turning the potter’s wheel at JavaOne Tokyo

Recently the word of “Turning the potter’s wheel” is very popular in Japan.
One Japanese guy(Kouhei Iida-san) asked why the presentator always “Turning the potter’s wheel” at the explanation?

And another guys evaluate whether it is right or not as follows.
Turning the potter’s wheel

As a result, so many presentator even though Steave Jobs had turned the potter’s wheel. And It’s not a bad meaning at all. And it’s a one of the expression of the enthusiastic.

And Today I confirmed JavaOne Tokyo speakers.
(Sorry all of ther speakers I coulnd’t take the photos.)

And so many speaker had turned the potter’s wheel as follows.

For All of JavaOne Tokyo speakers :
Great Thank you so much for your excellent presentation !!

Thank you & Best Regards.
Yoshio.











2012年4月8日 at 3:10 AM コメントする

JavaOne Tokyo のお礼

JavaOne Tokyo にご参加頂いた皆様、誠にありがとうございました。心より御礼申し上げます。

開催前日は、あいにくの空模様で交通機関が完全に麻痺してしまったため、地方からご参加いただいた皆様の中には前日に東京にお越し頂く事ができなかった方がいらっしゃる事を伺っております。また当日お越し頂けた皆様の中には、新幹線に切り替えて、それでも新幹線が東京に到着するのが深夜となり、ホテルまでタクシーで移動された方もいらっしゃると聞いています。そのような大変な状況にも関わらず、北は北海道から南は沖縄まで日本全国から、JavaOne Tokyo にご参加頂きました皆様、本当にありがとうございました。

JavaOne Tokyo がこれだけ盛り上がったのも、一重に日本全国からご参加頂いた数多くの Java 開発者の皆様のおかげでございます。皆様のご参加、心より御礼申し上げます。

今回の JavaOne は7年振りという事もあり、JavaOne を全くご存知ない世代の方々も数多く参加して頂けたのではないかと思います。JavaOne をご存知ない世代の方々に対して、Java の開発者の祭典である JavaOne を再び日本でお届けできた事を心より嬉しく思っております。

また、この2日間、Twitter 上に JavaOne のメッセージで溢れ帰る程の多くのつぶやきが見受けられました。この JavaOne の盛り上がり、Java 開発者の皆様のメッセージは、本社社員や、日本のオラクル社員にも十分伝わっておりますし、今回残念ながらご都合が悪くご参加いただけなかった皆様も、皆様のツイートを見て、次回は是非参加したいと言って下さっている方もお見かけ致しました。これもご参加頂いた皆様が数多くのフィードバックをしてくださったからだと思います。本当にありがとうございました。

さらにはブログで、本場 JavaOne サンフランシスコに参加された Nobeans さんも、下記のように本場 JavaOne サンフランシスコのようで楽しかったというようなメッセージも頂きました。単なる日本における Java の勉強会ではなく JavaOne Tokyo ができたんだなと嬉しく思いました。

あと、JavaOneTokyo全体の感想としては、一言で言えば超楽しかったです。
去年と一昨年にSFのJavaOneに参加してきたんですが、
“今回タワーホールとかでセッション開始待ちしてるときの雰囲気とか
音楽とかもう去年のSFのJavaOneそのもので、すっごいテンション
あがりました。もうそのままSFにいるみたいな気分。”

 

その他にも下記のように数多くのブログの投稿を頂いております(すいません全てハンドリングできていないかもしれません、もし自分も書いたという方がいらっしゃいましたら、是非教えていただけないでしょうか)。多くの皆様から楽しかった!!というようなメッセージを頂き、次回開催希望も多く承っております。これら開発者の皆様の声はちゃんと US や日本の上層部にお伝え致します。(実は既にこのブログを書く前に、社長、取締役に報告しております。(^_^))

JavaOne Tokyo に参加してくださった皆様のブログ:

その他、下記のように Togetter にまとめて下さった方々も多数いらっしゃいます。誠にありがとうございます。

Togetter のまとめ一覧:

最後に、
繰り返しになりますが、この度は JavaOne Tokyo 2012 にご参加頂きまして誠にありがとうございました。JavaOne Tokyo がまたいつか開催できればと思っております。誠に簡単ではございますが、JavaOne Tokyo に携わってくださった全ての皆様に御礼のご挨拶まで!!

2012年4月7日 at 7:19 PM コメントする

JavaOne 受講票引換券の印刷のお願い

 

JavaOne Tokyo 2012 にご参加の皆様

JavaOne 当日、マイページから入手可能な、受講票引換券をプリントアウトし受付にお持ちください、受講票と交換致します。

仮にマイページのログイン方法が分からない場合、もしくは受講票の引換券が表示されない等のなどの問題がございましたら、下記のレジストレーション事務局までお問い合わせください。

お問い合わせ:
JavaOne Tokyo レジストレーション事務局
E-Mail:info-javaone_jp AT oracle.com
TEL:03-6834-4694(平日10:00~18:00)

詳細:
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
JavaOne Tokyo 2012 受講票引換券発行/当日のご来場に関するご案内
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
申込番号:[XXXXXXXXXX]

この度は、JavaOne Tokyo 2012にお申し込みいただきありがとうございます。マイページより受講票引換券の発行を開始させていただきましたのでお知らせいたします。お手数ではございますが、ご来場前にご自身で受講票引換券を印刷し、当日はお忘れのないようお持ちください。

また、下記のご案内につきましては、ご来場前に必ずご一読くださいますようお願い申し上げます。

■受講票引換券の印刷/受講票のお渡し
マイページにログイン後、お申込み内容(選択セッション)一覧の右側の列に表示される「受講票の印刷」を押下し、受講票引換券を印刷してください。ご来場の際は、受講票引換券をお忘れなくお持ちください。受付にて受講票をお渡しいたします。

マイページURL: https://oj-events.jp/public/mypage/login?type=jo
ログインID:[XXXXXXXXXX]
パスワード:ご登録時にご自身で設定されたパスワード
※パスワードをお忘れの方は、上記マイページログインページに記載の
「パスワードをお忘れの方はこちら」より、再設定ください。

「ご注意」
◇受講票引換券を一度印刷した後、セッションの変更をされた場合は、再度
受講票引換券を印刷してください。当日は受講票引換券に記載のお申込み内容(選択セッション)を確認させていただき、記載がないセッションにはご入場いただけない場合がございますのでご注意ください。

◇受講票引換券及び受講票は2日間共通となります。
受講票引換券をお忘れになりますと再発行までにお時間がかかる場合があり
ますのでご注意ください。また、当日お渡しいたします受講票の再発行は致しかねますので、開催期間中は無くさないよう大切に保管してください。

■当日の受付
[受付場所] 六本木アカデミーヒルズ49
(〒106-6149 東京都港区六本木6-10-1 六本木ヒルズ森タワー49階)
[受付オープン時間] 4月4日(水)-5日(木) 8:00-19:30

印刷した受講票引換券を受付にてご提示ください。
当日朝は混雑が予想されますので、お時間に余裕をもってご来場ください。

※学生向け特別プログラムにてご参加の方は受講票引換券とともに「学生証」をご提示ください。

■来場者特典(カンファレンスバッグ/オリジナルTシャツ)
各日11時より会場内引換所にてお渡しいたします。来場者特典の引換券は受付にてお渡しいたします(お1人様1回限り)。

お問い合わせ:

JavaOne Tokyo レジストレーション事務局
E-Mail:info-javaone_jp AT oracle.com
TEL:03-6834-4694(平日10:00~18:00)

日本オラクル株式会社

 

2012年4月2日 at 2:05 PM コメントする

新しい Java SE API リファレンスの入手先について

2012 年 03 月 25 日、sun.com のドメインが利用不可になりました。これに併せ、java.sun.com で提供されていた Java SE API 日本語ドキュメントもオンライン経由で参照する事ができなくなりました。今後、日本語の Java SE API レファレンスはオンライン経由では参照できなくなりますので、アーカイブを御入手の上、ローカル環境でご参照ください。お手数をお掛けし申し訳ございませんが、どうぞ宜しくお願いします。

Java API の日本語ドキュメントはコチラから入手が可能です。
ドキュメントの再配布ポリシーはコチラをご参照ください。

新しい日本語 API ドキュメントのオンライン参照先URL (2012/4/11 訂正、追記)

PS.
引き続き、英語の API ドキュメントはオンラインで参照可能です。

Java SE 7 API Documentation
Java SE 6 API Documentation
J2SE 5 API Documentation
J2SE 1.4.2 Documentation
J2SE 1.3.1 Documentation

2012年3月25日 at 10:30 PM 3件のコメント

JavaOne Tokyo 2012 Call For Papers 募集中

JavaOne Tokyo 2012 を 2012 年 4 月 4日~5日の2日間で開催します。既にいろいろなセミナー等でご案内をさし上げているため、ご存知の方も多いかと思いますが、今日は JavaOne 2012 Tokyo の一般公募セッション (Call for Papers) についてご案内させていただきたいと思います。

JavaOne Tokyo では朝はやくから夜遅くまで Java に関する技術情報等を取得できるようになっていますが、通常セッション枠、BoF 枠と用意しそれぞれで一般の開発者の皆様もご登壇いただけるように公募を行なっています。一般公募の募集期間は 2012年1月20日(金)17時まで行なっております。

また、本公募は、日本だけではなく、US Oracle 本社による審査も行われますので、実際の発表のタイトルは日本語でも結構ですが、英語で説明を記載できる方は英語でご記入してください。

残り1週間程となっておりますが、JavaOne Tokyo で私も発表したいという方がいらっしゃいましたら是非ご応募ください。
皆様のご応募を心よりお待ちいたしております。

2012年1月11日 at 3:29 PM コメントする

はじめての Java Persistence API

今日は、Java Advent カレンダーの一貫で 12/19 分のエントリを記載します。昨日のなぎせさんに続き掲載します。また明日は私の盟友である岡崎さんです。

先日、なぎせさんより、「ProxyパターンとProxyクラスと黒魔術」と題してSQL の事を取り上げていただきました。また私自身、先日岡山のイベントで JPA について登壇したばかりなので、今日は DB つながりということで JPA (Java Persistence API) について岡山の資料を利用しながらご紹介します。

岡山の発表資料の全部はこちらです。

Java でデータベース (DB) 接続をする際、Java で一番最初に DB 接続をサポートした事から、ながく JDBC が利用されてきました。その後、J2EE に EJB の CMP Entity Bean が導入されましたが、これはとても重量級で扱いにくいフレームワークだったため、残念ながらあまり浸透しませんでした。それに変わって登場したのがオープンソースのフレームワークである JDO/Hibernate などです。

昨今、「もう Java EE 6 でいいんじゃない」、Java EE 6 はかんたんになりましたよ、などのブログ・エントリを書いたり、いろいろな所で登壇させて頂きましたが、JPA もまたかんたんに利用できるようになった、 Java EE の標準 O/R マッピング技術です。JPA は上記のようなオープンソースの O/R マッピング・フレームワークの良い部分を数多く取り入れ、かなり扱いやすくなっていますので、是非今一度標準の JPA のご使用を検討ください。また、JPA 2.0 は JPA 1.0 に比べ表現力がかなり豊かになっていますので、JPA 1.0 で物足りなさを感じられた方も今一度ご検討ください。JPA 2.0 になり、通常のビジネスアプリケーション開発のニーズをほぼ満たせると考えております。

また、ご存知の方もいらっしゃるかと思いますが、JPA は Java EE コンテナ以外の、通常の Java アプリケーションからも利用することができるようになっています。実際、JPA は GAE などでも利用できます。つまり今まで JPA はアプリケーションサーバ上でしか利用できないと思われていた方も、Java EE 環境がなくても JPA は利用できますので Java アプリケーション開発等コンテナの無い環境でも使用をご検討ください。

それでは、JDBC に比べて何が便利になっているかについて説明します。JDBC は低レベルの API しか提供していなかったため、自分で考慮、実装しなければならない事が数多くありました。例えば、JDBC をそのまま利用した場合、コネクションプールの実装はデフォルトでないため、DB にたいする問い合わせ(クエリ)を行う際に、毎回 DBに対してコネクションを張りにいかなければなりませんでした。またキャッシュも実装されていないため、毎回 DB にたいする操作を行わなければなりません。DB サーバにたいする問い合わせ(クエリ)数が少ない場合は、コネクションプールも、キャッシュもさほど重要ではないかもしれませんが、Web アプリケーションのように、クライアントからのリクエスト毎に DB の情報を参照するようなアプリケーションの場合、リクエスト毎に接続を張る、もしくはたとえ同じ情報を読むだけでも DB に接続するなど、必要以上に DB サーバに対して高負荷が掛かってしまいます。このような場合、コネクションプールを利用して DB 接続を再利用したり、キャッシュを利用する事で DB サーバにたいする負荷を軽減できます。さらに、JDBC を利用した場合トランザクション管理についても全て自身で実装、管理しなければならないため、JDBC を利用した場合、数多くの事を考慮しなければならない事がわかります。
JPA を利用すると、このような JDBC で開発者が考慮し実装しなければならない多くの機能を JPA のフレームワーク自身で既に実装していますので、開発者はそれらを再利用、もしくはコンテナに任せることがで、より安全にスケールするアプリケーションをコード量少なく短時間で開発できるようになります。つまり一言でいうならば、JPA を使用する場合、開発生産性が大幅に向上するという事です。たとえば、統合開発環境と連携する事で基本的な CRUD 操作のひな形まで自動生成してくれるためコード記述量も格段に減ります。

それでは実際に、 JPA の構成要素についてご紹介します。JPA は persistence.xml という XML 設定ファイル中に PersistenceUnit を(1つ以上)定義します。この PersistenceUnit 名は EntityManagerFactory のインスタンスを生成するために必要です。EntityManagerFactory から EntityManager のインスタンスを生成し、DB にたいする操作をおこないます。

永続化:EntityManager#persist()
削除:EntityManager#remove()
検索:EntityManager#find()

DB の操作を行う際、DB テーブルにたいして Java オブジェクトにマッピングした、Entity クラス(@Entity アノテーションを付加したクラス)を利用しておこないます。Java はオブジェクト指向型言語でクラスとして表現します、一方 DB はテーブルとして表現し、個々のデータを行(ロー)で表現します。JPA 2.0 は JPA 1.0 にくらべ Entity と DB テーブルのマッピング方法も数多く追加で提供されていますので、複雑な DB テーブルも Entity としてマッピング可能です。(本ページ下の参考資料をご参照)


繰り返しますが、Entityは @Entity のアノテーションを付加した単なる POJO です。この Entity クラスは JPA によって管理されていない状態では、単なる Java のオブジェクトとして扱います (例 new MyEntity() でインスタンスを生成した直後の状態)。Persistence Context による管理状態と管理されていない(デタッチ)状態でなにが違うかライフサイクルを用いて紹介します。管理状態とは、Persistence Context によって管理されている状態を指し、すべての Entity はPersistence Context によって管理されています。この状態の時に EntityManager を使って DB に永続化等を行う事ができます。

ライフサイクルの各状態を、実際のコードを用いて説明します。この例ではまず、Customer クラスが Entity で DB の CUSTOMER テーブルにマッピングしています。new Customer(); でインスタンスを作成します。この際、Java の Heap に Customer オブジェクトは含まれていますが、この時点では Persistence Context 内でまだ管理されていません。EntityManager#persist(customer) を実行する事により Persistence Context で管理状態となります。この状態で DB テーブルに対して操作を行うことができますが、たとえばトランザクションのコミット tx.commit() が呼び出されると、DB に対して永続化が行われ、この時に Customer の Entity は Persistence Context の管理状態から外れます(デタッチ状態)。ただし、この Persistence Context の管理状態から外れた際も、Customer は Java Heap 内に参照が残っているため、Java プログラムからは Customer オブジェクトに対しては操作する事ができます(例えば、Customer 電話番号の変更等)。管理状態から外れデタッチ状態の Customer に対して変更を加えた場合、対応する DB の行(ロー)と整合性がとれていません、そこでデタッチ状態の時に加えられた変更を EntityManager#merge() によって更新することができます。

上記までで、Entity, Entity のライフサイクル等を紹介しましたが、EntityManager の管理はアプリケーションサーバ等のコンテナ上で管理する方法と、アプリケーションで管理する方法の二種類があります。またそれぞれでできること、実装方法も異なります。下記にそれぞれにおける違いについてご紹介します。まず、コンテナ上で EntityManager を生成する方法は、@PersistenceContext のアノテーションを付加し persistence.xml に定義した PersistenceUnit 名(ここでは MYJPA_PU)を指定し、EntityManager にインジェクションします。ここでインジェクションされた EntityManager はコンテナ上で動作するため、トランザクション管理等もコンテナ側で行なってくれます。つまりトランザクション管理のコードを明示的に記載しなくても、EntityManager#persist() を実行した際に何らかの例外が発生した場合は、コンテナが自動的にロールバックします。

一方アプリケーションから管理する場合は、@PersistenceContext のアノテーションを付加する方法ではなく、Persistence.createEntityManagerFactory(“MYJPA_PU”)でファクトリを生成後、EntityManagerFactory#createEntityManager() にて EntityManager のインスタンスを生成します。アプリケーションから管理する場合は、コンテナによってトランザクション管理ができないため自身の手でトランザクション管理のコードを記述する必要があります。

最後に DB にたいする問い合わせ方法について紹介します。最もかんたんな方法として EntityManager の find(), getReferecnce() を利用して ID を指定し行う方法があります。しかし一般的には SQL に精通する開発者が問い合わせ(クエリー)を実装しやすいように、JPQL(Java Persistence Query Language) というSQL ライクなクエリ言語を使用して問い合わせをおこないます。通常の SQL はカラムを指定して問い合わせを実施しますが、JPQL では Entity を使用して問い合わせをおこないます。JPQL もまた JPA 2.0 は JPA 1.0 にくらべ表現力が高くなっており、さまざまな問い合わせを実現できますので是非 JPQL をご利用ください。

次に、DB へ問い合わせを行うために、JPQL よりもさらに型安全性を高める実装が可能な Criteria API について紹介します。Criteria API は Java プログラミングによる問い合わせが可能な API を提供します。具体的には、CriteriaBuilder, CriteriaQuery などのクラス、メソッドを使用して実装します、例えば下記のように JPQL クエリを、Java プログラミングで実装する事ができます。

ここで一番最後の行に記載する person.get(“name”) と記載している箇所に注目してください。ここでは、正しく “name” という文字列を使用して記述していますが、仮に “name” と入力すべき所を “nema” と入力ミスしてしまった場合を考えてください。このプログラムを実行するためコンパイルをおこないますが、文法上の間違いはないためコンパイルエラーは発生しません。結果として実行時にランタイムエラーが発生します。


つまり上記のように、Criteria API だけでは完全な型安全性が確保できていないことがわかります。型安全性をより高めるためには、Criteria API に加え Metamodel API を併用します。この Metamodel クラス(元の Entity に対して ”_” アンダーバーが付加)は統合開発環境によっては自動生成してくれるため、自分で作成しなくても良い場合もありますが、この Metamodel クラスを Criteria API と併用すると、person.get(“name”) の代わりに person.get(Person_.name)と記載でき、クラスのフィールドで指定可能となるため、コンパイル時に間違いを検知できるようになりランタイムエラーの発生を抑制できます。型安全をより求める場合は、Criterial API と Metamodel クラスを共にご使用ください。

最後に、繰り返しになりますが、
JDBC で実装する場合、自分で実装しなければならないコード、検討しなければならない箇所が多々ありますが、JPA を利用すると、そういった共通で必要な機能はすべてフレームワークが生成してくれています。全ての場合で JPA が有効とは申し上げませんが、JPA を使う事によりスケーラビリティを高める事が容易にできたり、また開発生産性が高まる事によって、よりビジネスロジックの開発に集中していただく事ができるようになります。また運用・保守時においても実装コードの可読性が大幅に高まるため、より保守しやすくなります。今まで標準以外の O/R マッパを使っていた方々も、標準でここまで簡単にできるようになっています。是非 JPA 2.0 を今一度ご検討ください。

JPA 2.0 の新機能はこちらもご参照ください。

私が参考にする Web Page
Java Persistence

おすすめ書籍

2011年12月19日 at 2:03 PM 1件のコメント

Java 関連ビデオのご紹介

もうすでに、Java Life のラップはご存知の方が多いかと思いますが、Java Life のラップはメーキングビデオ等も作られていたりします。その他今年の Java SE 7 Launch イベントや、 JavaOne の基調講演で実際に流されたビデオをご紹介します。クールなビデオもありますので、是非暇な時にでも御覧ください!!


(Java Life RAP)


(Java Life RAPのメーキング)


(Java SE 7 Launch イベント)

(JavaOne 基調講演で流されたビデオ)

2011年12月4日 at 12:28 AM コメントする

オラクルの Java エバンジェリストとして活動再開して1年経過

Duke
オラクル社員となって、昨年の 12 月 1 日にまた Java エバンジェリストとして活動を再開し早いもので1年が経過しました。この1年間様々な出来事があり、色々と大変なこともありましたが何とかそれらの試練を乗り越えることができました。これも一重に私を支えてくださった諸先輩や同僚、そしてJJUG の皆様や日本全国の勉強会でお会いした多くの開発者の皆様のおかげです。皆様のご支援があったからこそ私もこの1年精力的に活動ができました。皆様本当にありがとうございました。来年開催予定の JavaOne Tokyo に向けてこれからも精力的に活動をしてまいりますので、今後もどうぞご支援の程宜しくお願いします。ちなみに JavaOne 2012 Tokyo の登録開始は 1 月 24 日(火)を予定しています。それまで是非楽しみにお待ちください。

ところで、1年前に書いたブログを見てみました、それによると1年間でこんな事を実現したいという意思表示を行なっていました。http://yoshio3.com/2010/12/01/

● 日本 Oracle における Java の窓口を用意する予定です。
→ 実現不可
● Java に対する継続的なメッセージアウトを行います。(ブログ、講演等で)
 ■ 上記を通じJava に対する皆様の不安を払拭していきます。
 ■ Java が今後も安心してお使いいただけるプラットフォームである
  事を、ご理解頂けるよう努めてまいりたいと思います。
→ デブサミ、記事、インタビュー、Java SE 7 Launch、JavaOne 報告会
  などを通じ少しでもメッセージをお届けできたのではないかと思っております。
● 2012 年開催予定の JavaOne (Tokyo or Yokohama ?!) の成功に向けて
 各種方面の調整等を行っています。
→ これから本格的に活動開始ですが、各種コミュニティのご意見などを
  承りながら成功に向け今後も活動したいと思っております。

これらの中で実現できなかったのは下記でした。

● 日本 Oracle における Java の窓口を用意する予定です。

実現に向け取り組んでいたのですが、諸事情により実現ができず申し訳ございませんでした。今は私がコミュニティの皆様の声を吸い上げ、日本オラクルもしくは本社へ情報インプットしていますが、これを将来的には会社としてできればよいと思っております。それに向け社内で継続して支援者、支援組織を模索したいと考えております。
もちろん、今まで同様、私にメッセージをお届けいただければ私に可能な事は対応していきたいと考えておりますので今後もどうぞよろしくおねがいします。

最後に、
この1年間できた事とできなかった事ありましたが、ご支援頂いた皆様本当にありがとうございました。来年に向けまた精力的な活動を行なっていきたいと思いますので、引き続きどうぞよろしくおねがいします。

2011年12月1日 at 1:55 AM コメントする

Java SE 7 Launch イベント全国キャラバン開催

先日、本ブログでもアナウンスさせて頂きましたが、Java SE 7 が 7月28日に正式リリースされます。これに併せ、日本全国の各Java ユーザグループ(コミュニティ)主催で Java SE 7 の Launch イベント全国キャラバンを開催します。現時点で予定されている場所・日程は下記の通りです。まだ告知ページが公開されていない所もございますが、各詳細情報は、各 Java ユーザグループ(コミュニティ)よりご入手ください。

7/1 : Javaコミュニティ@九州 セミナー
7/7 : 帰ってきた Java HotTopic セミナー:Java SE 7 リリース記念 特別イベント
7/9 : 札幌 Java Conference 2011
7/16 : 関ジャバカンファレンス 2011
7/30 : Java Kueche 6周年記念講演会 & Java Kueche 第六期 総会

また、7月7日には日本オラクルで「帰ってきた Java HotTopic セミナー:Java SE 7 リリース記念 特別イベント」を開催します。
Sun の頃に開催していた Java HotTopic セミナー


2006 年 Java SE 6 が登場 5 年が経過し、ついに待望の Java SE の 新バージョンが 2011 年 7 月 28 日にリリースされます。 本イベントでは Java SE 7 リリース直前の特別記念イベントとして、 Java SE 7 に関する様々なトピックを紹介します。 前半のセッションでは、Java SE 7の全体像、さらにJava SE 8 で実現 される機能についての解説とオラクルの Java に対する考え方を紹介 する他、HotSpot と JRockit の今後等、Java の現在と今後について 分かり易く紹介します。 後半のセッションでは、Java SE 7 の主要な新機能である、Project Coin, InvokeDynamic, NIO.2, JSR-166y をデモや実例紹介を交えながら詳細に ご説明致します。 本セミナーに参加する事で Java SE 7 の全体概要を把握する事ができる だけでなく、今すぐ使える技、Tips 等も理解する事ができます。 Java SE 7 リリースを記念する本セミナーに是非ご参加ください。

開催概要
日程: 2011年7月7日 (木) 14:00~19:00 (受付時間: 13:30~)
会場: オラクル青山センター
会場住所: 〒107-0061 東京都港区北青山2-5-8

Twitter ハッシュタグ #java7
UStream :http://www.ustream.tv/channel/java-seminar-jp

詳細・お申込みはこちらから

是非、Java SE 7 Launch のイベントにお近くの会場まで足をお運びください。登壇者、ユーザグループ、コミュニティ一同心よりお待ち申し上げます。

2011年6月16日 at 12:19 PM 2件のコメント

過去の投稿


ご注意

このエントリは個人の見解であり、所属する会社の公式見解ではありません

カレンダー

2012年5月
« 4月    
 123456
78910111213
14151617181920
21222324252627
28293031  

カテゴリー

最近の投稿

Twitter

  • @boochnich センター棟で開催致しますので、センター棟(セミナーホール、402, 403, 405)までお越し頂けないでしょうか。 #jjug_ccc3 hours ago
  • JavaQne にご参加の皆様、今日はどうぞ宜しくお願いします。お土産も持ってまいりましたので是非楽しみにしてください!!#java #javaqne 3 hours ago

ブログ統計情報

  • 210,041 hits

RSSフィード


フォロー

Get every new post delivered to your Inbox.

現在1,361人フォロワーがいます。