Hibernate Annotation with Class Relationshipคาสั่งดา้นบนชื่อแอททริบิวต์คือ id แต่หลงัจาก Hibernate...

Post on 22-May-2020

8 Views

Category:

Documents

0 Downloads

Preview:

Click to see full reader

Transcript

Hibernate Annotationwith

Class Relationship

Entity RelationshipsUnidirectional one-to-one

ex. Person 1--->1 HeartBidirectional one-to-one

ex. Person 1<--->1 PassportUnidirectional one-to-many

ex. Person 1 --->* PhonesBidirectional one-to-many

aka. Bidirectional many-to-oneex. Person 1<--->* Childs

Unidirectional many-to-oneex. Person *--->1 Company

Unidirectional many-to-manyex. Person *--->* Address

Bidirectional many-to-manyex. Person *<--->* Orders

One to One Uni Direction

เปนความสมพนธซงในทางปฏบตเปนการก าหนดออบเจกตของคลาสหนง ๆ ใหอยในรปของแอททรบวตของอกคลาสหนงทมความสมพนธกน สามารถเรยกใชงานไดจากทก ๆ เมธอดภายในคลาสตามตองการ

Association Relationship

คลาส Person ประกอบไปดวยแอททรบวตในรปตวแปรPassport ออบเจกตสญลกษณลกศรแสดงถงความสมพนธแบบทศทางเดยว ดงนนคลาส Passport ไมทราบขอมลเกยวกบคลาส Person แตอยางใดดงนนคลาส dependent (Person) มการประกาศตวแปร Passport ออบเจกตไวภายในคลาส scope ดงน

public class Person {

private Passport passport;

.........;

public Passport getPassport() {

return passport;

}

}

public class Passport {

private long id;

.........;

public long getId() {

return id;

}

}

Passportpublic class Passport {

private String passport_no;

private Date issueDate;

private String province;

private String country;

public String getPassportNo() { return passport_no; }

public String getCountry() { return country; }

public Passport(){ }

public Passport(String passportNo, Date issueDate, String province, String country) {

this.passport_no = passportNo;

this.issueDate = issueDate;

this.province = province;

this.country = country;

}

}

Personpublic class Person {

private long id;

private String personName;

private char sex;

private Date birthDate;

private Passport passport;

public Person(){ }

public Person(String personName, char sex, Date birthDate) {

this.personName = personName;

this.sex = sex;

this.birthDate = birthDate;

}

public String getPersonName() { return personName; }

public Passport getPassport() {

return passport;

}

public void setPassport(Passport passport) {

this.passport = passport;

}

}

One to One Uni Direction : FK

ความสมพนธแบบหนงตอหนงแบบทศทางเดยวสามารถน าเสนอไดโดยการก าหนดคอลมนคยนอก (Foreign Key) ลงในตารางหนงเพอใชในการอางองไปยงคอลมนทเปนคยหลกของอกตารางหนงเพอสรางความสมพนธทเกดขนระหวางสองตาราง

One to One Uni Direction : Annotation

สญลกษณ @OneToOne ใชระบความสมพนธแบบหนงตอหนงสญลกษณ @OneToOne โดยปกตมกใชรวมกบพารามเตอร cascade เพอใหการบนทกขอมลออบเจกตตอเนอง เชน บนทก Person ออบเจกตเดยวแตสงผลตอเนองไปยงการบนทก Passport ออบเจกตโดยอตโนมตเนองจากเปนแบบทศทางเดยว @OneToOne จะถกก าหนดไวทเอนตททเปน Owner เสมอ ในกรณนไดแก Person

@OneToOne(cascade = CascadeType.ALL)

@JoinColumn@ OneToOne(cascade = CascadeType.ALL)

