Hibernate中实现对象与对象之间的关系:有一对一,一对多,多对多。下面来认识Hibernate的单向多对一关系。
在配置映射文件中让我们来认识<many-to-one name="" column="" cascade=""/>多对一这个标签。
首先,我们定义两个实体类:Customer,Order。
代码如下:
Customer类:
package example.many2one_single;
/**
* 客户(一方)
* @author Administrator
*
*/
public class Customer {
private Integer id;//对应表的主键
private String name;
private Integer age;
public Customer() {
}
public Customer(String name, Integer age) {
super();
this.name = name;
this.age = age;
}
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 Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
}
Order类:
package example.many2one_single;
/**
* 订单(多的一方)
* @author Administrator
*
*/
public class Order {
private Integer id;
private String OrderNo;//订单编号
private Integer price;//价格
private Customer customer;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getOrderNo() {
return OrderNo;
}
public void setOrderNo(String orderNo) {
OrderNo = orderNo;
}
public Integer getPrice() {
return price;
}
public void setPrice(Integer price) {
this.price = price;
}
public Order(String orderNo, Integer price) {
super();
OrderNo = orderNo;
this.price = price;
}
public Order() {
super();
// TODO Auto-generated constructor stub
}
public Customer getCustomer() {
return customer;
}
public void setCustomer(Customer customer) {
this.customer = customer;
}
}
第二步:配置映射文件,把Customer和Order的映射都写在同一个映射文件中:
CustomerOrder.hbm.xml:
<?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">
<hibernate-mapping package="example.many2one_single">
<class name="Customer" table="customers">
<id name="id" column="id" type="int">
<generator class="native"></generator>
</id>
<property name="name" column="name" type="string"></property>
<property name="age" column="age" type="int"></property>
</class>
<class name="Order" table="Orders">
<id name="id" column="id">
<generator class="native"></generator>
</id>
<property name="orderNo" column="orderNo"></property>
<property name="price" column="price"></property>
<!--many-to-one映射多方的关联属性
name表示关联的属性名
column表示多方的外键列
-->
<many-to-one name="customer" column="customers_id" ></many-to-one>
</class>
</hibernate-mapping>
第三步:在mysql建表:
create table customers(
id int(5) primary key auto_increment,name varchar(50),age int(5)
);
create table orders(
id int primary key auto_increment,
orderNo varchar(255),
price int(5),
customer_id int(5),
constraint customer_order_FK foreign key(id) references customers(id)
);
第四步,写执行代码:
package example.dao;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.cfg.Configuration;
import org.junit.Test;
import example.many2one_single.Customer;
import example.many2one_single.Order;
import example.utils.HibernateUtils;
public class CustomerOrderDao {
private static SessionFactory sessionFactory;
static{
//创建configure配置文件hibernate.properties
Configuration cfg=new Configuration();
//加载映射文件hibernate.cfg.xml
cfg.configure();
//创建sessionFactory工厂对象
sessionFactory=cfg.buildSessionFactory();
}
/**
* 先保存1客户,再保存2订单------3条SQL
*/
@Test
public void test01(){
Customer customer=new Customer("小李",14);
Order o1=new Order("order2011",100);
Order o2=new Order("order2012",100);
//创建创建单项关联
o1.setCustomer(customer);
o2.setCustomer(customer);
Session session=null;
Transaction ts=null;
try{
//创建session对象
//session= sessionFactory.openSession();
session=HibernateUtils.getSession();
//开启事务
ts= session.getTransaction();
//开始事务
ts.begin();
//保存对象到数据库
session.save(o1);
session.save(o2);
session.save(customer);
ts.commit();
}catch (Exception e) {
// TODO: handle exception
ts.rollback();
e.printStackTrace();
}finally{
//session.close();
HibernateUtils.closeSession();
}
}
/**
* 先保存2订单,再保存1客户------5条SQL
*/
@Test
public void test02(){
Customer customer=new Customer("小李",14);
Order o1=new Order("order2011",100);
Order o2=new Order("order2012",100);
//创建创建单项关联
o1.setCustomer(customer);
o2.setCustomer(customer);
Session session=null;
Transaction ts=null;
try{
//创建session对象
//session= sessionFactory.openSession();
session=HibernateUtils.getSession();
//开启事务
ts= session.getTransaction();
//开始事务
ts.begin();
//保存对象到数据库
session.save(customer);
session.save(o1);
session.save(o2);
ts.commit();
}catch (Exception e) {
// TODO: handle exception
ts.rollback();
e.printStackTrace();
}finally{
//session.close();
HibernateUtils.closeSession();
}
}
接下来我们认识cascade="save-update/all":当我们在代码中这样写的话会出现临时对象出错异常(org.hibernate.TransientObjectException: object references an unsaved transient instance - save the transient instance before flushing: example.many2one_single.Customer)。
/**
* 只保存2订单,级联保存1客户(cascade="save-update/all")
*/
@Test
public void test03(){
Customer customer=new Customer("小名",14);
Order o1=new Order("order2011",100);
Order o2=new Order("order2012",100);
//创建创建单项关联
o1.setCustomer(customer);
o2.setCustomer(customer);
Session session=null;
Transaction ts=null;
try{
//创建session对象
//session= sessionFactory.openSession();
session=HibernateUtils.getSession();
//开启事务
ts= session.getTransaction();
//开始事务
ts.begin();
//保存对象到数据库
session.save(o1);
session.save(o2);
ts.commit();
}catch (Exception e) {
// TODO: handle exception
ts.rollback();
e.printStackTrace();
}finally{
//session.close();
HibernateUtils.closeSession();
}
}
这是因为持久对象引用临时对象导致的错误,所以要避免这种错误,就应该在映射文件中添加 cascade="save-update"
配置如下:
<?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">
<hibernate-mapping package="example.many2one_single">
<class name="Customer" table="customers">
<id name="id" column="id" type="int">
<generator class="native"></generator>
</id>
<property name="name" column="name" type="string"></property>
<property name="age" column="age" type="int"></property>
</class>
<class name="Order" table="Orders">
<id name="id" column="id">
<generator class="native"></generator>
</id>
<property name="orderNo" column="orderNo"></property>
<property name="price" column="price"></property>
<!--many-to-one映射多方的关联属性
name表示关联的属性名
column表示多方的外键列
-->
<many-to-one name="customer" column="customers_id" cascade="save-update"></many-to-one>
</class>
</hibernate-mapping>
只更新2订单,级联更新1客户【cascade="save-update/all"】:
/**
* 只更新2订单,级联更新1客户【cascade="save-update/all"】
*/
@Test
public void test04(){
Session session=null;
Transaction ts=null;
try{
//创建session对象
//session= sessionFactory.openSession();
session=HibernateUtils.getSession();
//开启事务
ts= session.getTransaction();
//开始事务
ts.begin();
Order o6= (Order) session.get(Order.class, 6);
o6.setPrice(o6.getPrice()+20);
Order o7=(Order) session.get(Order.class, 7);
o7.setPrice(o7.getPrice()+30);
Customer cus=o6.getCustomer();
cus.setAge(cus.getAge()+4);
//保存对象到数据库
session.save(o6);
session.save(o7);
ts.commit();
}catch (Exception e) {
// TODO: handle exception
ts.rollback();
e.printStackTrace();
}finally{
//session.close();
HibernateUtils.closeSession();
}
}
只删除订单,级联删除客户【cascade="delete/all"】,只删除订单,不级联删除客户【cascade="none",默认值】:
/**
* 只删除订单,级联删除客户【cascade="delete/all"】
*/
@Test
public void test05(){
Session session=null;
Transaction ts=null;
try{
//创建session对象
//session= sessionFactory.openSession();
session=HibernateUtils.getSession();
//开启事务
ts= session.getTransaction();
//开始事务
ts.begin();
Order o6= (Order) session.get(Order.class, 8);
session.delete(o6);
ts.commit();
}catch (Exception e) {
// TODO: handle exception
ts.rollback();
e.printStackTrace();
}finally{
//session.close();
HibernateUtils.closeSession();
}
}