※準備工作
DROP TABLE PERSON_TOILET PURGE; DROP TABLE TOILET PURGE; DROP TABLE PERSON PURGE; CREATE TABLE PERSON( PID NUMBER(5), PNAME VARCHAR(20), CONSTRAINT PERSON_PK PRIMARY KEY(PID) ); CREATE TABLE TOILET( TID NUMBER(5), TNAME VARCHAR(20), CONSTRAINT TOILET_PK PRIMARY KEY(TID) ); CREATE TABLE PERSON_TOILET( PT_ID NUMBER(5), INSERT_TIME DATE, OTHER VARCHAR(20), PERSON_ID NUMBER(5), TOILET_ID NUMBER(5), CONSTRAINT PERSON_TOILET_PK PRIMARY KEY(PT_ID), CONSTRAINT FK_PID FOREIGN KEY(PERSON_ID) REFERENCES PERSON(PID) ON DELETE CASCADE, CONSTRAINT FK_TID FOREIGN KEY(TOILET_ID) REFERENCES TOILET(TID) ON DELETE CASCADE ); CREATE SEQUENCE TOILET_SEQ; CREATE SEQUENCE PERSON_SEQ; CREATE SEQUENCE PERSON_TOILET_SEQ;
※XML設定
Person.java
public class Person {
private Integer pid;
private String pname;
private Set<PersonToilet> personToilets = new HashSet<>();
// setter/getter...
}
Toilet.java
public class Toilet {
private Integer tid;
private String tname;
// setter/getter...
}
PersonToilet.java
public class PersonToilet {
private Integer ptId;
private Date insertTime;
private String other;
private Person centerPerson;
private Toilet centerToilet;
// setter/getter...
}
Person.hbm.xml
<class name="vo.Person" table="PERSON"> <id name="pid" type="java.lang.Integer"> <column name="PID" /> <generator class="sequence"> <param name="sequence">PERSON_SEQ</param> </generator> </id> <property name="pname" type="java.lang.String" column="PNAME" /> <set name="personToilets" inverse="true" cascade="save-update" lazy="false"> <key column="PERSON_ID" /> <one-to-many class="vo.PersonToilet" /> </set> </class>
Toilet.hbm.xml
<class name="vo.Toilet" table="TOILET"> <id name="tid" type="java.lang.Integer"> <column name="TID" /> <generator class="sequence"> <param name="sequence">TOILET_SEQ</param> </generator> </id> <property name="tname" type="java.lang.String" column="TNAME" /> </class>
PersonToilet.hbm.xml
<class name="vo.PersonToilet" table="PERSON_TOILET"> <id name="ptId" type="java.lang.Integer"> <column name="PT_ID" /> <generator class="sequence"> <param name="sequence">PERSON_TOILET_SEQ</param> </generator> </id> <property name="insertTime" type="java.util.Date" column="INSERT_TIME" /> <property name="other" type="java.lang.String" column="OTHER" /> <many-to-one name="centerPerson" column="PERSON_ID" not-null="true" cascade="save-update" class="vo.Person" /> <many-to-one name="centerToilet" column="TOILET_ID" lazy="false" not-null="true" cascade="save-update" class="vo.Toilet" /> </class>
新增測試
Session s = HibernateUtil2.getSession();
Transaction tx = s.beginTransaction();
try {
Toilet t1 = new Toilet();
t1.setTname("便所1號");
Toilet t2 = new Toilet();
t2.setTname("便所2號");
Toilet t3 = new Toilet();
t3.setTname("便所3號");
Person p1 = new Person();
p1.setPname("掃便所英俠");
Person p2 = new Person();
p2.setPname("茅坑王");
// 因為掃便所英俠可以上3間廁所,而茅坑王可以上2間廁所,所以要創5個實體
PersonToilet pt1 = new PersonToilet();
PersonToilet pt2 = new PersonToilet();
PersonToilet pt3 = new PersonToilet();
PersonToilet pt4 = new PersonToilet();
PersonToilet pt5 = new PersonToilet();
// -----設定關聯-----
// 掃便所英俠(p1)可以上便所1號(t1)
// 此時的中間表就代替了Toilet的位置,然後自己在去關聯Toilet
p1.getPersonToilets().add(pt1);
pt1.setCenterPerson(p1);
pt1.setCenterToilet(t1);// 就是這時去關聯Toilet
// 掃便所英俠(p1)可以上廁所2號(t2)
p1.getPersonToilets().add(pt2);
pt2.setCenterPerson(p1);
pt2.setCenterToilet(t2);
// 掃便所英俠(p1)可以上廁所3號(t3)
p1.getPersonToilets().add(pt3);
pt3.setCenterPerson(p1);
pt3.setCenterToilet(t3);
// 茅坑王(p2)可以上廁所1號(t1)
p2.getPersonToilets().add(pt4);
pt4.setCenterPerson(p2);
pt4.setCenterToilet(t1);
// 茅坑王(p2)可以上廁所3號(t3)
p2.getPersonToilets().add(pt5);
pt5.setCenterPerson(p2);
pt5.setCenterToilet(t3);
// 關聯表的其他兩個欄位
final Date date = new Date();
pt1.setInsertTime(date);
pt2.setInsertTime(date);
pt3.setInsertTime(date);
pt4.setInsertTime(date);
pt5.setInsertTime(date);
final String str = "insert";
pt1.setOther(str);
pt2.setOther(str);
pt3.setOther(str);
pt4.setOther(str);
pt5.setOther(str);
s.save(pt1);
s.save(pt2);
s.save(pt3);
s.save(pt4);
s.save(pt5);
tx.commit();
} catch (Exception e) {
tx.rollback();
System.err.println("例外錯誤!");
e.printStackTrace();
} finally {
if (s.isOpen()) {
s.close();
}
}
修改測試
Person person = (Person) s.get(Person.class, 182);// 掃便所英俠的ID
person.setPname("吸茅坑大王");
Date date = new Date();
for (PersonToilet pt : person.getPersonToilets()) {
pt.setInsertTime(date);
pt.setOther("update");
Toilet t = pt.getCenterToilet();
t.setTname("廁" + t.getTname().substring(1));
}
s.update(person);
tx.commit();
查詢測試
Person p = (Person) s.get(Person.class, 182);// 掃便所英俠的ID
s.close();
System.out.println(p.getPname());
// 必需在Person.hbm.xml和PersonToilet.hbm.xml的centerToilet設定lazy="false"
for (PersonToilet pt : p.getPersonToilets()) {
System.out.println(pt.getCenterToilet().getTname());
}
刪除測試
Person person = (Person) s.get(Person.class, 182); s.delete(person); tx.commit();
※和多對多雙向FK關聯一樣,我將cascade拿掉或設none才會成功
※Annotation設定
Person.java
@Entity
@Table
public class Person {
@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "XXX")
@SequenceGenerator(name = "XXX", sequenceName = "PERSON_SEQ")
private Integer pid;
private String pname;
@OneToMany(mappedBy = "centerPerson", cascade = CascadeType.ALL)
@LazyCollection(value = LazyCollectionOption.FALSE)
private Set<PersonToilet> personToilets = new HashSet<>();
// setter/getter...
}
Toilet.java
@Entity
@Table
public class Toilet {
@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "XXX")
@SequenceGenerator(name = "XXX", sequenceName = "TOILET_SEQ")
private Integer tid;
// setter/getter...
}
PersonToilet.java
@Entity
@Table(name = "PERSON_TOILET")
public class PersonToilet {
@Id
@Column(name = "PT_ID")
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "XXX")
@SequenceGenerator(name = "XXX", sequenceName = "PERSON_TOILET_SEQ")
private Integer ptId;
@Column(name = "INSERT_TIME")
private Date insertTime;
private String other;
@ManyToOne(cascade = CascadeType.ALL)
@JoinColumn(name = "PERSON_ID", unique = true)
private Person centerPerson;
@ManyToOne(cascade = CascadeType.ALL)
@JoinColumn(name = "TOILET_ID", unique = true)
private Toilet centerToilet;
// setter/getter...
}
※和第三十篇一樣,刪除都是最奇怪的地方
沒有留言:
張貼留言