1、Hibernate关联关系,2,主题,多对一/一对多 一对一 多对多 各种关联关系映射策略的选择 对cascade的理解 对inverse的理解,3,一、多对一(一对多),多对一 最常见的关联关系 反向,即为“一对多”关系 域(对象)模型 订单,产品 学生,班级 公民,国家 职员,部门 乘客,班机,4,多对一:关系模型,订单项表,Id itemName orderId,01 漂柔洗发水200ml装 0001,02 立白洗衣粉500g装 0001,订单表,Id orderDate customerName,0001 20090202 梁超君,0002 20090202 张三,关系模型 外键:在多
2、的一方,增加一外键,指向一方的主键 第三方表:两方的主键,组成第三方表(极少这样做),5,使用外键关联-例子,因为类型order属性的类型为Order,与表中外键orderId不匹配,因此不能用普通 的标签映射,要用标签映射. name:待持久化类的属性名 column:持久化的属性对应的表外键 class:此属性,对应的持久化类 not-null: 默认为false,true时,为此外键,设置not-null约束.会影响生成的表的schema,同时影响hibernate运行时的行为,会在保存时,先检查order属性,是否为null,Product端,6,一端,name:待持久化为的属性名 c
3、ascade:级联操作 Inverse: 为true时,禁止在本端维护关系.key:设定与所关联持久化类对应的表外键 (双向时,两边设的外键列名要对应) one-to-many:设定所关联的持久化类,7,使用第三方表关联-例子,Order端Product端,8,对inverse理解,Hibernate: insert into orderForm (orderNo, customerName, id) values (?, ?, ?) Hibernate: insert into Product (productNo, productName, orderId, id) values (?,
4、?, ?, ?),Hibernate: insert into Product (productNo, productName, orderId, id) values (?, ?, ?, ?) Hibernate: insert into orderForm (orderNo, customerName, id) values (?, ?, ?) Hibernate: update Product set orderId=? where id=?,留意元素中的inverse属性,该属性表示关联关系由哪一方进行维护。 所谓关联关系的维护就是说外键插入/或第三方表插入由谁来控制。如多对一关系中,
5、若由一端进行控制时,意味着在多端的表插入数据时,不会考虑其外键引用,直接在外键插入null值,一端插入数据时,再执行更新操作(此时外键不能设约束为not nul).如:反之,则在多端进行控制,在多端的表插入数据时, 直接插入其外键值.如:,9,注意 不管在哪一端控制,都是在程序中写了相应代码,才会发生. 默认inverse都为false(两端都可维护关系) 对于,一对多(多对一)来说,在多端的维护关系,是不能禁止的,因为中并不能设置inverse。另外:在“多对一”关系中,在一端维护关系,会导致性能低下,因为会产生多余的SQL语句。 所以可以在多端中设置inverse=true,避免这种情况发
6、生。,10,Inverse设置 inverse=false的一端端有责任维护关系 而inversetrue端无须维护关系。是将“维护关系”反转给另一方Inverse可在哪些标签中设置? inverse的设置位置,set,join (外键,第三方表)双向关联中双方都设置inversefalse的话,必会导致双方都重复更新同一个关系。 但是如果双方都设立inversetrue的话,双方都不维护关系的更新,这也是不行的。,11,Inverse例子,程序代码中,可在两端同时维护关系,这样做,会产生多余重复的SQL,影响性能.我们可能过inverse标签,限定,只在一端维护关系,product.setO
7、rder(order); /多端维护 order.setProduct(productSet); /一端维护 或 product.setOrder(order); /多端维护 order.getProduct().add(product) /一端维护当没有设inverse=true时,会发出类似如下的重复SQL语句: Hibernate: update Product set productNo=?, productName=?, orderId=? where id=? Hibernate: update Product set orderId=? where id=?,12,Insvers
8、e在各种关系中的应用,一对多/多对一关系中: 一般在一端,通过inverse=true,反转给”多端”维护关系 在多端的维护关系,是不是能禁止的,因为中并不能设置inverse而对于,一对一,多对多,在哪一方维护关系,都差不多。 两端,默认都为false 向关联中可设置一端为inversetrue,另一端为inversefalse。不要两端都设置为true,否则,都不维护关系 或者两端,都保留默认的设置inverse=false,在程序中注意,不要写重复的维护关系代码,则可。,13,单向与双向问题,不管哪种关联关系,都存在着单双向问题 是否要实现双向关联,要基于业务需求的考虑. 单向关联:只从
9、一方关联到另一方(只能从一方导航到另一方) 双向关联:可双向导航,双向关联其实是指双方都可以取得对方的应用,14,二、一对一,域(对象)模型 公民,身份证 学生信息,学籍信息 一夫一妻制,15,关系模型,关系模型 主键映射:两表主键相同 主键关联不需要额外的表字段;如果两行是通过这种一对一关系相关联的,那么这两行就共享同样的主关键字值。所以如果你希望两个对象通过主键一对一关联,你必须确认它们被赋予同样的标识值! 唯一外键映射:一表增加外键,指向另一表的主键 加字段 第三方表映射:(很少这么做),16,关系模型,主键映射,公民表,Id 姓名 出生日期,01 梁超君 1981-04-08,02 张
10、三 1956-04-04,身分证表,Id 身分证号,01 440981198104084217,02 440956195604044218,17,唯一外键映射,公民表,Id 姓名 出生日期 cardID,01 梁超君 1981-04-08 001,02 张三 1956-04-04 002,身分证表,Id 身分证号,001 440981198104084217,002 440956195604044218,18,主键方式,实现关联-例子,Card端Person端, person,19,外键方式实现关联-例子,Person端Card端,20,三、多对多,域(对象)模型 角色,用户 菜单,权限 用户
11、组,用户 学员,兴趣班 课程,老师 协会,会员,21,关系模型,关系模型 第三方表:将两表主键,组成第三方表,用户表,Id userName other,01 梁超君,02 张三,角色表,Id roleName other,0001,0002,22,第三方表关联-例子,Role端User端,23,四、对cascade的理解,cascade作用 当前对象进相关”操作”时,会级联”操作”与它相关联的对象. cascade标签能用在哪里? 集合标签中,如set,list,map等 One-to-one Many-to-one级联风格(cascade style)是可组合的 ,24,cascade值,
12、25,有关cascade使用的建议,建议,级联功能,一般最好依业务需求,进行使用.如常见的父子关系,如果子对象的生命周期限定在父亲对象的生命周期之内,可通过指定cascade=“all,delete-orphan”将其变为自动生命周期管理的对象。 有些情况,可能根本不需要级联(cascade)。 级联(cascade)通常在 和关系中比较有用。 通常在或关系中应用级联(cascade)没什么意义。 是否父子关系,由业务需求确定的 如订单与客户,一个没有客户的订单,是没意义的. 而订单与产品关系时,产品不属于任何一个订单,也是合理的.在程序中,需然已设置了级联,但最好还明确进行相关操作,这样更安
13、全.而且程序逻辑更明确.,26,有关如何选择关联方式? 单向,多对一:宜用”基于外键的关联”, 在多端维护关系 单向,一对多:宜用“基于第三方表的关联” (为什么?) 双向多对一/双向一对多: 宜用“基于外键的关联”,并在多端维护关系(在一端用inverse=“true”,将维护关系权反转给多端)一对一单双向关联,可选用基于外键,或基于主键的关联极少会用第三方表关联单双向的多对多,都只能使用第三方表关联了,小结,27,有关inverse? 你仅仅需要记住下面这个直观的规则:所有的双向关联需要有一端被 设置为inverse。在一个一对多(one-to-many)关联中 它必须是代表多(many)的那端。而在多对多(many-to-many)关联 中,你可以任意选取一端,两端之间并没有差别。有关casecade,