hibernate級聯刪除和插入


一個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進行設定:

  all : 所有操作都傳遞到相關聯的對象
  save-update 保存和更新傳遞到相關聯的對象
  delete 刪除操作傳遞到相關聯的對象
  delete-orphan : 所有操作都傳遞到相關聯的對象 並刪除不再與父對象關聯的對象。
  2.配置表關聯時,需注意inverse這個屬性,有true和false兩種值,表示數據表由誰進行進行操作,
   若是inverse="true"表示子表由子表本身維護,若是inverse="false"表示子表由主表維護。
    在級聯插入時,由於只對主表進行操作,子表沒有操作,要想order能夠順利插入ordertt表中,
   就需要將inverse="false"。若是inverse="true",子表也能插入數據,但是兩者關聯的CID沒有數據跟新
   下面是hibernate執行的sql語句,能夠很清楚的說明這點,當inverse="false"時,多了條update的語句
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效率差,沒有驗證過,通過觸發器

  和數據庫直接設置外鍵關聯,幾者效率如何,有待研究。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM