inverse常用于一对多双向关联关系中。
以Student(学生)和Class(班级)为例,它们之间的关系为一对多的关系,即一个学生只能属于一个班级,一个班级可以包含多个学
生。
学生类定义代码:
Class Student{
private int id;
private String name;
private Class class;
//省略getter()和setter()方法
}
班级类定义代码:
Class Class{
private int id;
private String name;
private Set students = new HashSet();
//省略getter()和setter()方法
}
Student类的映射文件:
<class name="Student" table="STUDENT">
<id name="id" type="int" column="ID">
<generator class="native" />
</id>
<property name="name" type="string" column="NAME" />
<many-to-one name="class" column="CLASS_ID" class="Class" cascade="save-update" />
</class>
Class类的映射文件:
<class name="Class" table="CLASS">
<id name="id" type="int" column="ID">
<generator class="native" />
</id>
<property name="name" type="string" column="NAME" />
<set name="students" table="STUDENT" cascade="save-update" inverse="false">
<key column="CLASS_ID" />
<one-to-many class="Student" />
</set>
</class>
希望你能对这两个映射文件所表达的数据库模式有正确的认识。即STUDENT表中存在一个名为CLASS_ID的字段,它和CLASS表中的ID字段是主外键关系。那个inverse属性就是用来规定是由谁(Student或Class)来维护这个主外键关系的。
inverse的默认值为false。
在处理逻辑代码中,如下:
Class c1 = new Class();
c1.setName("一班");
Student s1 = new Student();
Student s2 = new Student();
s1.setName("Jason");
s2.setName("Tom");
c1.getStudents().add(s1);
c2.getStudents().add(s2);
s1.setClass(c1);
s2.setClass(c1); //注释1
session.save(c1);
上面的代码会使Hibernate执行五条SQL语句,其中前三条是insert插入语句,后两条是update更新语句。插入就不用说了,那么为什么还要有更新语句呢?这是因为Class类映射文件的<set>元素中指定了inverse="false",这就告之Hibernate:STUDENT表与CLASS表的主外键关系是由Class类来维护的。当执行save后,执行了三条insert语句,这三条语句中的后两条是插入到STUDENT表的,它们的CLASS_ID字段是通过s1.getClass().getID()取出的,假如我将上面“注释1”处修改为s2.setClass(c2);(c2是另一个Class对象,可能是持久化对象),这样,主外键关系不就乱了吗。为了保证主外键关系,Hibernate在这种情况下会再执行两条update语句来更改STUDENT表中两个新插入记录的CLASS_ID字段,当然,这时CLASS_ID字段的取值是从c1对象中直接取得,而不再是s1.getClass().getID()方式了。
如果我们将Class类映射文件的<set>元素中的inverse属性修改为true,这就是告诉Hibernate:Class类不维护主外键关系了,这个任务就交给了Student类。于是,我们再执行上面的代码,Hibernate就会只执行三条insert语句,而不会执行任何update语句。因为Hibernate会通过Student类的s1.getClass().getID()和s2.getClass().getID()来确定CLASS_ID字段的值。
故,为了节省数据库资源,省却不必要的update语句,我们一般建议在一对多双向关联关系中,将一方的inverse属性设置为true,即将主外键的关系交由多方来维护。
打个比方:在一个公司中,是老板认识所有的员工容易,还是所有员工认识老板容易?
我是一个Hibernate的初学者,前两天刚刚研究了一下inverse属性,有所心得。写了这么多东西,希望能对你有所帮助。
分享到:
相关推荐
`Inverser-master` 文件夹很可能包含了一个用 Java 实现的项目,该项目利用 Swing 创建了用户界面,允许用户输入矩阵并计算其逆矩阵。在这样的程序中,用户界面可能会包含文本框或表格来输入矩阵元素,以及按钮来...
Mylist类包含了对链表的各种操作,如添加元素(addTail)、逆序(Inverser)、排序(Sort)、价格变动(New)和输出(Output)等方法。 链表作为一种动态数据结构,允许在任意位置进行插入和删除操作,相比顺序表更灵活。在...
- 逆序存储图书信息,并将结果写入`book_inverser.txt`。 - 按价格升序排序图书信息,并保存到`book_sort.txt`。 - 修改图书价格,根据条件执行不同的价格提升策略,然后写入`book_new.txt`。 在提供的部分代码中,...
10. 将图书列表按相反顺序存储,结果写入`book_inverser.txt`文件。 实验还提供了一个可选部分,包括: 1. 按图书价格排序,将结果以(定价、图书编号、图书标题)格式保存至`book_sort.txt`。 2. 实现一元多项式...
- **逆序存储**:反向存储图书信息,并写入`book_inverser.txt`。 此外,实验还提供了可选任务,如按照图书价格排序并输出到`book_sort.txt`,以及实现一元多项式的加法、减法和乘法操作。这里涉及到了排序算法和...
最后再建立一个属性“eated”(被吃),它是属性“eat”的逆关系, 在右下角“Inverser”框中选择“eat”属性。 步骤 7: 建立 Branch 类 建立“owl:Plant”的子类“Branch”(树枝),并附加限制条件。在选择...
以下是一些关键术语及其对应的中文解释: 1. **速度 (Geschwindigkeit)**: 描述物体在单位时间内移动的距离。 2. **动量 (Bewegungsgroesse)**: 物体的质量与其速度的乘积,是物体运动状态的量度。 3. **摩擦 ...
2. **反向电流(inverser Strom gegenstrom)**:在某些电子元件如二极管中,电流反向流动的现象。 3. **结构分析(strukturanalyse)**:分析机械结构的稳定性、强度和刚度的方法。 4. **自由度(Freiheitsgrad)**...