@JoinColumn(name=“passport_no")

private Passport passport;

สญลกษณ @JoinColumn ประกอบไปดวยพารามเตอรทใชก าหนดชอคอลมนทตองการอางอง หรอ คอลมนทเปนคยนอก (Foreign Key ) นนเองในกรณทไมมการประกาศ @JoinColumn หรอมแตไมมการระบ name ไวทowner side คา defaults จะถกเรยกใชโดยอตโนมต โดย join คอลมนทเกดขนจะถกสรางขนในตาราง owner โดยใชชอรวมกนระหวางชอความสมพนธของเอนตททมความสมพนธกบ owner side, _ (underscore) และชอคอลมนทเปนคยหลก เชน passport_passprt_no

One to One Uni Direction : FK

@Entity

@Table(name = "PERSON")

public class Person {

....;

@OneToOne(cascade = CascadeType.ALL)

@JoinColumn(name = "passport_no")

private Passport passport;

....;

}

@Entity

@Table (name = "PASSPORT")

public class Passport {

.....;

}

สราง FK ชอ passport_noเพอลงคไปท Passport

เพอสรางความสมพนธแบบ onetoone

One-To-One Mapping (Annotations)

public class Person {

int id;...

Passport passport;}

@Entity

@OneToOne

@Id

Passport

…no

Person

passport_noID …

@JoinColumn(name=“passport_no")

@Entity

public class Passport {

int no;

.....;

}

สญลกษณ @Column

สญลกษณ @Column ใชส าหรบระบชอและรายละเอยดตาง ๆ ของคอลมนทถกแปลงมาจากแอททรบวตทก าหนดไวในคลาส ตวอยางเชน

@Column(name = “person_id")

private int id;

ค าสงดานบนชอแอททรบวตคอ id แตหลงจาก Hibernate แปลงใหอยในรปของตารางแลว คอลมนดงกลาวจะถกก าหนดชอ person_id แทนสวนในกรณทมการก าหนดแอทรบวตในรปออบเจกตจากคลาส Date หรอ Calendar จ าเปนตองระบสญลกษณ @Temporal เพอแปลงคาระหวาง time-stamp และ java util date เพอใหแสดงผลไดอยางถกตอง

Passport@Entity

@Table (name = "PASSPORT")

public class Passport {

@Id

@Column(name = "passport_no")

private String passport_no;

@Temporal(TemporalType.DATE)

@Column(name = "issue_date")

private Date issueDate;

@Column(name = "place_of_birth")

private String province;

@Column(name = "country")

private String country;

public String getPassportNo() { return passport_no; }

public String getCountry() { return country;}

public Passport(){ }

public Passport(String passportNo, Date issueDate, String province, String country) {

this.passport_no = passportNo;

this.issueDate = issueDate;

this.province = province;

this.country = country;

}

}

Person@Entity

@Table(name = "PERSON")

public class Person {

@Id

@GeneratedValue

@Column(name = "person_id") private long id;

@Column(name = "person_name") private String personName;

@Column(name="sex") private char sex;

@Temporal(TemporalType.DATE)

@Column(name = "birthDate") private Date birthDate;

public Person(){ }

public Person(String personName, char sex, Date birthDate) {

this.personName = personName;

this.sex = sex;

this.birthDate = birthDate;

}

@OneToOne(cascade = CascadeType.ALL)

@JoinColumn(name = "passport_no")

private Passport passport;

public Passport getPassport() {

return passport;

}

hibernate.cfg.xml<session-factory>

<!-- Database connection settings -->

<property name="connection.driver_class">com.mysql.jdbc.Driver</property>

<property name="connection.url">jdbc:mysql://localhost:3306/Person Passport</property>

<property name="connection.username">root</property>

<property name="connection.password">1234</property>

<!-- JDBC connection pool (use the built-in) -->

<property name="connection.pool_size">1</property>

<!-- Echo all executed SQL to stdout -->

<property name="show_sql">true</property>

<!-- Drop and re-create the database schema on startup -->

<property name="hbm2ddl.auto">create</property>

<!-- Mention here all the model classes along with their package name -->

<mapping class="com.itsci.hibernate.Person"/>

<mapping class="com.itsci.hibernate.Passport"/>

</session-factory>

Run Program

Session session = sessionFactory.openSession();

Transaction tx = null;

Person person = new Person("Somchai Jaidee",'M', convertDate("13-08-2540"));

Passport passport = new Passport( 1357473, convertDate("26-01-2557"),

"Chiangmai", "Thailand");

try{

tx = session.beginTransaction();

person.setPassport(passport);

Long id = (Long) session.save(person);

Person per = (Person) session.get(Person.class, id);

System.out.println("Person's Name: " + per.getPersonName());

Passport pass = per.getPassport();

System.out.println("Passport's Number: " + pass.getPassportNo());

System.out.println("Country: " + pass.getCountry());

tx.commit();

}catch (HibernateException e) {

if (tx!=null) tx.rollback();

e.printStackTrace();

}

setPassport ลงใน Person ออบเจกตSave เฉพาะ Person

One to One Uni Direction : FK

Output

Hibernate: insert into PASSPORT (country, issue_date, passport_no,

place_of_birth) values (?, ?, ?, ?)

Hibernate: insert into PERSON (birthDate, passport_id, person_name, sex) values

(?, ?, ?, ?)

Person's Name: Somchai Jaidee

Passport's Number: 1357473

Country: Thailand

@JoinColumn without name

ในกรณทไมมการประกาศ @JoinColumn หรอม @JoinColumn แตไมมการระบ name ไวท owner side คา defaults จะถกเรยกใชโดยอตโนมตโดย join คอลมนทเกดขนจะถกสรางขนในตาราง owner โดยใชชอรวมกนระหวางชอความสมพนธของเอนตททมความสมพนธกบ owner side, _ (underscore) และชอคอลมนทเปนคยหลก เชน passport_passport_no

Bidirectional One to One

นยามความสมพนธแบบสองทศทาง (bidirectional) เปนแนวคดทใชในการประยกตความสมพนธระหวางสองออบเจกตทสามารถเขาถงไดทงสองดานความสมพนธทเกดขนขนระหวางคลาส Person และ Passport ทสามารถเขาถง Person ออบเจกตไดจาก Passport ออบเจกต และ Passport ออบเจกตจาก Peson ออบเจกต

Bidirectional One to One

โดยปกตแลวการโปรแกรมเชงวตถทมความสมพนธแบบทศทางเดยวสามารถท างานไดอยางถกตองดงนนในทางปฏบตการโปรแกรมส าหรบความสมพนธแบบสองทศทางสามารถพบไดคอนขางยากแตอยางไรกตามดวยการท างานของ Hibernate เมออยในระดบของฐานขอมล การเขาถงขอมลภายในสามารถท าไดทงสองดานดงนนความสมพนธแบบสองทศทางจงเปนสงทจ าเปนส าหรบการท างานรวมกบ Hibernate

Bidirectional : One to One

@Entity

@Table(name = "PERSON")

public class Person {

....;

@OneToOne .....

@JoinColumn(name = "passport_id")

private Passport passport;

....;

}

@Entity

@Table (name =

"PASSPORT")

public class Passport {

.....;

@OneToOne .......

private Person person;

}

ความสมพนธแบบสองทศทาง ผใชสามารถเขาถงออบเจกตไดทงสองดาน ทงจาก Person => Passport และ Passport => Personดงนนใน Hibernate จงจ าเปนตองก าหนดสญลกษณแสดงความสมพนธ @OneToOne ไวทงสองดาน

แนวคดเกยวกบ Owner และ Inverse side

เปนแนวคดทมาจากความแตกตางระหวางความสมพนธระหวางคลาสทสามารถมไดทงแบบทศทางเดยวและสองทศทาง สวนในระบบฐานขอมลจะมความสมพนธไดแบบทศทางเดยวเทานนเพอใหเกดความสอดคลองกนในระดบของตารางฐานขอมลจงจ าเปนตองใชแนวคดดงกลาวดานทมคยนอก (foreign key) ในตารางจะถกเรยกวาดานทเปน Ownerและดานตรงกนขามจะเปนดาน Inverse เสมอ ความสมพนธแบบสองทศทางจะประกอบไปดวยดานทเปน Owner และ Inverse ขณะทแบบทศทางเดยวจะมเฉพาะดานทเปน Owner เทานนดานทเปน Owner รบผดชอบเกยวกบ Add, Update และ Delete ทสงผลตอเนองไปยงดานทเปน Inverse โดยอตโนมต

Owning Side Concepts

ในกรณทความสมพนธระหวาง Person และ Passport เปนแบบสองทศทาง ซงสามารถเขาถงไดทงสองทาง ดานทเปน inverse ของความสมพนธจะตองถกก าหนดสญลกษ @OneToOne พรอมระบค าสง mappedBy ไวเสมอค าสง mappedBy จะใชอางองไปยงฟลดของ owning side ของความสมพนธ (Person) ทถกระบไวดวย @JoinColumn เสมอ

Bidirectional One-to-One@Entity

@Table(name = "PERSON")

public class Person {

....;

@OneToOne (cascade = CascadeType.ALL)

@JoinColumn(name = "passport_no")

private Passport passport;

....;

}

@Entity

@Table (name = "PASSPORT")

public class Passport {

.....;

@OneToOne(cascade = CascadeType.ALL ,mappedBy="passport“)

private Person person;

}

Bidirectional One To One Mapping

public class Person {

int id;

@JoinColumn(name=“passport_no”Passport passport;

}

public class Passport {

int id;

Person person;}

PassportID …

Personpassport_noID …

@Entity

@OneToOne

@Id

@Entity

@Id

@OneToOne(mappedBy=“passport”

Bidirectional One-to-One

เพอใหเปนไปตามความสมพนธแบบสองทศทาง จ าเปนตองมการตดตง Person และ Passport ออบเจกตเขาดวยกนทงสองดานดงน

person.setPassport(passport);passport.setPerson(person)

ความแตกตางระหวางความสมพนธแบบทศทางเดยวและสองทศทางคอวธการบนทกขอมลออบเจกตลงในตารางฐานขอมลแบบทศทางเดยวการบนทกขอมลจะเกดขนท Person ออบเจกตเทานนแบบสองทศทางการบนทกขอมลออบเจกตสามารถท าไดทงสองทศทาง

Output

Hibernate: insert into PASSPORT (country, issue_date, passport_no,

place_of_birth) values (?, ?, ?, ?)

Hibernate: insert into PERSON (birthDate, passport_id, person_name, sex)

values (?, ?, ?, ?)

Person's Name: Somchai JaiDee

Passport's Number: 1357473

Country: Thailand

One-To-One Shared Primary Key

เปนความสมพนธแบบนในระดบของตารางฐานขอมลคอการใชคยหลกของตารางรวมกนวธการนคยหลกของเอนตท product จะถกตงสมมตฐานวาเปนคาคยหลกเดยวกบเอนตท product_detail ดงการน าเสนอในแบบจ าลองความสมพนธตอไปน

@PrimaryKeyJoinColumn

@PrimaryKeyJoinColumn ใชส าหรบการสรางความสมพนธจากตารางหนงไปยงยงตารางอน โดยปกตแลวการใชสญลกษณดงกลาวจะไมมการสรางคอลมนเพมเตมแตอยางใด ทงนเนองจากทงสองเอนตทมการใชคยหลกเดยวกน คยหลกในตาราง Product ถกใชเปนคาคยหลกในตาราง ProductDetail ตามไปดวย สญลกษณ @Cascade ทมคา CascadeType.ALL เพอการบนทก อพเดทหรอลบขอมลออกจากตาราง Product จะสงผลตอเนองไปยงตาราง ProductDetail โดยอตโนมต

One-To-One Shared Primary Key : UNI

@Entity

@Table(name = "PRODUCT")

public class Product {

@Id

@GeneratedValue

@Column(name = "PRODUCT_ID")

private long productId;

@OneToOne(cascade=CascadeType.ALL)

@PrimaryKeyJoinColumn

private ProductDetail productDetail;

}@Entity

@Table(name = "PRODUCT_DETAIL")

public class ProductDetail {

@Id

@GeneratedValue

private long productId;

public ProductDetail() { }

}

สญลกษณ @Column

สญลกษณ @Column ใชส าหรบระบชอและรายละเอยดตาง ๆ ของคอลมนทถกแปลงมาจากแอททรบวตทก าหนดไวในคลาส ผใชสามารถใชสญลกษณดงกลาวรวมกบการระบคาตาง ๆ ดงตอไปน

name ใชระบชอคอลมนทตองการในตารางฐานขอมลlength ใชก าหนดขนาดของคอลมนทใชส าหรบ map คา String หนง ๆnullable ใชระบคา NOT NULL เมอมการสราง schema เชน nullable = false หมายถงคอลมนทถกระบไมสามารถมคาเปน null ไดunique ใชก าหนดคาในคอลมนทถกระบตองมคาไมซ ากน

One-To-One SPKey : Uni (run)

Session session = sessionFactory.openSession();

Product pro = new Product("Polo", 1412.00);

ProductDetail productDetail = new ProductDetail(1001,"Shirt" , "Sahapat");

Transaction tx = null;

try{

tx = session.beginTransaction();

pro.setProductDetail(productDetail);

session.save(pro);

tx.commit();

}catch (HibernateException e) {

if (tx!=null) tx.rollback();

e.printStackTrace();

}finally {

session.close();

}

One-To-One Shared Primary Key : Bi

@Entity

@Table(name = "PRODUCT")

public class Product {

@Id

@GeneratedValue

@Column(name = "PRODUCT_ID")

private long productId;

@OneToOne(cascade=CascadeType.ALL)

@PrimaryKeyJoinColumn

private ProductDetail productDetail;

}

@Entity

@Table(name = "PRODUCT_DETAIL")

public class ProductDetail {

@Id

private long productId;

public ProductDetail() { }

@OneToOne(mappedBy = "productDetail")

private Product product;

}

Same Primary Keyกรณทตองการให Hibernate สราง id ของเอนตท ProductDetail ใหมคาเดยวกบ Primary Key ในเอนตท Product สามารถใชค าสงดงน

@Id

@GeneratedValue (generator = "newgen")

@GenericGenerator(strategy = "foreign", name="newgen",

parameters = @Parameter(name = "property", value="product"))

private long productId;

พารามเตอรแรกก าหนดชอง Generator ทตองการไดแก "newGen“พารามเตอรถดมาก าหนดชนดของ strategy ทใชในการสรางคา ID ซงกรณนเปนสรางคาคยนอก ดงนนเลอกใช Generator ทเรยกวา “foreign” สวนสดทายก าหนด property ชอของตารางทสมพนธกน ไดแก product

One To Many Relationship

เปนความสมพนธทพบไดบอย ๆ ในการโปรแกรมเชงวตถ โดยคลาสหนงมความสมพนธกบคลาสอน ๆ ในรปของหนงตอกลมในระดบการโปรแกรมเปนการประกาศตวแปรแอททรบวตในรปกลมของออบเจกตจากคลาสอน ๆ ไวภายในอกคลาสหนงทมความสมพนธกน

One Company : Many Employees

public class Employee {

private Long id;

private String employeeName;

public Employee(String employeeName) {

this.employeeName = employeeName;

}

public String getEmployeeName() {

return employeeName;

}

public void setEmployeeName(String

employeeName) {

this.employeeName = employeeName;

}

}

public class Company {

private Long id;

private String companyName;

public Company(String companyName) {

this.companyName = companyName;

}

private Set<Employee> employeeSet;

public Set<Employee> getEmployees() {

return employeeSet;

}

public void setEmployees(Set<Employee>

employees) {

this.employeeSet = employees;

}

}

}

One To Many Uni

การสรางความสมพนธแบบ One To Many แบบทศทางเดยวเรยกใชสญลกษณ @OneToMany เพอก าหนดความสมพนธแบบหนงตอกลมเรยกใชสญลกษณ @JoinColumn เพอสรางคยนอกเพอใชในการอางองไปยงตารางทมความสมพนธกนเรยกใชสญลกษณ @Cascade (cascade = CascadeType.All) ลงทางดานคลาสทเปน Owner เพอสงผลตอเนองไปยงการบนทกขอมลรวมกบ คลาสทมความสมพนธกนโดยอตโนมต

One To Many Uni : Structure

@Entity

@Table(name = "COMPANY")

public class Company {

.....;

@OneToMany (cascade=CascadeType.ALL)

@JoinColumn (name = "company_id")

private Set<Employee> employees = new HashSet<Employee>();

// setter & getter;

}

@Entity

@Table (name = "EMPLOYEE")

public class Employee {

....;

}

Run : One To Many Uni

Session session = sessionFactory.openSession();

Transaction tx = null;

Company company = new Company("IndyThaiTester");

Employee employee1 = new Employee("Somchai");

Employee employee2 = new Employee("Somsri");

company.getEmployees().add(employee1);

company.getEmployees().add(employee2);

try{

tx = session.beginTransaction();

session.save(company);

tx.commit();

}catch (HibernateException e) {

if (tx!=null) tx.rollback();

e.printStackTrace();

}

finally {

session.close();

}

Output

Hibernate: insert into COMPANY (company_name) values (?)

Hibernate: insert into EMPLOYEE (employee_name) values (?)

Hibernate: insert into EMPLOYEE (employee_name) values (?)

Hibernate: update EMPLOYEE set company_id=? where employee_id=?

Hibernate: update EMPLOYEE set company_id=? where employee_id=?

@OneToMany และ @ManyToOne

ความสมพนธแบบหนงตอกลมอาจมองไดเปนสองแบบไดแกหนงตอกลม ใช @OneToManyกลมตอหนง ใช @ManyToOne

สาเหตทตองใชสญลกษณทแตกตางกนเนองมาความจ าเปนทตองแจงให Hibernate ทราบวาคลาสดานใดท าหนาทเปนเจาของความสมพนธและคลาสดานใดอยตรงขามกบเจาของความสมพนธดงกลาว

Many To One Uni : Structure

@Entity

@Table(name = "COMPANY")

public class Company {

.....;

}

@Entity

@Table (name = "EMPLOYEE")

public class Employee {

....;

@ManyToOne (cascade=CascadeType.ALL)

@JoinColumn (name = "company_id")

private Company company;

}

สวนทเปนกลมออบเจกตจากคลาส Set จะถกตดออกไป

เพมตวแปรดานทเปน one มาแทนท

Run : Many To One UniSession session = sessionFactory.openSession();

Transaction tx = null;

Company company = new Company("IndyThaiTester");

Employee employee1 = new Employee("Somchai");

Employee employee2 = new Employee("Somsri");

try{

tx = session.beginTransaction();

employee1.setCompany(company);

employee2.setCompany(company);

session.save(employee1);

session.save(employee2);

tx.commit();

}catch (HibernateException e) {

if (tx!=null) tx.rollback();

e.printStackTrace();

}

finally {

session.close();

}

Bidirectional One To Many

โดยปกตความสมพนธทเกดขนระหวางคลาสทเกดขนเมอคลาสหนงมการอางอางถงคลาสอกกลมหนง ซงในทางปฏบตสามารถเขาถงไดทงสองทางความสมพนธแบบหนงตอกลมสองทศทางสามารถน าเสนอไดดงคลาสไดอาแกรมตอไปน

Owning Side

ความสมพนธแบบหนงตอกลมเกดขนระหวางคลาส Company และคลาส Employees เนองจากเปนความสมพนธแบบสองทศทาง ตองระบทง @OneToMany และ @ManyToOneซงดานทเปน ManyToOne ถอเปน Owner ขณะทดานทเปน OneToMany ถอเปน inverse เสมอดงนนตองระบค าสง mappedBy="company" ไวในคลาส Company ทเปน Inverse เพออางถงตวแปรออบเจกตทถกประกาศไวในคลาส Employee ซงท าหนาทเปน Owner ของความสมพนธเสมอ

Bidirectional One To Many : Structure

@Entity

@Table(name = "COMPANY")

public class Company {

.....;

@OneToMany (cascade=CascadeType.ALL, mappedBy = "company")

private Set<Employee> employeeSet = new HashSet<Employee>();

.....;

}

@Entity

@Table (name = "EMPLOYEE")

public class Employee {

....;

@ManyToOne(cascade=CascadeType.ALL)

@JoinColumn (name = "company_id")

private Company company;

}

Run : Bidirectional One To ManySession session = sessionFactory.openSession();

Transaction tx = null;

Company company = new Company("IndyThaiTester");

Employee employee1 = new Employee("Somchai Jaidee");

Employee employee2 = new Employee("Somsri Jaipak");

company.getEmployees().add(employee1);

company.getEmployees().add(employee2);

employee1.setCompany(company);

employee2.setCompany(company);

try{

tx = session.beginTransaction();

session.save(employee1);

session.save(employee2);

tx.commit();

}catch (HibernateException e) {

if (tx!=null) tx.rollback();

e.printStackTrace();

}

top related