※table per class hierarchy(每個階層類別一個表)
※table per subclass(每個子類別一個表)
※table per concrete class(每個具體類別一個表)
尤於翻譯的有和沒有一樣,所以提供官方連結,這裡先從下往上講,個人感覺比較好懂
※table per concrete class(union-subclass)
※準備資料
CREATE TABLE STUDENT( ID NUMBER(5), NAME VARCHAR(10), PRICE NUMBER(5), PRODUCT_DATE DATE, SCORE NUMBER(3), SCHOOL VARCHAR(20), CONSTRAINT PK_STUDENT PRIMARY KEY(ID) ); CREATE TABLE MAKER( ID NUMBER(5), NAME VARCHAR(10), PRICE NUMBER(5), PRODUCT_DATE DATE, SALARY NUMBER(6), COMPANY VARCHAR(20), CONSTRAINT PK_MAKER PRIMARY KEY(ID) );
※ID、NAME、PRICE、PRODUCT_DATE,這四個欄位兩張表都有,所以可以提出來模擬成java的繼承關係,取一個名字,譬如叫Chess,然後將兩張對應的表繼承它
※XML設定
Chess.java
public abstract class Chess { private Integer id; private String name; private Integer price; private Date productDate; //setter/getter... }
※Chess是個抽象類別,讓Student和Maker繼承
Student.java
public class Student extends Chess { private Integer score; private String school; //setter/getter... }
Maker.java
public class Maker extends Chess { private Integer salary; private String company; //setter/getter... }
Chess.hbm.xml
<class name="vo.Chess" abstract="true"> <id name="id" type="java.lang.Integer"> <column name="ID" /> <generator class="assigned" /> </id> <property name="name" type="java.lang.String"> <column name="NAME" /> </property> <property name="price" type="java.lang.Integer"> <column name="PRICE" /> </property> <property name="productDate" type="java.util.Date"> <column name="PRODUCT_DATE" /> </property> <union-subclass name="vo.Student" table="STUDENT"> <property name="score" type="java.lang.Integer"> <column name="SCORE" /> </property> <property name="school" type="java.lang.String"> <column name="SCHOOL" /> </property> </union-subclass> <union-subclass name="vo.Maker" table="MAKER"> <property name="salary" type="java.lang.Integer"> <column name="SALARY" /> </property> <property name="company" type="java.lang.String"> <column name="COMPANY" /> </property> </union-subclass> </class>
※Chess可以加個abstract=true,更加確定是個抽象類別,其他兩個類別用union-subclass
測試類:
SessionFactory sf = HibernateUtil2.getSessionFactory(); Session s1 = sf.openSession(); Session s2 = sf.openSession(); Transaction tx = s1.beginTransaction(); Transaction tx2 = s2.beginTransaction(); try { System.out.println("-----測試學生-----"); Student stu = new Student(); stu.setId(1); stu.setName("象棋"); stu.setPrice(50); stu.setProductDate(new Date(100, 0, 1)); stu.setScore(78); stu.setSchool("家裡蹲大學"); s1.save(stu); Student stuRtn = (Student) s1.load(Student.class, 1); System.out.println("學校名:" + stuRtn.getSchool()); System.out.println("-----測試員工-----"); Maker mak = new Maker(); mak.setId(1); mak.setName("五子棋"); mak.setPrice(30); mak.setProductDate(new Date(102, 11, 12)); mak.setSalary(43000); mak.setCompany("少林寺管委會"); s2.save(mak); Maker makRtn = (Maker) s2.load(Maker.class, 1); System.out.println("公司名:" + makRtn.getCompany()); tx.commit(); tx2.commit(); } catch (Exception e) { System.err.println("例外錯誤!"); e.printStackTrace(); tx.rollback(); } finally { if (s1.isOpen()) { s1.close(); } if (s2.isOpen()) { s2.close(); } }
※hibernate.cfg.xml只要增加一行<mapping resource="vo/Chess.hbm.xml" />即可
※如果使用同一個session,而且id相同,就會出現「org.hibernate.NonUniqueObjectException: a different object with the same identifier value was already associated with the session:」的例外
就算有二級快取,也是一樣,所以和快取沒關係
.原因是因為同一個session不能有相同的名稱
.使用Session的clean、refresh、merge都不行
.但如果是Student和Maker分開,也就是Student做完就commit,然後clean再做Maker即可,我現在是假設二筆資料一起commit、一起rollback的話就不行
.Maker不使用save,改用merge會過,但在load時,會出現Student不能強轉成Maker的錯,很正常,因為繼承同一個類別,Session裡面存的是第一次的Student
.這是使用table per concrete class的缺點
※Annotation設定
Chess.java
@Inheritance(strategy = InheritanceType.TABLE_PER_CLASS) @Entity public abstract class Chess { private Integer id; private String name; private Integer price; private Date productDate; @Id public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public Integer getPrice() { return price; } public void setPrice(Integer price) { this.price = price; } @Column(name = "PRODUCT_DATE") public Date getProductDate() { return productDate; } public void setProductDate(Date productDate) { this.productDate = productDate; } }
※id是一定要設的,而Column只有productDate的名稱和資料庫不同,設這個就好
※三個類別都必需設定@Inheritance
Student.java
@Inheritance(strategy = InheritanceType.TABLE_PER_CLASS) @Entity public class Student extends Chess { private Integer score; private String school; //setter/getter... }
※由於Table和Column一樣可以不打,所以這是最精簡設定
Maker.java
@Inheritance(strategy = InheritanceType.TABLE_PER_CLASS) @Entity public class Maker extends Chess { private Integer salary; private String company; //setter/getter... }
hibernate.cfg.xml
<mapping class="vo.Chess" /> <mapping class="vo.Student" /> <mapping class="vo.Maker" />
※三個類別都必需增加才可以
※測試類別一樣
沒有留言:
張貼留言