Hibernate Annotation with Class...
Transcript of Hibernate Annotation with Class...
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();
}