※準備工作
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( PERSON_ID NUMBER(5), TOILET_ID NUMBER(5), 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;
※和二十九篇完全一樣
※XML設定
hibernate.cfg.xml
<session-factory> <property name="hibernate.connection.driver_class">oracle.jdbc.driver.OracleDriver</property> <property name="hibernate.connection.url">jdbc:oracle:thin:@127.0.0.1:1521:orcl</property> <property name="hibernate.connection.username">username</property> <property name="hibernate.connection.password">password</property> <property name="hibernate.dialect">org.hibernate.dialect.OracleDialect</property> <property name="hibernate.show_sql">true</property> <property name="hibernate.format_sql">true</property> <!-- <property name="hibernate.use_sql_comments">true</property> --> <!-- <property name="hibernate.connection.autocommit">true</property> --> <!-- <property name="hibernate.hbm2ddl.auto">update</property> --> <property name="hibernate.transaction.factory_class">org.hibernate.transaction.JDBCTransactionFactory</property> <property name="hibernate.current_session_context_class">thread</property> <!-- <property name="hibernate.cache.use_second_level_cache">true</property> --> <!-- <property name="hibernate.cache.provider_class">org.hibernate.cache.EhCacheProvider</property> --> <!-- <property name="hibernate.QueryCacheEnabled">true</property> --> <!-- <property name="hibernate.cache.use_query_cache">true</property> --> <mapping resource="vo/Toilet.hbm.xml" /> <mapping resource="vo/Person.hbm.xml" /> <!-- <class-cache usage="read-only" class="vo.Emp"/> --> </session-factory>
Person.java
public class Person { private Integer pid; private String pname; private Set<Toilet> toilets = new HashSet<>(); // setter/getter... }
Toilet.java
public class Toilet { private Integer tid; private String tname; // setter/getter... }
※因為是單向,所以Toilet不用關聯Person
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="toilets" table="PERSON_TOILET" cascade="delete" lazy="false"> <key column="PERSON_ID" /> <many-to-many column="TOILET_ID" class="vo.Toilet" /> </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>
新增測試
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("茅坑王"); // 掃便所英俠可以上廁所1~3號 p1.getToilets().add(t1); p1.getToilets().add(t2); p1.getToilets().add(t3); // 茅坑俠可以上廁所1、3號 p2.getToilets().add(t1); p2.getToilets().add(t3); s.save(p1); s.save(p2); 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, 161);// 掃便所英俠的ID person.setPname("吸茅坑大王"); for (Toilet toilet : person.getToilets()) { toilet.setTname("廁" + toilet.getTname().substring(1)); } s.update(person); tx.commit();
查詢測試
Person p = (Person) s.get(Person.class, 161);// 掃便所英俠的ID s.close(); System.out.println(p.getPname()); // 必需在Person.hbm.xml設定lazy="false" for (Toilet toi : p.getToilets()) { System.out.println(toi.getTname()); }
刪除測試
Person pp = (Person) s.get(Person.class, 167); s.delete(pp); tx.commit();// 關聯表不會刪
※cascade不要設delete相關,怪怪的
※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; @ManyToMany @LazyCollection(value = LazyCollectionOption.FALSE) @JoinTable(name = "PERSON_TOILET", joinColumns = { @JoinColumn(name = "PERSON_ID", updatable = false) }, inverseJoinColumns = { @JoinColumn(name = "TOILET_ID", updatable = false) }) private Settoilets = 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; private String tname; // setter/getter... }
※刪除的時候,我將cascade整個拿掉,才和XML一樣