一个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效率差,没有验证过,通过触发器

  和数据库直接设置外键关联,几者效率如何,有待研究。

posted on 2012-02-01 19:48  lzycc  阅读(6595)  评论(0编辑  收藏  举报