※準備工作
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 Set setStudent = 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)
沒有留言:
張貼留言