※準備工作
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... }
※和第三十篇一樣,刪除都是最奇怪的地方
沒有留言:
張貼留言