Hibernate关联映射(1)
Hibernate有三种关联映射,分别是一对一,一对多,多对多。
因为一对一在开发中很少用到,所以不讲。
一对多,多方里要有外键指向一方。
例如顾客和订单,一个顾客可以有多个订单,一个订单只能属于一个顾客。这就是一对多。
1.我们这里说的全是双向的。
2.hibernate包是用Myeclipse自带的4.14
[Customer.java][6]
package com.ljs.bean;
import java.util.HashSet;
import java.util.Set;
public class Customer {
private Integer id;
private String name;
//用户拥有多个订单
private Set<Order> orders = new HashSet<Order>();
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Set<Order> getOrders() {
return orders;
}
public void setOrders(Set<Order> orders) {
this.orders = orders;
}
}
[Order.java][6]
package com.ljs.bean;
public class Order {
private Integer id;
private String address;
private double price;
//订单属于某个用户
private Customer customer;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
public double getPrice() {
return price;
}
public void setPrice(double price) {
this.price = price;
}
public Customer getCustomer() {
return customer;
}
public void setCustomer(Customer customer) {
this.customer = customer;
}
}
[Customer.hbm.xml][6]
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="com.ljs.bean">
<class name="Customer" table="customers">
<id name="id" type="integer">
<generator class="native"/>
</id>
<property name="name" type="string" length="20"/>
<!-- 一对多关系使用set集合映射 -->
<set name="orders">
<!-- 确定关联的外键列 -->
<key column="cid"/>
<!--映射到关联类属性-->
<one-to-many class="com.ljs.bean.Order"/>
</set>
</class>
</hibernate-mapping>
[Order.hbm.xml][6]
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="com.ljs.bean">
<class name="Order" table="orders">
<id name="id" type="integer">
<generator class="native"/>
</id>
<property name="address" length="50"/>
<property name="price"/>
<!-- 多对一关系映射 -->
<many-to-one name="customer" class="com.ljs.bean.Customer" column="cid"/>
</class>
</hibernate-mapping>
[Test.java][]
package com.ljs.test;
import org.hibernate.Session;
import org.hibernate.Transaction;
import com.ljs.bean.Customer;
import com.ljs.bean.Order;
import com.ljs.util.HibernateUtil;
public class HibernateTest {
static Session session = HibernateUtil.getSession();
public static void main(String[] args) {
// TODO Auto-generated method stub
Transaction tx = session.beginTransaction();
// 创建一个客户
Customer c1 = new Customer();
c1.setName("张三");
// 创建两个订单
Order o1 = new Order();
o1.setAddress("广州");
o1.setPrice(100000d);
Order o2 = new Order();
o2.setAddress("上海");
o2.setPrice(2500d);
// 描述关系--订单属于某个客户
o1.setCustomer(c1);
o2.setCustomer(c1);
// 描述关系--客户有多个订单
c1.getOrders().add(o1);
c1.getOrders().add(o1);
// 持久化先存客户
try{
session.save(c1);
session.save(o1);
session.save(o2);
tx.commit();
}catch (Exception e){
e.printStackTrace();
tx.rollback();
}finally {
if(session.isOpen()) {
session.close();
}
}
}
}
运行可看见控制台输出
Hibernate: insert into customers (name) values (?)
Hibernate: insert into orders (address, price, cid) values (?, ?, ?)
Hibernate: insert into orders (address, price, cid) values (?, ?, ?)
Hibernate: update orders set cid=? where id=?
Hibernate: update orders set cid=? where id=?
在这里顺便说下反转和级联,上面的sql出现了插入和更新两种sql操作,但是做的都是同一件事,这样多出多余的sql,浪费资源。所以我们可以使用反转inverse属性来解决这个问题,默认情况下,两方的默认值为false,在一对多中,我们一般将一方的inverse属性设置为true,由多的一方来维护关联关系。在Customer.hbm.xml中的set中设置
<set name="orders" inverse="true">
控制台输出
Hibernate: insert into customers (name) values (?)
Hibernate: insert into orders (address, price, cid) values (?, ?, ?)
Hibernate: insert into orders (address, price, cid) values (?, ?, ?)
如果想当主控方执行保存,更新,删除操作时,其关联的对象也执行相同的操作,可以使用cascade级联属性
修改后的Test.java
package com.ljs.test;
import org.hibernate.Session;
import org.hibernate.Transaction;
import com.ljs.bean.Customer;
import com.ljs.bean.Order;
import com.ljs.util.HibernateUtil;
public class HibernateTest {
static Session session = HibernateUtil.getSession();
public static void main(String[] args) {
// TODO Auto-generated method stub
Transaction tx = session.beginTransaction();
// 创建一个客户
Customer c1 = new Customer();
c1.setName("张三");
// 创建两个订单
Order o1 = new Order();
o1.setAddress("广州");
o1.setPrice(100000d);
Order o2 = new Order();
o2.setAddress("上海");
o2.setPrice(2500d);
// 描述关系--订单属于某个客户
//不再关联
//o1.setCustomer(c1);
//o2.setCustomer(c1);
// 描述关系--客户有多个订单
c1.getOrders().add(o1);
c1.getOrders().add(o2);
// 持久化先存客户
try{
session.save(c1);
//不用对订单进行持久化
//session.save(o1);
//session.save(o2);
tx.commit();
}catch (Exception e){
e.printStackTrace();
tx.rollback();
}finally {
if(session.isOpen()) {
session.close();
}
}
}
}
修改Customer.hbm.xml
<set name="orders" cascade="save-update" inverse="true">