一個Customer中有多個Order,刪除(增加)Customer同事刪除(增加)Order.命名很多不規范,臨時寫的demo,湊合着....
Customer.hbm.xml:
<?xml version="1.0"?> <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD//EN" "http://hibernate.sourceforge.net/hibernate-mapping-2.0.dtd"> <hibernate-mapping> <class name="com.demo.hibernate.model.Customer" table="CUSTOMER"> <id name="id" type ="java.lang.Integer" column="CID"> <generator class="increment" /> </id> <property name="username" column="USERNAME" /> <property name="password" column="PASSWORD" /> <set name="order" table="ordertt" inverse="false" cascade="all"> <key column="CID"/> <one-to-many class="com.demo.hibernate.model.Order"/> </set> </class> </hibernate-mapping>
Order.hbm.xml:
<?xml version="1.0"?> <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD//EN" "http://hibernate.sourceforge.net/hibernate-mapping-2.0.dtd"> <hibernate-mapping> <class name="com.demo.hibernate.model.Order" table="ORDERTT"> <id name="orderId" type ="java.lang.Integer" column="orderId" unsaved-value="0"> <generator class="increment" /> </id> <property name="id" column="CID" /> <property name="orderName" column="orderName" /> </class> </hibernate-mapping>
相應的Javabean:
public class Customer { private int id; private String username; private String password; private Set<Order> order= new HashSet<Order>(); //get和set方法 }
public class Order {
private int orderId;
private int id; //customerid
private String orderName;
}
測試:
package com.demo.hibernate.test; import java.util.HashSet; import java.util.Set; import org.hibernate.HibernateException; import org.hibernate.SessionFactory; import org.hibernate.Transaction; import org.hibernate.cfg.Configuration; import org.hibernate.classic.Session; import com.demo.hibernate.model.Customer; import com.demo.hibernate.model.Order; public class Test { public static void main(String[] args) { try { SessionFactory sf = new Configuration().configure() .buildSessionFactory(); Session session = sf.openSession(); Transaction tx = session.beginTransaction();
// List<Customer> customers = session.createQuery("select c from Customer as c").list();
// for(Iterator iterator = customers.iterator();iterator.hasNext();) {
// Customer customer= (Customer)iterator.next();
// System.out.println(customer.getId()+ " "+customer.getUsername());
// }
Customer customer = new Customer(); customer.setPassword("customer"); customer.setUsername("customer203"); Order order = new Order(); order.setOrderName("customer203"); Set<Order> orders = new HashSet<Order>(); orders.add(order); customer.setOrder(orders); // session.delete(customer); session.save(customer); tx.commit(); session.close(); } catch (HibernateException e) { e.printStackTrace(); } } }
小結:1.在hibernate中設置級聯關系是通過cascade進行設定:
Hibernate: select max(CID) from CUSTOMER Hibernate: select max(orderId) from ORDERTT Hibernate: insert into CUSTOMER (USERNAME, PASSWORD, CID) values (?, ?, ?) Hibernate: insert into ORDERTT (CID, orderName, orderId) values (?, ?, ?) Hibernate: update ORDERTT set CID=? where orderId=?
3.unsaved-value屬性
在進行級聯插入時,最初沒有對子表的id設置unsaved-value="0",導致拋出如下異常:
Hibernate: select max(CID) from CUSTOMER Hibernate: insert into CUSTOMER (USERNAME, PASSWORD, CID) values (?, ?, ?) Hibernate: update ORDERTT set CID=?, orderName=? where orderId=? org.hibernate.StaleStateException: Batch update returned unexpected row count from update [0]; actual row count: 0; expected: 1
可以看到原本應該執行insert的sql卻執行了update。這就是unsaved-value這個屬性的作用了。
我們級聯插入數據時,save(customer)時,hibernate根據配置文件找到了子表,同時給子表生成save(order)方法,這個時候根據unsaved-value判斷了,
hibernate會根據配置文件,找到order主鍵,getOrderId();若是orderId與unsaved-value指定的值一樣,則表示,此對象尚未持久化,hibernate一系列
邏輯之后,就有了insert,反之就是update。如果不寫unsaved-value,很顯然,hibernate默認為update。因為sql找不到相應的id,導致報錯。
5.我們在查詢customer對象時,記住是用createQuery而非createSqlQuery,前者是面向對象查詢,后者是純粹的sql,想要得到customer對象,使用前者
4.Google的時候看到的,一並記下。當hibernate設置級聯時,數據庫無需任何外鍵或者觸發器之類的操作,都說hibernate效率差,沒有驗證過,通過觸發器
和數據庫直接設置外鍵關聯,幾者效率如何,有待研究。