引用myqhit在one-many和many-one的关系中的inverse的详解。
1.现在假设有两个类Customer与Order,一个Customer可以有多个Order
2. 如果在Customer.hbm.xml中设置inverse=投入额,那么代表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.模型类
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;
}
}
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.配置文件
<?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>
<?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.测试代码
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,用如下代码测试
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);
}
测试结果为:
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可以为空,这样下面的代码才不会 抛出错误
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);
}
测试结果:
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,而且从性能上来说一般还是有字节点来维护与父节点的关系比较好如下代码就可以简单而且高效来建立二者之间的关系.
public void testSave() {
Customer customer = customerDao.findById("1");
Order order = new Order();
order.setCustomer(customer);
orderDao.save(order);
assertNotNull(order.getId());
}
这里的操作很简单而且数据库操作也仅有一条查询语句和一条插入语句.
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 (?, ?)
分享到:
相关推荐
同时,`Account.hbm.xml`中的`many-to-one`元素将`column`属性设置为`FID`,表示通过`FID`字段关联到`User`实体。 #### 测试场景解释 在测试场景中,我们创建了一个`User`对象和一个`Account`对象,并在`User`对象...
在深入讲解这两个属性之前,我们首先需要理解 Hibernate 中的一些基本概念,如 one-to-many 和 many-to-one 关系、对象的状态以及 Session 缓存。 一、one-to-many 和 many-to-one 关系 在示例中,`class` 表(班级...
对于`one-to-one`和`many-to-one`关系,它们仅包含单个对象的引用,因此不需要使用`inverse`。 - **Inverse 的值** - **默认值**:`inverse`的默认值为`false`,表示对集合对象的修改会被反映到数据库中。 - **`...
本篇将深入探讨Hibernate中的对象关系映射,包括一对一(One-to-One)、一对多(One-to-Many)、多对一(Many-to-One)以及多对多(Many-to-Many)的关系映射。 ### 1. 一对一关系 一对一关系在现实生活中很常见,...
关联映射主要包括四种类型:一对一(One-to-One)、一对多(One-to-Many)、多对一(Many-to-One)和多对多(Many-to-Many)。下面我们将逐一探讨这些关联映射的配置方法。 1. **一对一关联映射** - **主键关联**...
### Hibernate表关联关系详解 ...综上所述,无论是`many-to-many`还是`one-to-one`关联关系,在Hibernate中都可以通过相应的配置文件来实现。正确地理解和配置这些关联关系对于构建高效、可扩展的应用程序至关重要。
在User的配置文件中,不直接声明与Account的关联,而是在Account的配置文件中通过`<many-to-one>`标签来定义与User的关联。`name`属性指定了关联属性名,`column`属性指定了外键列名,`class`属性指定了关联类的全...
- **一对一映射**:使用`<many-to-one>`元素表示,如`<many-to-one name="friend" column="friend_id" update="false"/>`。 - **一对多映射**:使用`<set>`元素配合`<one-to-many>`元素表示,例如: ```xml ...
- `<many-to-one>`、`<one-to-many>`、`<one-to-one>`、`<many-to-many>`:分别表示不同类型的关联关系。 ##### 2.2 基本映射示例 以一个简单的用户(User)与地址(Address)为例,假设有一个用户表(users)和一...
在关系型数据库设计中,实体之间的关联关系主要有三种类型:一对一(One-to-One)、一对多(One-to-Many)以及多对多(Many-to-Many)。而Hibernate作为一种流行的Java持久层框架,它能够帮助我们更好地管理和操作...
相对应地,多对一(Many-to-One)关系则是从多个实体指向一个单一实体的关联。理解这两种配置的区别对于进行高效的数据操作至关重要。 **一对多关系详解:** 在Hibernate中,一对多关系通常用在父类(拥有端)和...
5. `<many-to-one>`和`<one-to-many>`元素:用于描述一对多或多对一的关系。例如: ```xml <!-- 一对多 --> <set name="orders" inverse="true"> <one-to-many class="com.example.models.Order"/> <!-- ...
这种一对一关联的方式比较特殊,它在两个表中都添加了一个外键,同时在配置文件中使用`<many-to-one>`代替`<one-to-one>`。虽然这种方式在官方文档中未明确提及,但在实践中也是可行的。 **配置文件** (`Course.hbm...
在双向关联中,Hibernate引入了`inverse`属性来指定关联的哪一方负责维护关系。这主要是因为在一个双向关联中,如果两边都试图维护关系的话,可能会导致数据库级别的并发问题或循环更新的问题。因此,通常需要指定一...
在这个配置文件中,`<many-to-one>`元素指定了订单与消费者之间的一对多关系。`class`属性指定了一对一关联的另一端实体类型,`column`属性则指定了外键字段。 #### 三、自身一对多关系配置示例 自身一对多关系是...
Hibernate 配置文件详解 Hibernate 是一个流行的 ORM(Object-Relational ...通过 hibernate.cfg.xml 和 .hbm.xml 文件,我们可以定义 Hibernate 的基本连接信息和映射关系,从而实现 Java 应用程序中的数据库交互。
`<many-to-one>` 用于表示从一方到多方的映射,而 `<property>` 用于映射基本类型的属性(C、D选项错误)。 以上是对 Hibernate 题目中的关键知识点的详细解释,涵盖了 Hibernate 的基本概念、配置、映射和查询等...
- **<many-to-one>标签**:关键标签,用于指定关联关系。 - **多对一存储**:通常先存储父对象(如Group),然后再保存子对象(如User)。 - **重要属性-cascade(级联)**:控制当父对象操作时是否级联到子对象,...