J2EE と EJB

Relation Mapping
EJB 3.0 コース
第9回
2006年8月6日
1
ここでの目標

複数のテーブルを組み合わせてデータにア
クセスする「Relation Mapping」について理解
する
2
一対一の関係: @OneToOne
3
一対一の関係:
従業員と自宅の住所
EJB_EMPLOYEE 社員テーブル
EMP_ID
VERSION 社員テーブル
L_NAME F_NAME
EJB_EMPLOYEE
309
829
丸山
3
冨岡
稚内
ADDR_ID
不二夫
北海道
MANAGER_ID
829
123
097-0012
日本
P_CODE
COUNTRY
EJB_ADDRESS 住所テーブル
ADDRESS_ID
STREET
CITY PROVINCE
4
住所のIDから住所を得る
EMP_ID
VERSION
L_NAME
F_NAME
ADDR_ID
@Entity
@Table(name="EJB_EMPLOYEE")
public class Employee implements Serializable {
@Id @Column(name="EMP_ID")
:
@OneToOne(cascade=CascadeType.ALL)
@JoinColumn(name="ADDR_ID")
public Address getAddress() { return address; }
}
5
カスケード処理
テーブル間の関連があるときに、処理を伝播さ
せる (カスケードさせる) ことが可能
 テーブル間の関係が親子関係のときに利用
 関連に用いるアノテーション (*To*) とcascade

public enum CascadeType{
ALL, PERSIST, MERGE, REMOVE, REFRESH
};
@OneToMany(cascade=CascadeType.ALL)
public Collection<MailAddress> getMailAddresses(){…}
6
関連インスタンスのロード

関連インスタンスのロードのタイミングを指定できる



即時 (eager) ロード:ソースがロードされると、ターゲットも同時に
ロード
遅延 (lazy) ロード:ターゲットがアクセスされたときにロード
*To*アノテーションとfetchメンバ


OneToOne、 ManyToOneのデフォルトはEAGER
OneToMany、ManyToManyのデフォルトはLAZY
• *ToManyは、ロードするインスタンスが多数になるため
@ManyToOne(fetch=FetchType.EAGER)
public Studen getOwner() {…}
7
社員の住所の取得
public Address getAddressForEmployee(Integer
employeeId) {
Employee employee =
em.find(Employee.class, employeeId);
return employee.getAddress();
}
8
@ManyToOne
9
多対一の関係:
メールアドレスと学生
Student 学生テーブル
ID
Name
309
丸山不二夫
[email protected]
309
[email protected]
309
[email protected]
309
MailAddress メールアドレステーブル
Address
Student ID
10
Student.java
@Entity
@Table(name = "student")
public class Student {
@Id @Column(name="id")
public int getId() {...}
public void setId(int id) {...}
@Column(name="name")
public String getName() {...}
public void setName(String name) {...}
}
11
MailAddress.java
@Entity
@Table(name = "mail_address")
public class MailAddress {
@Id @Column(name="address")
public String getAddress() {...}
public void setAddress(String address) {...}
@ManyToOne(cascade=CascadeType.ALL,
fetch=FetchType.EAGER)
@JoinColumn(name="student_id",
referencedColumnName="id")
public Student getOwner() {...}
public void setOwner(Student owner) {...}
}
12
メールアドレスから学生を得る
[email protected]
309
309
丸山 不二夫
@ManyToOne(fetch=FetchType.EAGER)
@JoinColumn(name=“student_id",
referencedColumnName=“id")
public Student getOwner() {…}
public void setOwner(Student owner) {…}
13
アドレスの情報から持ち主の学生
を得る
@Remote
public interface MailAddressFacade {
void addMailAddress(int student_id, String address);
MailAddress findMailAddressByAddress
(String address);
Student findStudentByAddress(String address);
}
14
アドレスの情報から持ち主の学生
を得る (実装)
public Student findStudentByAddress
(String address) {
MailAddress mailAddress
= (MailAddress)em
.find(MailAddress.class, address);
return mailAddress.getOwner();
}
15
一対多の関係: @OneToMany
16
多対一と一対多
Student 学生テーブル
ID
Name
309
丸山 不二夫
[email protected]
309
[email protected]
309
[email protected]
309
MailAddress メールアドレステーブル
Address
Student
ID
17
多対一と一対多
 メールアドレスから学生
→多対一(ManyToOne)
 学生からメールアドレス
→ 一対多(OneToMany)
18
Student.java
@Entity
@Table(name = "student")
public class Student {
@Id @Column(name="id")
public int getId() {...}
public void setId(int id) {...}
@Column(name="name")
public String getName() {...}
public void setName(String name) {...}
// メールアドレスの情報はどこからとる?
}
19
学生からメールアドレスの一覧を
得るには?
ID
Name
309
丸山 不二夫
Address
[email protected]
[email protected]
Student ID
309
309
@OneToMany(cascade=CascadeType.ALL)
@JoinColumn(name=“student_id",
referencedColumnName=“id")
public Collection<MailAddress>
getMailAddresses() {
return mailAddresses;
}
20
学生の情報からメールアドレス一
覧を得る
@Remote
public interface StudentFacade {
void addStudent(int id, String name);
Student findStudentById(int id);
Collection<MailAddress>
findMailAddressesById(int id);
}
21
学生の情報からメールアドレス一
覧を得る (実装)
public Collection<MailAddress>
findMailAddressesById(int id) {
Student student =
(Student)em.find( Student.class, id );
return student.getMailAddresses();
}
22
多対多の関係: @ManyToMany
23
多対多の例) 学生と履修科目
Student 学生テーブル
Course 科目テーブル
ID
ID
Name
301
小泉純子
1
Course
Name
Java I
Teacher Name
302
安倍晋太
2
Java II
植田龍男
303
武部務
3
Java III
佐賀孝博
304
麻生次郎
4
J2EE I
安藤友晴
植田龍男
24
多対多の場合には中間テーブル
が必須
Association Table
Student ID
Course ID
301
1
301
2
302
2
302
3
302
4
303
1
303
3
25
Association Table を介した対応
Student 学生テーブル
ID
Name
joinColumns=
@JoinColumn(name=“Student_ID",
referencedColumnName="ID"),
Association Table
Student ID
Course ID
inverseJoinColumns=
@JoinColumn(name=“Course_ID",
referencedColumnName="ID")
Course 科目テーブル
ID
Course
Name
Teacher Name
26
ManyToManyの記述の例
@ManyToMany(cascade=CascadeType.ALL)
@AssociationTable(
table=@Table(name=“course_regist"),
joinColumns=@JoinColumn(
name=“Student_ID",
referencedColumnName="ID"),
inverseJoinColumns=@JoinColumn(
name=“Course_ID",
referencedColumnName="ID")
)
public Collection<Course> getCourses() {…}
27
学生から履修科目の一覧を取得
public Collection<Course> getCourses() {
return courses;
}
public void setCourses
(Collection<Course> courses) {
this.courses = courses;
}
28