2015年12月20日 星期日

多對一單向FK關聯 (Hibernate3.x 二十八)

※準備工作

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>
</class>

※因為是多對一單向,這裡是一,所以不用特別設定

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>
    
    <many-to-one name="clazz" column="CLAZZ_ID" not-null="true" lazy="false" cascade="all"/>
</class>

※因為是多對一單向,這裡是多,所以要設定

Clazz.java

public class Clazz {
    private Integer cid;
    private String cname;
    // setter/getter...
}

※因為是多對一單向,這裡是一,所以不用特別設定

Student.java

public class Student {
    private Integer sid;
    private String sname;
    private Clazz clazz;
    // setter/getter...
}

※因為是多對一單向,這裡是多,所以要設定

新增測試

Clazz clazz = new Clazz();
clazz.setCname("一年壬班");
    
for (int i = 1; i <= 2; i++) {
    Student stu = new Student();
    stu.setSname("小" + i + "班");
    stu.setClazz(clazz);
    s.save(stu);
}
tx.commit();

修改測試

Clazz clazz = new Clazz();
clazz.setCid(47);
clazz.setCname("三年丙班");
    
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 + "班");
    stu.setClazz(clazz);
    s.update(stu);
}
tx.commit();

查詢多方(Student)測試

Student stu = (Student) s.get(Student.class, 90);
s.close();
System.out.println(stu.getSname());
System.out.println(stu.getClazz().getCname());

※還是要設定lazy="false",否則Clazz(一方)會查不到

※預設fetch是select


刪除多方(Student)測試

Student stu = (Student) s.get(Student.class, 90);
s.delete(stu);
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;
    
    // 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;
    
    @ManyToOne(cascade = CascadeType.ALL, fetch = FetchType.LAZY)
    @JoinColumn(name = "CLAZZ_ID")
    @LazyToOne(value = LazyToOneOption.FALSE)
    private Clazz clazz;
    
    // setter/getter...
}

※測試的結果和XML設定相比較,只有查詢略有不同
XML預設是select;  Annotation預設是FetchType.EAGER(join)

沒有留言:

張貼留言