※準備工作
DROP TABLE STUDENT PURGE; DROP TABLE CLAZZ PURGE; CREATE TABLE CLAZZ( CID NUMBER(5), CNAME VARCHAR(15), CONSTRAINT CLAZZ_PK PRIMARY KEY(CID) ); CREATE TABLE STUDENT( SID NUMBER(5), SNAME VARCHAR(15), CLAZZ_ID NUMBER(5), CONSTRAINT STUDENT_PK PRIMARY KEY(SID), CONSTRAINT STUDENT_FK FOREIGN KEY(CLAZZ_ID) REFERENCES CLAZZ(CID) ON DELETE CASCADE ); CREATE SEQUENCE CLAZZ_SEQ; CREATE SEQUENCE STUDENT_SEQ;
※和一對多雙向FK關聯一模一樣
※XML設定
Clazz.hbm.xml
<class name="vo.Clazz" table="CLAZZ"> <id name="cid" type="java.lang.Integer"> <column name="CID" /> <generator class="sequence"> <param name="sequence">CLAZZ_SEQ</param> </generator> </id> <property name="cname" type="java.lang.String"> <column name="CNAME" /> </property> <set name="setStudent" inverse="false" cascade="all" lazy="false" fetch="join"> <key column="CLAZZ_ID" not-null="true" /> <one-to-many class="vo.Student" /> </set> </class>
※inverse一定要false(因為Student不知道Clazz存在),要自己維護,所以會產生多餘的SQL,可能就是因為這樣,所以官方不推薦使用
Student.hbm.xml
<class name="vo.Student" table="STUDENT"> <id name="sid" type="java.lang.Integer"> <column name="SID" /> <generator class="sequence"> <param name="sequence">STUDENT_SEQ</param> </generator> </id> <property name="sname" type="string"> <column name="SNAME" /> </property> </class>
Clazz.java
public class Clazz { private Integer cid; private String cname; private Set<Student> setStudent = new HashSet<>(); // setter/getter... }
Student.java
public class Student { private Integer sid; private String sname; // setter/getter... }
新增測試
Clazz clazz = new Clazz(); clazz.setCname("1年1班"); for (int i = 1; i <= 2; i++) { Student stu = new Student(); stu.setSname("小" + i + "號"); clazz.getSetStudent().add(stu); } s.save(clazz); tx.commit();
※如果inverse="true",關聯的字段(CLAZZ_ID)是null,不會報錯,因為多方Student不知道一方Clazz的存在,我的<key> 有設not null,但也沒報錯誤訊息; 而<set>沒有not null 選項
修改測試
Clazz clazz = new Clazz(); clazz.setCid(51); clazz.setCname("1年2班"); String sql = " SELECT * FROM STUDENT WHERE CLAZZ_ID = :id "; SQLQuery query = s.createSQLQuery(sql) .addScalar("SID", StandardBasicTypes.INTEGER) .addScalar("SNAME", StandardBasicTypes.STRING); query.setParameter("id", clazz.getCid()); @SuppressWarnings("unchecked") List<Object> list = query.list(); for (int i = 0; i < list.size(); i++) { Object[] o = (Object[]) list.get(i); Student stu = new Student(); stu.setSid((Integer) o[0]); stu.setSname("小" + i); clazz.getSetStudent().add(stu); } s.update(clazz); tx.commit();
查詢一方(Clazz)測試
Clazz clazz = (Clazz) s.get(Clazz.class, 51); s.close(); System.out.println(clazz.getCname()); for (Student stu : clazz.getSetStudent()) { System.out.println(stu.getSname()); }
※預設是select,lazy="false"才能查到Student的表
刪除一方(Clazz)測試
Clazz clazz = (Clazz) s.get(Clazz.class, 51); s.delete(clazz); tx.commit();
※Annotation設定
Clazz.java
@Entity @Table public class Clazz { @Id @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "XXX") @SequenceGenerator(name = "XXX", sequenceName = "CLAZZ_SEQ") private Integer cid; @Column private String cname; @OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY) @JoinColumn(name = "CLAZZ_ID") @LazyCollection(value = LazyCollectionOption.FALSE) private SetsetStudent = new HashSet<>(); // setter/getter... }
Student.java
@Entity @Table public class Student { @Id @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "OOO") @SequenceGenerator(name = "OOO", sequenceName = "STUDENT_SEQ") private Integer sid; @Column private String sname; // setter/getter... }
※測試的結果和XML設定一樣,包括查詢的預設值也是select(因為之前的X對X,Annotation的設定預設幾乎都是join)
沒有留言:
張貼留言