テーブルの結合
今回はテーブル結合です。
【前提条件】
[環境]
- JDK 1.7.0_07
- Glassfish 3.1.2.2
- PostgreSQL 9.1(JDBC:postgresql-9.1-901.jdbc4.jar)
[その他]
- 前回*1のデータやソースを一部再利用
【概要】
JPA2.0で提供されているアノテーションを使用して、
テーブル結合した結果をエンティティに設定します。
【サンプルコード】
[テーブル]
ユーザ権限を保持する「user_authority」というテーブルを作成します。
CREATE TABLE user_authority ( seq_number serial NOT NULL, auth_user_id character varying(10) NOT NULL, authority_type integer, CONSTRAINT authority_primary_key PRIMARY KEY (seq_number) )
前回作成したuserdataテーブルとuser_authorityテーブルは1:多の関係です。
結合するカラムはuserdata.user_idとuser_authority.auth_user_idです。
seq_numberはserial型となっていますが、
エンティティのクラスではint型で扱います。
[Entity]
user_authorityテーブルに対応するエンティティのクラスを作成します。
package jp.glory.persistence.entity; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.Id; import javax.persistence.Table; @Entity @Table(name = "user_authority") public class UserAuthority { @Id @Column(name = "seq_number") private int seqNumber = 0; @Column(name = "auth_user_id") private String authUserId = null; @Column(name = "authority_type") private int authorityType = 0; // アクセサメソッドは省略 }
UserAuthorityクラスでは特に新しいことはしていません。
前回に作ったUserDataクラスを修正します。
package jp.glory.persistence.entity; 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.OneToMany; import javax.persistence.Table; @Entity @Table(name = "userdata") public class UserData { @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; // アクセサメソッドは省略 }
userdataテーブルからuser_authorityテーブルへは
1:多の関係なので、UserDataクラスからUserAuthorityのリストを持ちます。
1:多の場合はjavax.persistence.OneToManyアノテーションを使用します。
OneToMany以外にOneToOne、ManyToOne、ManyToManyアノテーションがあります。
結合するカラムの設定はjavax.persistence.JoinColumnアノテーションを使用します。
今回はJoinColumnsアノテーションの中には
複数のJoinColumnアノテーションの定義が指定できます。
結合するカラムが一つの場合はJoinColumnアノテーションだけの指定で動きます。
JoinColumnアノテーションではname属性を指定します。
結合するカラム名が同じであればname属性だけの指定で動きます。
サンプルではカラム名が異なるので、
name属性とreferencedColumnName属性を指定しています。
name属性には結合先のテーブルのカラム名を、
referencedColumnName属性には結合元のテーブルのカラム名を指定します。
[persistence.xml]
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="blog" transaction-type="JTA"> <jta-data-source>jdbc/blog</jta-data-source> <class>jp.glory.persistence.entity.UserData</class> <class>jp.glory.persistence.entity.UserAuthority</class> </persistence-unit> </persistence>
[データ取得]
エンティティクラスのデータを取得する
ManagedBeanは前回のUserListPageクラスを再利用します。
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 jp.glory.persistence.entity.UserData; @ManagedBean(name = "userListPage") @RequestScoped public class UserListPage { private List<UserData> userList = null; public UserListPage() { EntityManagerFactory factory = Persistence.createEntityManagerFactory("blog"); EntityManager manager = factory.createEntityManager(); userList = new ArrayList<>(); userList.add(manager.find(UserData.class, "USER-0001")); userList.add(manager.find(UserData.class, "USER-0002")); userList.add(manager.find(UserData.class, "USER-0003")); } // アクセサメソッドは省略 }
[ページ]
ページは今回追加したテーブルの表示処理を追加します。
<?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: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> </f:view> </html>