`

有关Hibrnate中inverse的配置

阅读更多

1.现在假设有两个类Customer与Order,一个Customer可以有多个Order


2.如果在Customer.hbm.xml中设置inverse=true,那么代表customer与order的关系由order来维护,就是说如果采用Customer c=customerDao.findById("1"),c.getOrders.add(new Order()),那么在数据库层面表现为,首先假设在order表格中customer_id可以为空,那么上面的代码会在order表中重保存一条order记录,但是这条纪录中的customer_id=null,这正体现出inverse的设置作用,customer的保存不会维护ustomer与order之间的关系。

 

3.如果在Customer.hbm.xml中设置iverser=false,那么代表customer与order的关系由customer来维护,

还是采用2种说明的代码,那么在数据库中表现为会增加一条order记录,并且这条记录的customer_d不为空.

 

具体代码说明:

1.模型类

Java代码 复制代码
  1. public class Customer {   
  2.   
  3.     private String id;   
  4.   
  5.     private String name;   
  6.   
  7.     private Set orders = new HashSet();   
  8.   
  9.     public String getId() {   
  10.         return id;   
  11.     }   
  12.   
  13.     public void setId(String id) {   
  14.         this.id = id;   
  15.     }   
  16.   
  17.     public String getName() {   
  18.         return name;   
  19.     }   
  20.   
  21.     public void setName(String name) {   
  22.         this.name = name;   
  23.     }   
  24.   
  25.     public Set getOrders() {   
  26.         return orders;   
  27.     }   
  28.   
  29.     public void setOrders(Set orders) {   
  30.         this.orders = orders;   
  31.     }   
  32. }  
public class Customer {

	private String id;

	private String name;

	private Set orders = new HashSet();

	public String getId() {
		return id;
	}

	public void setId(String id) {
		this.id = id;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public Set getOrders() {
		return orders;
	}

	public void setOrders(Set orders) {
		this.orders = orders;
	}
}

 

 

Java代码 复制代码
  1. public class Order {   
  2.   
  3.     private String id;   
  4.   
  5.     private Customer customer;   
  6.   
  7.     private String address;   
  8.   
  9.     public String getAddress() {   
  10.         return address;   
  11.     }   
  12.   
  13.     public void setAddress(String address) {   
  14.         this.address = address;   
  15.     }   
  16.   
  17.     public Customer getCustomer() {   
  18.         return customer;   
  19.     }   
  20.   
  21.     public void setCustomer(Customer customer) {   
  22.         this.customer = customer;   
  23.     }   
  24.   
  25.     public String getId() {   
  26.         return id;   
  27.     }   
  28.   
  29.     public void setId(String id) {   
  30.         this.id = id;   
  31.     }   
  32. }  
public class Order {

	private String id;

	private Customer customer;

	private String address;

	public String getAddress() {
		return address;
	}

	public void setAddress(String address) {
		this.address = address;
	}

	public Customer getCustomer() {
		return customer;
	}

	public void setCustomer(Customer customer) {
		this.customer = customer;
	}

	public String getId() {
		return id;
	}

	public void setId(String id) {
		this.id = id;
	}
}

 

 

1.配置文件

Java代码 复制代码
  1. <?xml version="1.0" encoding="utf-8"?>   
  2. <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"  
  3. "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">   
  4. <!--    
  5.     Mapping file autogenerated by MyEclipse - Hibernate Tools   
  6. -->   
  7. <hibernate-mapping>   
  8.     <class name="domain.Customer" table="customers" catalog="blogday">   
  9.         <id name="id">   
  10.             <column name="id" />   
  11.             <generator class="native"></generator>   
  12.         </id>   
  13.         <property name="name">   
  14.             <column name="name" length="20" />   
  15.         </property>   
  16.         <set name="orders" lazy="true" inverse="true" cascade="all">   
  17.             <key column="customer_id" />   
  18.             <one-to-many class="domain.Order" />   
  19.         </set>   
  20.     </class>   
  21. </hibernate-mapping>   
  22.    
<?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 - Hibernate Tools
-->
<hibernate-mapping>
	<class name="domain.Customer" table="customers" catalog="blogday">
		<id name="id">
			<column name="id" />
			<generator class="native"></generator>
		</id>
		<property name="name">
			<column name="name" length="20" />
		</property>
		<set name="orders" lazy="true" inverse="true" cascade="all">
			<key column="customer_id" />
			<one-to-many class="domain.Order" />
		</set>
	</class>
</hibernate-mapping>
 

 

Java代码 复制代码
  1. <?xml version="1.0" encoding="utf-8"?>   
  2. <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"  
  3. "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">   
  4. <!--    
  5.     Mapping file autogenerated by MyEclipse - Hibernate Tools   
  6. -->   
  7. <hibernate-mapping>   
  8.     <class name="domain.Order" table="orders" catalog="blogday">   
  9.         <id name="id">   
  10.             <column name="id" />   
  11.             <generator class="native"></generator>   
  12.         </id>   
  13.         <property name="address">   
  14.             <column name="address" length="20" />   
  15.         </property>   
  16.         <many-to-one name="customer" column="customer_id"  
  17.             class="domain.Customer" cascade="none" />   
  18.     </class>   
  19. </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 - Hibernate Tools
-->
<hibernate-mapping>
	<class name="domain.Order" table="orders" catalog="blogday">
		<id name="id">
			<column name="id" />
			<generator class="native"></generator>
		</id>
		<property name="address">
			<column name="address" length="20" />
		</property>
		<many-to-one name="customer" column="customer_id"
			class="domain.Customer" cascade="none" />
	</class>
</hibernate-mapping>

 

3.测试代码

Java代码 复制代码
  1. public void testSaveOrdersByInverse_Error_Method() {   
  2.         Exception e = null;   
  3.         Customer c = customerDao.findById("1");   
  4.         Order order = new Order();   
  5.         Order order2 = new Order();   
  6.         c.getOrders().add(order2);   
  7.         c.getOrders().add(order);   
  8.         try {   
  9.             customerDao.save(c);   
  10.             customerDao.getHibernateTemplate().flush();   
  11.         } catch (Exception e1) {   
  12.             e = e1;   
  13.         }   
  14.         assertNotNull(e);   
  15.     }   
  16.        
public void testSaveOrdersByInverse_Error_Method() {
		Exception e = null;
		Customer c = customerDao.findById("1");
		Order order = new Order();
		Order order2 = new Order();
		c.getOrders().add(order2);
		c.getOrders().add(order);
		try {
			customerDao.save(c);
			customerDao.getHibernateTemplate().flush();
		} catch (Exception e1) {
			e = e1;
		}
		assertNotNull(e);
	}
	 

4. 结果说明

 

4.1  如果设置invserse=true,那么方法testSaveOrdersByInverse_Error_Method()在测试的时候

customerDao.getHibernateTemplate().flush()进行flush的时候会发生错误,错误原因是在order表格中

不允许customer_id=null,而在此时方法testSaveOrdersByInverse_Error_Method会级联保存order记录,但是保存的order记录中hibernate却设置customer_id=null,这也说明了inverse=true说明customer不负责与order之间的引用关系,只是简单的保存记录,并没有建立起二者之间的关系.

 

4.2如果设置inverse=false,说明customer与order之间的关系由customer来维护,那么上面的测试方法testSaveOrdersByInverse_Error_Method()不但会保存相应的order记录,并且order记录中的customer_id也不为空.

 

5.性能考虑

 

5.1 如果设置inverse=true,用如下代码测试

Java代码 复制代码
  1. public void testSaveOrdersByInverse_Right_method() {   
  2.         Exception e = null;   
  3.         Customer c = customerDao.findById("1");   
  4.         Order order1 = new Order();   
  5.         Order order2 = new Order();   
  6.         c.getOrders().add(order1);   
  7.         c.getOrders().add(order2);   
  8.         order1.setCustomer(c);   
  9.         order2.setCustomer(c);   
  10.         try {   
  11.             customerDao.save(c);   
  12.             customerDao.getHibernateTemplate().flush();   
  13.         } catch (Exception e1) {   
  14.             e = e1;   
  15.         }   
  16.         assertNull(e);   
  17.     }  
public void testSaveOrdersByInverse_Right_method() {
		Exception e = null;
		Customer c = customerDao.findById("1");
		Order order1 = new Order();
		Order order2 = new Order();
		c.getOrders().add(order1);
		c.getOrders().add(order2);
		order1.setCustomer(c);
		order2.setCustomer(c);
		try {
			customerDao.save(c);
			customerDao.getHibernateTemplate().flush();
		} catch (Exception e1) {
			e = e1;
		}
		assertNull(e);
	}

   测试结果为:

 

Java代码 复制代码
  1. Hibernate: select orders0_.customer_id as customer3_1_, orders0_.id as id1_, orders0_.id as id1_0_, orders0_.address as address1_0_, orders0_.customer_id as customer3_1_0_ from blogday.orders orders0_ where orders0_.customer_id=?   
  2. Hibernate: insert into blogday.orders (address, customer_id) values (?, ?)   
  3. Hibernate: insert into blogday.orders (address, customer_id) values (?, ?)  
Hibernate: select orders0_.customer_id as customer3_1_, orders0_.id as id1_, orders0_.id as id1_0_, orders0_.address as address1_0_, orders0_.customer_id as customer3_1_0_ from blogday.orders orders0_ where orders0_.customer_id=?
Hibernate: insert into blogday.orders (address, customer_id) values (?, ?)
Hibernate: insert into blogday.orders (address, customer_id) values (?, ?)

    说明没插入一条order只需要执行一次插入操作,没有额外的代码执行.

 

5.2 如果设置inverse=false,也顺便设置数据库中order表格中customer_id可以为空,这样下面的代码才不会 抛出错误

Java代码 复制代码
  1. public void testSaveOrdersByInverse_Error_Method() {   
  2.         Exception e = null;   
  3.         Customer c = customerDao.findById("1");   
  4.         Order order1 = new Order();   
  5.         Order order2 = new Order();   
  6.         c.getOrders().add(order1);   
  7.         c.getOrders().add(order2);   
  8.         try {   
  9.             customerDao.save(c);   
  10.             customerDao.getHibernateTemplate().flush();   
  11.         } catch (Exception e1) {   
  12.             e = e1;   
  13.         }   
  14.         assertNull(e);   
  15.     }  
public void testSaveOrdersByInverse_Error_Method() {
		Exception e = null;
		Customer c = customerDao.findById("1");
		Order order1 = new Order();
		Order order2 = new Order();
		c.getOrders().add(order1);
		c.getOrders().add(order2);
		try {
			customerDao.save(c);
			customerDao.getHibernateTemplate().flush();
		} catch (Exception e1) {
			e = e1;
		}
		assertNull(e);
	}

 测试结果:

Java代码 复制代码
  1. Hibernate: select customer0_.id as id0_0_, customer0_.name as name0_0_ from blogday.customers customer0_ where customer0_.id=?   
  2. Hibernate: select orders0_.customer_id as customer3_1_, orders0_.id as id1_, orders0_.id as id1_0_, orders0_.address as address1_0_, orders0_.customer_id as customer3_1_0_ from blogday.orders orders0_ where orders0_.customer_id=?   
  3. Hibernate: insert into blogday.orders (address, customer_id) values (?, ?)   
  4. Hibernate: insert into blogday.orders (address, customer_id) values (?, ?)   
  5. Hibernate: update blogday.orders set customer_id=? where id=?   
  6. Hibernate: update blogday.orders set customer_id=? where id=?  
Hibernate: select customer0_.id as id0_0_, customer0_.name as name0_0_ from blogday.customers customer0_ where customer0_.id=?
Hibernate: select orders0_.customer_id as customer3_1_, orders0_.id as id1_, orders0_.id as id1_0_, orders0_.address as address1_0_, orders0_.customer_id as customer3_1_0_ from blogday.orders orders0_ where orders0_.customer_id=?
Hibernate: insert into blogday.orders (address, customer_id) values (?, ?)
Hibernate: insert into blogday.orders (address, customer_id) values (?, ?)
Hibernate: update blogday.orders set customer_id=? where id=?
Hibernate: update blogday.orders set customer_id=? where id=?

 

 

插入customer也会相应的插入order记录,这个在上面已经说明.但是看这里多出了两条update语句,针对每一个孩子都去更新父亲的id明显速度很慢,因为父亲有个孩子的集合,他无法知道哪个孩子的父亲id已经指向自己了,所以对于每一个孩子,都要更新父亲使他只想自己,而这个关系由孩子维护就好多了,每个孩子只有一个父亲,只有设置过的才需要更新,所以显然,这个父子关系由孩子来维护比较省力.减轻了数据库的负担.

 

 

正对以上情况在设置one-many或者many-one或者many-many的时候需要谨慎用inverse,而且从性能上来说一般还是有字节点来维护与父节点的关系比较好如下代码就可以简单而且高效来建立二者之间的关系.

 

Java代码 复制代码
  1. public void testSave() {   
  2.     Customer customer = customerDao.findById("1");   
  3.     Order order = new Order();   
  4.     order.setCustomer(customer);   
  5.     orderDao.save(order);   
  6.     assertNotNull(order.getId());   
  7. }  
	public void testSave() {
		Customer customer = customerDao.findById("1");
		Order order = new Order();
		order.setCustomer(customer);
		orderDao.save(order);
		assertNotNull(order.getId());
	}

 

这里的操作很简单而且数据库操作也仅有一条查询语句和一条插入语句.

 

Java代码 复制代码
  1. Hibernate: select customer0_.id as id0_0_, customer0_.name as name0_0_ from blogday.customers customer0_ where customer0_.id=?   
  2. Hibernate: insert into blogday.orders (address, customer_id) values (?, ?)  
Hibernate: select customer0_.id as id0_0_, customer0_.name as name0_0_ from blogday.customers customer0_ where customer0_.id=?
Hibernate: insert into blogday.orders (address, customer_id) values (?, ?)

 

 

 

 

分享到:
评论

相关推荐

    JavaEE学习笔记之Hibernate表关系之一对多(inverse详解)

    在Hibernate中,通过配置XML映射文件或使用注解,我们可以定义实体间的这种关系。在一对多关系中,"一"端称为父实体,"多"端称为子实体。 `inverse`属性是Hibernate中用于控制关联维护权的重要参数,它的主要作用...

    hibernate配置文件详解

    Hibernate 配置文件详解 Hibernate 是一个流行的 ORM(Object-Relational Mapping)框架,用于简化 Java 应用程序中的数据库交互。 Hibernate 的配置文件是其核心组件之一,用于定义 Hibernate 的运行期参数。下面...

    hibernate inverse和cascade的详细讲解

    在这些配置选项中,`inverse`和`cascade`是最具挑战性的两个概念之一。它们主要用于控制对象之间关联关系的维护以及操作的级联行为。本文将详细介绍这两个属性的概念、作用以及应用场景,并通过示例来帮助读者更好地...

    Hibernate中cascade与inverse属性详解

    在 Hibernate 框架中,`cascade` 和 `inverse` 是两个非常重要的属性,它们用于管理对象之间的关联关系。...在实际开发中,需要根据业务需求灵活调整 `cascade` 和 `inverse` 的配置,以达到最佳的数据管理和性能优化。

    Hibernate关联关系配置

    在上面的配置中,`&lt;set&gt;`元素定义了一个名为`orders`的集合,用于存放所有与当前消费者相关的订单。`inverse="true"`表示当更新集合时,是否由该方负责更新关联的另一方;`cascade="all"`表示级联操作,即对消费者...

    hibernate 级联(cascade和inverse)一对多

    在Java的持久化框架Hibernate中,级联操作(Cascade)和反转(Inverse)是两个重要的概念,它们主要用于管理对象关系模型中的关联关系。在一对多的关系中,这些特性可以帮助简化数据操作,提高代码的可读性和维护性...

    常用 Hibernate 映射配置说明.doc

    `hibernate-mapping`节点是Hibernate映射文件中的顶级节点,用于定义一系列配置选项,控制整个映射文件的行为和映射规则。这些配置包括数据库连接细节、默认的映射策略等。 - **schema**: 定义了数据库的Schema名称...

    hibernate集合映射inverse和cascade详解.txt

    在深入探讨Hibernate集合映射中的`inverse`与`cascade`属性之前,我们首先需要理解Hibernate框架的基本概念。Hibernate是一个开放源代码的对象关系映射(ORM)框架,它为Java应用程序提供了一种将对象模型与数据库...

    Hibernate学习笔记和资料

    hibernate中一对一,一对多,多对多关系的配置,延迟加载,cascade,inverse hibernate查询方式概述,HQL查询,QBC查询,分页,结果集封装方式 ,高级查询 查询的优化,一级缓存,二级缓存,批量查询,注解方式

    hibernate之一对多配置demo

    在XML配置中,我们可以设置级联属性: ```xml ``` 这里`cascade="all-delete-orphan"`表示级联所有操作,包括删除孤儿(即当一个班级被删除时,其关联的学生也将被删除)。 四、总结 通过本教程,你可以了解...

    Hibernate 多表映射关系配置

    在这个配置中,`User` 类有一个 `Set&lt;Role&gt;` 类型的 `roles` 属性,而 `Role` 类有一个 `Set&lt;User&gt;` 类型的 `users` 属性。`inverse` 属性用于指定哪个集合负责维护关联关系,通常将它设为 `false` 的那个集合负责...

    hibernate的联合主键怎么设置

    有了以上配置,你就可以在程序中通过 Hibernate API 来操作这个联合主键的实体类了,例如增删改查等操作。 接下来,我们讨论 `inverse` 属性的影响。`inverse` 属性用于控制在一个关联关系中,哪一方负责维护关联...

    Hibernate 简单 PPT 总结

    - "05-2018-7-9-Hibernate-配置数据库连接池.pptx"可能介绍了如何在Hibernate中配置和使用数据库连接池,以提高应用性能。 - "2018-7-24-Hibernate-配置表关系.pptx"和"06-2018-7-9-Hibernate-对象关系映射文件.pptx...

    Hibernate配置文件中映射元素详解

    【Hibernate配置文件中映射元素详解】 在对象关系映射(ORM)框架Hibernate中,对象与数据库表之间的关联是通过一个XML配置文件来定义的。这个XML文件包含了映射元素,用于描述Java类如何转化为数据库中的表。映射...

    hibernate配置要点详谈

    在Hibernate中,有两种主要的配置文件形式:`hibernate.cfg.xml` 和 `hibernate.properties`。 1. **`hibernate.cfg.xml`**: - 这种配置文件通常包含数据库连接信息、映射文件位置以及其他配置参数。 - 可以直接...

    inverse=true的总结

    综上所述,“inverse=true”是Hibernate中一个关乎数据一致性与性能的重要配置。理解并恰当运用它,可以有效地优化ORM框架的使用,提高代码质量,并减少潜在的数据库一致性问题。在实际项目开发中,需要根据业务需求...

    hibernate中一对多配置

    在Java的持久化框架Hibernate中,一对多(One-to-Many)关系是数据库表...在Hibernate中,它们的配置方式略有不同,但都通过外键实现关联。理解这些概念并正确配置,能帮助我们更有效地管理和操作数据库中的对象关系。

    对Hibernate配置文件中的映射元素详解

    在本文中,我们将深入探讨Hibernate配置文件中的映射元素,这些元素是将对象关系映射到数据库的关键部分。首先,我们需要了解映射文件的基本结构,它通常是一个XML文档,遵循特定的DTD(文档类型定义)。 `...

Global site tag (gtag.js) - Google Analytics