2015年11月7日 星期六

複合主鍵 (Hibernate3.x 十五)

※準備資料

CREATE TABLE SCHOOL_USER(
    ID NUMBER(10) NOT NULL,
    UNAME VARCHAR(10) NOT NULL,
    SEX VARCHAR(1),
    CONSTRAINT PK_ID_UNAME PRIMARY KEY(ID, UNAME)
);
    
COMMENT ON TABLE SCHOOL_USER IS '使用者';
COMMENT ON COLUMN SCHOOL_USER.ID IS '使用者id';
COMMENT ON COLUMN SCHOOL_USER.NAME IS '使用者名稱';
COMMENT ON COLUMN SCHOOL_USER.SEX IS '性別';

※使用ID和NAME為複合主鍵

※XML設定

UserPK.java

public class UserPK implements Serializable {
    private Integer uid;
    private String uname;
    //setter/getter...
}

※一定要implements Serializable,不然執行時會出「org.hibernate.MappingException: composite-id class must implement Serializable: vo.UserPK」的錯

User.java

private UserPK xxx;
private String sex;
//setter/getter...

User.hbm.xml

<class name="vo.User" table="SCHOOL_USER">
    <composite-id name="xxx" class="vo.UserPK">
    
        <key-property name="uid" type="java.lang.Integer">
            <column name="ID" />
        </key-property>
    
        <key-property name="uname" type="java.lang.String">
            <column name="NAME" />
        </key-property>
    
        <generator class="assigned" />
    </composite-id>
    
    <property name="sex" type="java.lang.String">
        <column name="SEX" />
    </property>
</class>

※我資料庫的表本來想取名為USER,欄位叫UID,但這兩個剛好是Oracle的關鍵字,雖然聽說可用「"」的方式,但為了保險起見,還是算了,所以我在hbm.xml做轉換的動作

※generator必需在composite-id的最下面

測試類

Session s = HibernateUtil2.getSession();
Transaction tx = s.beginTransaction();
try {
    UserPK pk = new UserPK();
    User u = new User();
    pk.setUid(1);
    pk.setUname("one");
    u.setXxx(pk);
    u.setSex("M");
    s.save(u);
    tx.commit();
    
    UserPK pk2 = new UserPK();
    pk2.setUid(1);
    pk2.setUname("one");
    User u2 = (User) s.load(User.class, pk2);
    System.out.println(u2.getXxx().getUid() + "||" + u2.getXxx().getUname());
} catch (Exception e) {
    tx.rollback();
    System.err.println("例外錯誤!");
    e.printStackTrace();
} finally {
    if (s.isOpen()) {
        s.close();
    }
}


※Annotation設定

記得要在hibernate.cfg.xml增加mapping class

UserPK.java

@Embeddable
public class UserPK implements Serializable {
    //...
}

※PK類只要在類別設定即可

User.java

@Entity
@Table(name = "SCHOOL_USER")
public class User {
    private UserPK xxx;
    private String sex;
    
    @EmbeddedId
    @AttributeOverrides({
        @AttributeOverride(name = "uid", column = @Column(name = "ID", nullable = false, length = 10)),
    
        @AttributeOverride(name = "uname", column = @Column(name = "NAME", nullable = false, length = 10))
    })
    public UserPK getXxx() {
        return xxx;
    }
    
    public void setXxx(UserPK xxx) {
        this.xxx = xxx;
    }
    
    public String getSex() {
        return sex;
    }
    
    public void setSex(String sex) {
        this.sex = sex;
    }
}

※注意是@EmbeddedId哦!

※在@AttributeOverride設定對應關係,當然和之前一樣,Column和類別名稱一樣可不打,只留@EmbeddedId即可

沒有留言:

張貼留言