`

理解Hibernate的inverse和cascade属性(实例)

阅读更多
1.理解cascade属性
创建CUSTOMERS和ORDERS数据库表
CREATE TABLE  `hiber`.`customers` (
  `ID` bigint(20) NOT NULL AUTO_INCREMENT,
  `NAME` varchar(45) DEFAULT NULL,
  PRIMARY KEY (`ID`)
) ENGINE=MyISAM;

CREATE TABLE  `hiber`.`orders` (
  `ID` bigint(20) NOT NULL AUTO_INCREMENT,
  `ORDER_NO` varchar(45) DEFAULT NULL,
  `CUSTOMER_ID` bigint(20) DEFAULT NULL,
  PRIMARY KEY (`ID`)
) ENGINE=MyISAM;

创建持久化对象
Customer类:
package com;

import java.io.Serializable;

public class Customer implements Serializable {

private static final long serialVersionUID = 1L;

private long id;
private String name;
public long getId() {
return id;
}
private void setId(long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}

}

Customer类的配置文件(Customer.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>
<class name="com.Customer" table="CUSTOMERS">
<id name="id" column="ID" type="long">
<generator class="native"/>
</id>

<property name="name" column="NAME" type="string"/>
</class>
</hibernate-mapping>

Order类:
package com;

import java.io.Serializable;

public class Order implements Serializable {

private static final long serialVersionUID = 1L;

private long id;
private String orderNo;
private Customer customer;
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public String getOrderNo() {
return orderNo;
}
public void setOrderNo(String orderNo) {
this.orderNo = orderNo;
}
public Customer getCustomer() {
return customer;
}
public void setCustomer(Customer customer) {
this.customer = customer;
}

}

Order类的配置文件(Order.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="com">
<class name="Order" table="ORDERS">
<id name="id" column="ID" type="long">
<generator class="identity"/>
</id>

<property name="orderNo" column="ORDER_NO" type="string" not-null="true"/>
<many-to-one name="customer" column="CUSTOMER_ID" class="com.Customer" />
</class>
</hibernate-mapping>

创建一个工具类
package tool;

import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;

import com.Customer;
import com.Order;

public class HibernateUtil {

private static SessionFactory sessionFactory;

static {
Configuration config = new Configuration();
//适合Java属性配置连接数据库
config.addClass(Customer.class)
      .addClass(Order.class);

//适合XML配置连接数据库
//config.configure();
sessionFactory = config.buildSessionFactory();
}

public static SessionFactory getSessionFactory() {
return sessionFactory;
}

public static Session getSession() {
return sessionFactory.openSession();
}

}

配置Hibernate的连接数据库(有2种方式)
1.Java属性(hibernate.properties文件)
hibernate.dialect=org.hibernate.dialect.MySQLDialect
hibernate.connection.driver_class=com.mysql.jdbc.Driver
hibernate.connection.url=jdbc:mysql://localhost:3306/hiber
hibernate.connection.username=root
hibernate.connection.password=123456
hibernate.show_sql=true

2.XML(hibernate.cfg.cml)
<?xml version='1.0' encoding='utf-8'?>
<!DOCTYPE hibernate-configuration PUBLIC
        "-//Hibernate/Hibernate Configuration DTD 3.0//EN"
        "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">

<hibernate-configuration>
    <session-factory>

        <!-- Database connection settings(MySQL) -->
        <property name="connection.driver_class">com.mysql.jdbc.Driver</property>
        <property name="connection.url">jdbc:mysql://localhost:3306/hiber</property>
        <property name="connection.username">root</property>
        <property name="connection.password">123456</property>

        <!-- SQL dialect -->
        <property name="dialect">org.hibernate.dialect.MySQLDialect</property>

        <property name="show_sql">true</property>

<!-- 映射配置文件 -->
        <mapping resource="com/Customer.hbm.xml"/>
        <mapping resource="com/Order.hbm.xml"/>

    </session-factory>
</hibernate-configuration>


创建测试类
package service;

import org.hibernate.Session;
import org.hibernate.Transaction;

import tool.HibernateUtil;

import com.Customer;
import com.Order;

public class BusinessService {

/**
* @param args
*/
public static void main(String[] args) {
Session session = HibernateUtil.getSession();
Transaction tx = null;
try {
tx = session.beginTransaction();
Customer customer = new Customer();
customer.setName("David");
Order o = new Order();
o.setOrderNo("no_003");
//建立单向关联
o.setCustomer(customer);
session.save(o); //因为在Order.hbm.xml中配置了cascade="save-update",所以会级联保存
System.out.println(customer.getId()); //在save()操作后,事物提交前,已经能获得ID
customer.setName("Phil"); //会执行一条Update语句
tx.commit();
customer.setName("Bruce"); //事物提交后,持久化类的修改不会被保存
} catch(Exception e) {
if (tx != null) {
tx.rollback();
}
e.printStackTrace();
} finally {
session.close();
}
}

}
运行会抛以下异常
org.hibernate.TransientObjectException: object references an unsaved transient instance - save the transient

instance before flushing: com.Customer
因为Order类对象参照的Customer不是持久化对象,而是临时对象。在保存Order对象之前,应该先保存Customer对象。可以使用级

联,修改配置文件(Order.hbm.xml)如下(加上cascade="save-update"):
<many-to-one name="customer" column="CUSTOMER_ID" class="com.Customer" cascade="save-update" />

再次运行
/**Output:
Hibernate: insert into CUSTOMERS (NAME) values (?)
Hibernate: insert into ORDERS (ORDER_NO, CUSTOMER_ID) values (?, ?)
7
Hibernate: update CUSTOMERS set NAME=? where ID=?
*/

以上输出,没有生成查询ID的语句(Hibernate: select max(ID) from CUSTOMERS)。因为我设置的标识符生成器是native和

identity的,这会由底层数据库负责生成ID,可以看到创建数据库表的时候设置了主键的auto_increment。如果数据库表没有设置

主键的auto_increment或者数据库不支持主键自动增涨,可以将标识符生成器设置为increment,这时持久化对象时会生成查询ID

的语句。

/*
查看数据库
select * from  customers where id = 7;

ID NAME
7 Phil

select * from orders where customer_id = 7;

ID ORDER_ID CUSTOMER_ID
13 no_001   7
*/

总结:
cascade表示级联,可选值有:
<1>."none":(默认值)不级联
<2>."save-update":级联保存和更新
<3>."delete":级联删除
<4>."all":包括save-update和delete
<5>."delete-orphan":删除所有和本对象已经解除关系了的对象
<6>."all-delete-orphan":包括all和delete-orphan



2.理解inverse属性

将上面的单向关联改成双向关联
在Customer.java持久化类里填加Order
private Set orders = new HashSet();
public Set getOrders() {
return orders;
}
public void setOrders(Set orders) {
this.orders = orders;
}

在Customer.hbm.xml中填加orders属性的配置
<set name="orders" cascade="all" inverse="false">
<key column="CUSTOMER_ID"/>
<one-to-many class="com.Order"/>
</set>

修改测试类:
package service;

import org.hibernate.Session;
import org.hibernate.Transaction;

import tool.HibernateUtil;

import com.Customer;
import com.Order;

public class BusinessService {

/**
* @param args
*/
public static void main(String[] args) {
Session session = HibernateUtil.getSession();
Transaction tx = null;
try {
tx = session.beginTransaction();
Customer customer = new Customer();
customer.setName("David");
Order o = new Order();
o.setOrderNo("no_001");

session.save(customer);
session.save(o);

//建立双向关联
customer.getOrders().add(o);
o.setCustomer(customer);

tx.commit();
} catch(Exception e) {
if (tx != null) {
tx.rollback();
}
e.printStackTrace();
} finally {
session.close();
}
}

}
/**Output:
Hibernate: insert into CUSTOMERS (NAME) values (?)
Hibernate: insert into ORDERS (ORDER_NO, CUSTOMER_ID) values (?, ?)
Hibernate: update ORDERS set ORDER_NO=?, CUSTOMER_ID=? where ID=?
Hibernate: update ORDERS set CUSTOMER_ID=? where ID=?
*/
如果Customer.hbm.xml配置文件<set>设置inverse="true",就不会输出最后1条update语句,表示Customer持久化类不维护关联关

系;如果设置inverse="false"(默认值)或者不设置该属性,表示Customer持久化类维护关联关系,这样造成多执行一次update

操作;一般都把<set>加上inserve="true"属性,以免影响Java应用的性能。<many-to-one>没有inverse属性,它运行行为默认维

护关联关系(inverse="false")。

修改Customer.hbm.xml文件orders属性的配置(inverse="true")
<set name="orders" cascade="all" inverse="true">
<key column="CUSTOMER_ID"/>
<one-to-many class="com.Order"/>
</set>

再次运行
/**Output:
Hibernate: insert into CUSTOMERS (NAME) values (?)
Hibernate: insert into ORDERS (ORDER_NO, CUSTOMER_ID) values (?, ?)
Hibernate: update ORDERS set ORDER_NO=?, CUSTOMER_ID=? where ID=?
*/

总结:在双向关联关系中,一般设置一的一端为inverse="true",多的一端为inverse="false"。
0
0
分享到:
评论

相关推荐

    Hibernate的多对一和一对多操作实例

    `inverse`属性表示是否反向维护关联关系,`lazy`属性控制加载策略,而`cascade`属性则定义了级联操作的行为。 ### 总结 通过上述实例,我们可以清晰地看到在Hibernate框架中如何实现“多对一”和“一对多”的关系...

    Hibernate 对集合属性的操作.zip_hibernate

    在Java开发中,Hibernate是一个非常重要的对象关系映射(ORM)框架,它简化了...通过深入理解和熟练应用这些知识点,开发者可以高效地在Hibernate中管理集合属性,实现复杂的数据操作,提升项目的开发效率和运行性能。

    hibernate自身关联一对多实例(树形结构)

    总结来说,"Hibernate自身关联一对多实例(树形结构)"涉及到Java对象与数据库表之间的映射,以及如何在代码中建立和管理这种关联。正确理解和应用这些知识,可以帮助开发者高效地处理层次型数据,提高开发效率。对于...

    hibernate学习笔记

    ### Hibernate中的Inverse属性详解 在Hibernate框架中,`inverse`属性是用于管理对象...通过上述实例分析,我们可以看到`inverse`属性在实际开发中的应用价值,以及它如何帮助我们构建更加健壮和高效的数据库应用。

    Hibernate笔试题.doc

    在使用了 Hibernate 的系统中,要想在删除某个客户数据的同时删除该客户对应的所有订单数据,可以配置客户和订单关联的 cascade 属性为 all。 7. 一对多关联配置 在一对多关联配置中,存在错误的是 inverse 属性不...

    3.Hibernate 03 表关系详细教案1

    总结,本教程详细介绍了Hibernate中表关系的映射,包括不同关系的配置、`Cascade`和`Inverse`属性的使用,以及如何在Java类和XML配置文件中实现这些映射。理解并掌握这些概念对于高效使用Hibernate进行数据库操作至...

    Hibernate级联操作.docx

    在 Hibernate 中,级联操作(Cascade)和反向属性(Inverse)是管理对象关系的重要概念,特别是在处理一对多(One-to-Many)或多对一(Many-to-One)关系时。 **级联操作(Cascade)** 级联操作定义了当主对象被...

    Hibernate基础考试题借鉴.pdf

    4. **inverse属性**:在Hibernate中,inverse属性用于指定关联的维护责任。C选项正确,表示在节点上,声明关联的维护由对方(many端)负责。 5. **级联操作**:在删除客户数据时希望同时删除相关订单,需要配置...

    Hibernate笔记.doc

    总之,理解并熟练运用这些Hibernate映射属性和关联管理策略,能够帮助开发人员更有效地进行数据持久化操作,减少不必要的数据库交互,提高应用程序的性能和数据一致性。在实际开发中,应根据业务需求和性能考虑,...

    J2EE考试复习试题.pdf

    在使用Hibernate的系统中,要想在删除某个客户数据的同时删除该客户对应的所有订单数据,可以配置客户和订单关联的cascade属性为all。 知识点7: 一对多关联配置 在Hibernate中,一对多关联的配置中,inverse属性...

    hibernate题目

    4. **inverse 属性**:在 Hibernate 中,inverse 属性用于指定关联的维护责任。在 `&lt;one-to-many&gt;` 节点上设置 inverse="true" 表示多方(集合端)负责关联的维护(C选项正确)。在 `&lt;set&gt;` 节点上设置 inverse 属性...

    Hibernate双向一对多

    标题"Hibernate双向一对多"指的是Hibernate框架中的一个重要关系映射概念,即在一个实体类中,一个实例可以与多个另一个实体类的实例相关联,而在另一个实体类中,每个实例也可以关联到该实体类的一个实例。...

    Hibernate开发指南(原版书)

    - **数据访问**:讨论PO(Persistent Object)和VO(Value Object)的区别,以及unsaved-value属性的作用,深入解析Inverse和Cascade机制,解释延迟加载(Lazy Loading)的原理和应用场景。 - **事务管理**:分析...

    Hibernate开发指南

    Inverse和Cascade则用于控制实体间关联关系的传播。 延迟加载(Lazy Loading)是一种优化策略,可以提高性能,但需要在使用时注意其懒加载机制。事务管理部分介绍了基于JDBC和基于JTA(Java Transaction API)的...

    精通hibernate:对象持久化技术孙卫琴第二版part2

    本章介绍一对多关联关系的映射方法,重点介绍inverse属性和cascade属性的用法。本章还将介绍通过Hibernate API来保存、修改和删除具有关联关系的对象的方法。 7.1 建立多对一的单向关联关系 148 7.1.1 [many-to-...

Global site tag (gtag.js) - Google Analytics