2015年12月12日 星期六

一對一單向PK關聯 (Hibernate3.x 二十四)

這次的設定是Car可以關聯到CarAttr,但CarAttr不能關聯到Car,所以是單向


※XML設定

※一對一單向PK關聯

準備工作

DROP TABLE CAR PURGE;
DROP TABLE CAR_ATTR PURGE;
    
CREATE TABLE CAR (    
    CID NUMBER(5,0), 
    NAME VARCHAR2(20), 
    CONSTRAINT CAR_PK PRIMARY KEY (CID)
);
    
CREATE TABLE CAR_ATTR (
    CAID NUMBER(5,0), 
    COLOR VARCHAR2(20), 
    CC NUMBER(3,0), 
    CONSTRAINT CAR_ATTR_PK PRIMARY KEY (CAID)
);
CREATE SEQUENCE CAR_ATTR_SEQ;

※和一對一雙向PK關聯一樣,只是多個自動產生PK的sequence

hibernate.cfg.xml

要增加xml連到hbm.xml的設定
<mapping resource="vo/Car.hbm.xml" />
<mapping resource="vo/CarAttr.hbm.xml" />


Car.hbm.xml

<class name="vo.Car" table="CAR">
    <id name="cid" type="java.lang.Integer">
        <column name="CID" />
        <generator class="foreign">
            <param name="property">carAttr</param>
        </generator>
    </id>
    
    <property name="name" type="java.lang.String">
        <column name="NAME" />
    </property>
    
    <one-to-one name="carAttr" class="vo.CarAttr" constrained="true" />
</class>

※PK交給CarAttr設定

CarAttr.hbm.xml

<class name="vo.CarAttr" table="CAR_ATTR">
    <id name="caid" type="java.lang.Integer">
        <column name="CAID" />
        <generator class="sequence">
            <param name="sequence">CAR_ATTR_SEQ</param>
        </generator>
    </id>
    
    <property name="color" type="java.lang.String">
        <column name="COLOR" />
    </property>
    
    <property name="cc" type="java.lang.Integer">
        <column name="CC" />
    </property>
</class>

※因為是單向,所以不用關聯到Car

Car.java

public class Car {
    private Integer cid;
    private String name;
    private CarAttr carAttr;
    //setter/getter...
}

※要關聯到CarAttr,所以要寫

CarAttr.java

public class CarAttr {
    private Integer caid;
    private String color;
    private Integer cc;
    //setter/getter...
}

※不用關聯到Car,所以不用寫

新增測試

Session s = HibernateUtil2.getSession();
Transaction tx = s.beginTransaction();
try {
    CarAttr ca = new CarAttr();
    // ca.setCaid(3350);// 如果不是sequence就在這塞PK
    ca.setColor("藍2");
    ca.setCc(530);
    
    Car c = new Car();
    c.setName("寶石傑2");
    c.setCarAttr(ca);
    
    s.save(c);
    tx.commit();
} catch (Exception e) {
    tx.rollback();
    System.err.println("例外錯誤!");
    e.printStackTrace();
} finally {
    if (s.isOpen()) {
        s.close();
    }
}

※只要save(c)就可以了,我試過沒有cascade="all"也可以

修改測試

CarAttr ca = new CarAttr();
ca.setCaid(103); // 實務上須自行去資料庫撈出來
ca.setColor("藍5");
ca.setCc(530);
    
Car c = new Car();
c.setName("寶石傑5");
c.setCarAttr(ca);
c.setCid(ca.getCaid());
    
s.update(c);
// s.update(ca);// 如果在Car.hbm.xml加cascade="all" 可不用這行
tx.commit();

※要注意cascade的差異

查詢測試

Car car = (Car) s.get(Car.class, 103);
s.close();
System.out.println(car.getName());
System.out.println(car.getCarAttr().getColor()); 

※需在Car.hbm.xml加lazy="false",否則會出Session is close的錯
※資料庫撈不到也會出Session is close的錯
※fetch="join"無效,一直都是select
※因為是單向,查Car肯定只會查到自己的,所以不用測

刪除測試

Car c = new Car();
c.setCid(105);
    
CarAttr ca = new CarAttr();
ca.setCaid(c.getCid());
    
c.setCarAttr(ca);
    
s.delete(c); // 需在Car.hbm.xml加cascade="all",不然只會刪除Car
tx.commit();

※要注意cascade的差異




※Annotation設定


hibernate.cfg.xml

<mapping class="vo.Car" />
<mapping class="vo.CarAttr" />

Car.java

@Entity
@Table
public class Car {
    @Id
    @GenericGenerator(name = "xxx", strategy = "foreign", parameters = { @Parameter(name = "property", value = "carAttr") })
    @GeneratedValue(generator = "xxx")
    private Integer cid;
    
    private String name;
    
    @OneToOne(cascade = CascadeType.ALL, fetch = FetchType.EAGER)
    @PrimaryKeyJoinColumn
    private CarAttr carAttr;
    
    //setter/getter...
}

CarAttr.java

@Entity
@Table(name = "CAR_ATTR")
public class CarAttr {
    @Id
    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "XXX")
    @SequenceGenerator(name = "XXX", sequenceName = "CAR_ATTR_SEQ")
    private Integer caid;
    
    private String color;
    
    private Integer cc;
    
    //setter/getter...
}

※增刪改查的測試只有一個地方不同,那就是查詢Car時,FetchType.LAZY和FetchType.EAGER(也就是select和join)都有用了,這點居然不同步,很奇怪

沒有留言:

張貼留言