一个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效率差,没有验证过,通过触发器
和数据库直接设置外键关联,几者效率如何,有待研究。