クエリの実行

今回はクエリの実行です。

【前提条件】

[環境]
[その他]
  • 前回*1のデータやソースを一部再利用

【概要】

JPA2.0でクエリを実行する場合は
javax.persistence.NamedQueryアノテーションを使用します。

サンプルは前回の一覧に検索機能を追加したものです。

【サンプルコード】

[テーブル]

今回のサンプルのテーブルとテーブルのデータは
前回までの「userdata」テーブルと「user_authority」テーブルを使います。

[Entity]

UserDataクラスを直します。
UserAuthorityクラスは修正しません。

package jp.glory.persistence.entity;

import java.io.Serializable;
import java.sql.Timestamp;
import java.util.List;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.JoinColumns;
import javax.persistence.NamedQueries;
import javax.persistence.NamedQuery;
import javax.persistence.OneToMany;
import javax.persistence.Table;

@Entity
@Table(name = "userdata")
@NamedQueries({
        @NamedQuery(name = "findAll", query = "SELECT u FROM UserData u"),
        @NamedQuery(name = "findByUserId", query = "SELECT u FROM UserData u WHERE u.userId = :userId"),
})
public class UserData implements Serializable {

    private static final long serialVersionUID = 6528642302239465812L;

    @Id
    @Column(name = "user_id")
    private String userId = null;

    private String name = null;

    @Column(name = "last_update")
    private Timestamp lastUpdate = null;

    @OneToMany
    @JoinColumns({
        @JoinColumn(name = "auth_user_id", referencedColumnName = "user_id")
    })
    private List<UserAuthority> authorityList = null;

    // アクセサメソッドは省略
}

サンプルではNamedQueryアノテーション
name属性とquery属性を指定しています。

name属性にはクエリのキーとなる値を
query属性には実行するクエリを指定します。

クエリは通常のJPQLを使用します。
サンプルはJPQLを使用したものです。

JPQLはSQLと同じような構文ですが、
テーブル名・カラム名の指定をJavaのクラス名・プロパティ名で指定できます。

SQLでテーブルを指定する箇所にはクラス名を指定します。
サンプルではFROM句でエイリアスに「u」を指定しています。

カラムの指定はエイリアス.プロパティ名でアクセスできます。
全てのカラムを指定する場合はエイリアスのみでアクセスできます。

パラメータを受け取る場合は「:パラメータ名」で指定できます。
サンプルではfindByUserIdで「:userId」として使用しています。


複数のクエリを指定する場合は
javax.persistence.NamedQueriesアノテーションを使用します。

[クエリの実行]

クエリの実行は一覧ページから行います。

package jp.glory.ui;

import java.util.ArrayList;
import java.util.List;

import javax.faces.bean.ManagedBean;
import javax.faces.bean.RequestScoped;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;
import javax.persistence.Query;
import javax.persistence.TypedQuery;

import jp.glory.persistence.entity.UserData;

@ManagedBean(name = "userListPage")
@RequestScoped
public class UserListPage {

    private final EntityManagerFactory factory = Persistence.createEntityManagerFactory("blog");

    private final EntityManager manager = factory.createEntityManager();

    private String searchUserId = null;

    private List<UserData> userList = null;

    public UserListPage() {

        final Query query = manager.createNamedQuery("findAll");
        userList = query.getResultList();
    }

    public void searchSingleResult() {

        final Query query = manager.createNamedQuery("findByUserId");
        query.setParameter("userId", searchUserId);

        UserData result = (UserData) query.getSingleResult();
        userList = new ArrayList<>();
        userList.add(result);
    }

    public void searchTypedSingleResult() {

        final TypedQuery<UserData> query = manager.createNamedQuery("findByUserId", UserData.class);
        query.setParameter("userId", searchUserId);

        UserData result = query.getSingleResult();
        userList = new ArrayList<>();
        userList.add(result);
    }

    public void searchTypedResultList() {

        final TypedQuery<UserData> query = manager.createNamedQuery("findAll", UserData.class);

        userList = query.getResultList();
    }

    // アクセサメソッドは省略
}    

クエリの実行はEntityManager#createNamedQueryメソッドを使用します。
createNamedQueryメソッドはパラメータを一つ取るタイプと
二つの取るタイプの二つがあります。

パラメータが一つのタイプはクエリ名を指定します。
クエリ名はNamedQueryアノテーションで定義したname属性を指定します。
戻り値の型はjavax.persistence.Queryクラスになります。

パラメータが二つのタイプは
クエリ名と返却されるクラスを指定します。
戻り値の型はjavax.persistence.TypedQueryクラスになります。
TypeQueryクラスはQeuryクラスのサブクラスです。

結果を取得するメソッドは
単一の結果を取得するgetSingleResultメソッドと
複数の結果を取得するgetResultListメソッドがあります。

Queryクラスで結果を取得する場合はObject型、
TypeQueryクラスで結果を取得する場合は生成時に指定した型が返却されます。

Query#getResultListメソッドはListではなくListが返却されます。

実行するクエリのパラメータを指定するには
Query#setParameterメソッドを使用します。
setParameterメソッドにはパラメータ名称と値を指定します。

[ページ]

前回の一覧のページから
ユーザIDを入力するテキストボックスと
各メソッドを実行するボタンを追加しています。

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> 
<html xmlns="http://www.w3.org/1999/xhtml"
    xmlns:f="http://java.sun.com/jsf/core"
    xmlns:ui="http://java.sun.com/jsf/facelets"
    xmlns:h="http://java.sun.com/jsf/html">
    <f:view>
        <h:form id="searchForm">
            <div>
                <h:inputText value="#{userListPage.searchUserId}" />
            </div>
            <div>
                <h:commandButton action="#{userListPage.searchSingleResult()}" value="searchSingleResult" />
                <h:commandButton action="#{userListPage.searchTypedSingleResult()}" value="searchTypedSingleResult" />
                <h:commandButton action="#{userListPage.searchTypedResultList()}" value="searchTypedResultList" />
            </div>
            <h:dataTable value="#{userListPage.userList}" var="user">
                <h:column>
                    <f:facet name="header">
                        ユーザID
                    </f:facet>
                    <h:outputText value="#{user.userId}" />
                </h:column>
                <h:column>
                    <f:facet name="header">
                        ユーザ名
                    </f:facet>
                    <h:outputText value="#{user.name}" />
                </h:column>
                <h:column>
                    <f:facet name="header">
                        最終更新日
                    </f:facet>
                    <h:outputText value="#{user.lastUpdate}" >
                        <f:convertDateTime pattern="yyyy/MM/dd HH:mm:ss.SSS" timeZone="JST"/>
                    </h:outputText>
                </h:column>
                <h:column>
                    <f:facet name="header">
                        権限
                    </f:facet>
                    <ui:repeat value="#{user.authorityList}" var="authority">
                        <h:outputText value="#{authority.authorityType}" />
                    </ui:repeat>
                </h:column>
            </h:dataTable>
        </h:form>
    </f:view>
</html>

【実行】

初期表示はUserListPageクラスのコンストラクタの
中身が実行されています。

それぞれのボタンを押した場合
[searchSingleResult]

[searchTypedSingleResult]

[searchTypedResultList]