在领域模型中,类与类之间最普遍的关系就是关联关系,以Customer和Order为例:
一个customer能发出多个订单,而订单只能是属于一个用户。那么从order到 customer的关联关系是(N-1)的关联。从customer到order一对多的关联。
单向(N-1)关联:
该类型的关联只需要从N端到①端(也就是order到customer)。
域模型中:从order到customer的单向多对一关联关系需要在order类中定义一个customer属性,而在customer中无需定义存放order对象的集合属性。
关系数据模型:ORDERS表中的CUSTOMER_ID参照CUSTOMERS表的主键:
步骤:
1.建立Customer类:
2.建立Order类:
3.利用hibernate插件生成hbm.xml文件,一般来说 该文件可能会根据实际情况作修改。
对于hbm.xml文件来说:
① ID生成策略一半选择native。
②属性对应的数据字段名为带下划线的命名方式。
对于①端的配置由于是普通属性,那么可以不做修改,对于N端配置,普通属性也不用修改,但是在映射关联关系属性的时候需要注意:如下方式配置。
4.将hbm.xml文件添加到hibernate.cfg.xml文件的<mapping resource="路径">下中。
5.运行程序,由于在hibernate.cfg.xml文件中设置了自动生成数据表,那么程序运行就会创建ORDERS/CUSTOMER两张表。
下面我们分析测试类的运行过程:
1.执行save操作:
情况一:
先插入customer对象,再插入Order对象(也就是先插入①端的对象,再插入N端的对象,那么执行3条insert语句)
情况二:
先插入Order对象,再插入Customer对象(先插入N端对象,再插入①端对象)
跟情况一相同,均可以执行插入并成功。但是多出了两条update语句。
为什么呢?
因为在插入Order的时候,需要一个CUSTOMER_ID,但先执行save操作的时候是立即发送的SQL,此时并不知道该外键,后续当Customer插入之后,那么该外键在session中也就是存在的状态了,程序继续运行到Transaction.commit()的时候,会flush(),也就是提交前的冲刷过程,该过程会检查session缓存中对象的初始状态是否与现有状态不一致,显然在这里后来的customer对象的CUSTOMER_ID导致先前插入的Order对象发生变化,于是为了保持一致,执行两条update语句。
综上两种情况而言,由于我们对两个关联关系的对象save的顺序不一样,代码的执行过程也是不一样的,显然前者的效率较高。所以推荐使用先插入①端对象,再插入N端对象,以避免多余的update操作。
2.查询操作:
在需要使用到关联的对象的时候,才会发送对应的SQL语句。
//若此时session.close();那么会发生懒加载异常。
Customer customer = Order.getCustomer();
System.out.println(customer.getCustomerName());
其实在获取Order的时候,默认情况下,其关联的Customer对象在没有使用的时候是一个代理对象。
3.更新操作update
4.删除操作:
在不设定级联的情况下,且①端的对象有N端的对象在引用,那么便不能直接删除①端的对象。