hibernate里面的一对多关系映射里面,一般都是指一张主表和一张从表。
在表示“多”的一方数据表里面增加一个外键,来指向表示“一”的那方数据表,“一”也就是我们所说的主表,而“多”就是我们所说的从表,接下来我们可以举个例子来进行说明:
(我所用的数据库是mysql)
这是一张顾客表(customer)的结构
这是一张订单表(order)的结构
在两张表里面,customer的cid和order里面的cid是一致的,因此我们可以将订单表里面的cid设置一个外键,将它和顾客表里面的cid进行绑定;
通过相应的绑定,当用户删除掉一条客户信息的时候,订单表里面的cid会自动变换为null值,在这里我设置了删除时为set null操作而不是cascade操作,因此不会出现级联删除(后边会讲如何进行级联删除操作)
然后便是顾客类的代码:
package com.sise.lh.model;
import java.util.HashSet;
import java.util.Set;
public class Customer {
public int cid;
public String cname;
public Set<Order> order=new HashSet<Order>();
public Set<Order> getOrder() {
return order;
}
public void setOrder(Set<Order> order) {
this.order = order;
}
public String getCname() {
return cname;
}
public void setCname(String cname) {
this.cname = cname;
}
public int getCid() {
return cid;
}
public void setCid(int cid) {
this.cid = cid;
}
}
然后便是订单order类:
package com.sise.lh.model;
public class Order {
public String address;
public int cid;
public int id;
public int price;
public Customer customer;
public int getPrice() {
return price;
}
public void setPrice(int price) {
this.price = price;
}
public String getAddress() {
return address;
}
public int getCid() {
return cid;
}
public int getId() {
return id;
}
public Customer getCustomer() {
return customer;
}
public void setCustomer(Customer customer) {
this.customer = customer;
}
public void setAddress(String address) {
this.address = address;
}
public void setCid(int cid) {
this.cid = cid;
}
public void setId(int id) {
this.id = id;
}
}
光有这些类的描述还不够,还需要有相应的配置才可以:
这里是顾客表的配置:
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<!-- Mapping file autogenerated by MyEclipse Persistence Tools -->
<hibernate-mapping>
<class name="com.sise.lh.model.Customer" table="customer" catalog="test">
<id name="cid" column="cid">
<generator class="identity"></generator>
</id>
<property name="cname" type="java.lang.String">
<column name="cname" length="35" not-null="true" />
</property>
<!-- save-update:设置级联关系,这样的话可以支持顺时态和持久态的对象同时保存 -->
<!-- delete:设置级联关系进行删除 -->
<!-- delete-orphan:设置级联关系进行孤儿删除 -->
<set name="order" >
<key column="cid"/>
<one-to-many class="com.sise.lh.model.Order"/>
</set>
</class>
</hibernate-mapping>
这里是订单表的配置:
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<!-- Mapping file autogenerated by MyEclipse Persistence Tools -->
<hibernate-mapping>
<class name="com.sise.lh.model.Order" table="order" catalog="test">
<id name="id" column="id">
<generator class="identity"></generator>
</id>
<property name="address" type="java.lang.String">
<column name="address" length="35" not-null="true" />
</property>
<property name="price" type="java.lang.Integer">
<column name="price" length="6" not-null="true" />
</property>
<many-to-one name="customer" class="com.sise.lh.model.Customer" column="cid">
</many-to-one>
</class>
</hibernate-mapping>
接下来是进行相应的测试部分:
@Test
public void testManyToOne()
{
Transaction transaction= session.beginTransaction();
Customer c=(Customer) session.get(Customer.class, 13);
Order o1=new Order();
o1.setAddress("深圳01");
o1.setPrice(144);
Order o2=new Order();
o2.setAddress("南京01");
o2.setPrice(188);
c.getOrder().add(o1);
c.getOrder().add(o2);
session.save(c);
session.save(o1);
session.save(o2);
transaction.commit();
}
成功之后的截图如下:
由于我们之前在设置外键的时候只是设置为了set null操作,因此当用户表里面的信息被删除之后,订单表里面的信息还不会立马就被删除,只是有所绑定的cid字段会被设置为null而已。
接下来便是删除操作部分:
@Test
public void testDelete()
{
Transaction transaction=session.beginTransaction();
Customer c=(Customer) session.get(Customer.class, 13);
session.delete(c);
transaction.commit();
}
果然和开始预期所想的结果一样,那么这个时候,又是否有办法在不接触到数据库的前提下,通过hibernate的配置来进行订单表里面整条数据的级联删除呢?
答案是有的,可以通过修改xml里面cascade属性进行操作,也就是这顾客类customer.hbm.xml的配置:
<set name="order" cascade="delete">
<key column="cid"/>
<one-to-many class="com.sise.lh.model.Order"/>
</set>
只需要在上边添加cascade=”delete”属性即可实现
关于顾客表里面的cascade状态我参考了另外一篇博客里面的内容
http://www.cnblogs.com/amboyna/archive/2008/02/18/1072260.html
此时我又进行了相应的操作,再次插入两条数据:
接下来再是一次执行删除操作
@Test
public void testDelete()
{
Transaction transaction=session.beginTransaction();
Customer c=(Customer) session.get(Customer.class, 18);
session.delete(c);
transaction.commit();
}
通过cascade=”delete”属性的绑定,这次数据被完全删除了