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