※準備工作
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 Set toilets = 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一樣
