hibernate 多对多关系总结
hibernate中,对对象关系的映射处理估计是最让人迷惑和头疼的,特别是cascade和inverse属性的使用,不知已经杀死了我多少个脑细胞了,好记性永远比不上烂笔头,为了能节省自己的脑细胞,降低猝死的出现概率,暂且在此记录一下自己的学习内容,以便日后查阅:
实体对象关系说明:
1、用户类(user)->tb_pms_user
2、用户组(group)->tb_pms_group
其中,一个用户组可以包含多个用户,一个用户可以加入多个用户组,多对多关系。
Spring的配置文件:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:jee="http://www.springframework.org/schema/jee"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.0.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.0.xsd
http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-2.0.xsd"> <bean id="propertyConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="locations">
<list>
<value>/WEB-INF/deploy/pms/app-config/jdbc.properties</value>
</list>
</property>
</bean> <!-- 配置数据原 -->
<bean id="dataSource"
class="org.apache.commons.dbcp.BasicDataSource">
<property name="driverClassName"
value="com.mysql.jdbc.Driver">
</property>
<property name="url" value="jdbc:mysql://localhost:3306/pms"></property>
<property name="username" value="root"></property>
<property name="password" value="1qaz!QAZ"></property>
</bean> <!-- 配置session工厂 -->
<bean id="sessionFactory"
class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
<property name="dataSource">
<ref bean="dataSource" />
</property>
<property name="mappingResources">
<list>
<value>com/pms/entity/TbPmsGroup.hbm.xml</value>
<value>com/pms/entity/TbPmsUser.hbm.xml</value>
</list>
</property>
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">
org.hibernate.dialect.MySQLDialect
</prop>
<prop key="hibernate.show_sql">true</prop>
</props>
</property>
</bean>
<!-- spring jdbcTemplate -->
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<property name="dataSource" ref="dataSource"></property>
</bean> <!-- 事务管理器 -->
<bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<property name="sessionFactory">
<ref local="sessionFactory" />
</property>
</bean>
<!-- 事务代理拦截器的配置 -->
<bean id="baseTransactionProxy" abstract="true" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
<property name="transactionManager">
<ref bean="transactionManager" />
</property>
<property name="transactionAttributes">
<props>
<prop key="insert*">PROPAGATION_REQUIRED</prop>
<prop key="update*">PROPAGATION_REQUIRED</prop>
<prop key="delete*">PROPAGATION_REQUIRED</prop>
<prop key="*">PROPAGATION_REQUIRED,readOnly</prop>
</props>
</property>
</bean> <!-- 日志bean
<bean id="logSupport" class="com.shproject.log.impl.LogSupportImpl"/> <aop:config>
<aop:aspect id="addLog" ref="logSupport">
<aop:pointcut id="servicePointCut" expression="execution(* com.shproject.service.impl.*.* (..))"/>
<aop:after method="addLog" pointcut-ref="servicePointCut"/>
</aop:aspect>
</aop:config>
-->
<bean id="baseDao" class="com.pms.base.BaseDao">
<property name="sessionFactory">
<ref bean="sessionFactory"/>
</property>
<property name="jdbcTemplate">
<ref bean="jdbcTemplate"/>
</property>
</bean> <bean id="userDao" class="com.pms.dao.impl.TbPmsUserDaoImpl" parent="baseDao">
</bean> <bean id="groupDao" class="com.pms.dao.impl.TbPmsGroupDaoImpl" parent="baseDao">
</bean> <bean id="userService" class="com.pms.service.impl.UserServiceImpl">
<property name="userDao">
<ref bean="userDao"/>
</property>
</bean> <bean id="groupService" class="com.pms.service.impl.GroupServiceImpl">
<property name="groupDao">
<ref bean="groupDao"/>
</property>
</bean> </beans>
实体类及映射文件:
TbPmsUser.hbm.xml
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<!-- Generated 2013-7-22 10:23:27 by Hibernate Tools 3.2.4.GA -->
<hibernate-mapping>
<class name="com.pms.entity.TbPmsUser" table="tb_pms_user">
<id name="userid" type="string" column="F_USERID">
<generator class="uuid.hex" />
</id>
<property name="name" type="string" column="F_NAME"> </property>
<property name="email" type="string" column="F_EMAIL"> </property>
<property name="mobile" type="string" column="F_MOBILE"> </property>
<property name="password" type="string" column="F_PASSWORD"> </property>
<property name="flag" type="java.lang.Integer" column="F_FLAG"> </property>
<property name="registertime" type="date" column="F_REGISTERTIME"> </property>
<property name="lastlogin" type="date" column="F_LASTLOGIN"> </property>
<property name="areaid" type="string" column="F_AREAID"> </property>
<property name="levelId" type="java.lang.Integer" column="F_LEVEL_ID"> </property>
<property name="hostid" type="string" column="F_HOSTID"> </property>
<property name="islock" type="java.lang.Integer" column="F_ISLOCK"> </property>
<property name="lockdatebegin" type="date" column="F_LOCKDATEBEGIN"> </property>
<property name="ifSuperuser" type="string" column="IF_SUPERUSER"> </property>
<property name="lastmodify" type="date" column="F_LASTMODIFY"> </property> <set name="groups" table="tb_pms_user_group" cascade="none" inverse="false">
<key column="F_USERID"/>
<many-to-many column="F_GROUPID" class="com.pms.entity.TbPmsGroup"/>
</set>
</class>
</hibernate-mapping>
TbPmsGroup.hbm.xml
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<!-- Generated 2013-7-22 10:23:27 by Hibernate Tools 3.2.4.GA -->
<hibernate-mapping>
<class name="com.pms.entity.TbPmsGroup" table="tb_pms_group">
<id name="groupid" type="string" column="F_GROUPID">
<generator class="uuid.hex" />
</id>
<property name="groupname" type="string" column="F_GROUPNAME">
</property>
<property name="flag" type="java.lang.Integer" column="F_FLAG">
</property>
<property name="areaId" type="string" column="F_AREA_ID">
</property>
<property name="groupdesc" type="string" column="F_GROUPDESC">
</property> <set name="users" table="tb_pms_user_group" lazy="true" inverse="false" cascade="none">
<key column="F_GROUPID"/>
<many-to-many column="F_USERID" class="com.pms.entity.TbPmsUser"/>
</set> </class>
</hibernate-mapping>
关于casecad
cascade属性并不是多对多关系一定要用的,有了它只是让我们在插入或删除对像时更方便一些,只要在cascade的源头上插入或是删除,所有 cascade的关系就会被自己动的插入或是删除。便是为了能正确的cascade,unsaved-value是个很重要的属性。Hibernate通 过这个属性来判断一个对象应该save还是update,如果这个对象的id是unsaved-value的话,那说明这个对象不是 persistence object要save(insert);如果id是非unsaved-value的话,那说明这个对象是persistence object(数据库中已存在),只要update就行了。saveOrUpdate方法用的也是这个机制。
关于inverse
inverse属性主要是用来说明两个模型间的关系究竟该怎么维护的,为true时说明两者的关系由对方去维护,为false时说明关系由自己维护,默认是false的,就是说关系的两端都来维护关系。这个意思就是说,如有一个Student,Teacher和TeacherStudent表,Student和Teacher是多对多对多关系,这个关系由TeacherStudent这个表来表现。那么什么时候插入或删除TeacherStudent表中的记录来维护关系呢?在用hibernate时,我们不会显示的对TeacherStudent表做操作。对TeacherStudent的操作是hibernate帮我们做的。hibernate就是看hbm文件中指定的是"谁"维护关系,那个在插入或删除"谁"时,就会处发对关系表的操作。前提是"谁"这个对象已经知道这个关系了,就是说关系另一头的对象已经set或是add到"谁"这个对象里来了。前面说过inverse默认是false,就是关系的两端都维护关系,对其中任一个操作都会处发对表系表的操作。当在关系的一头,如Student中的bag或set中用了inverse="true"时,那就代表关系是由另一关维护的(Teacher)。就是说当这插入Student时,不会操作TeacherStudent表,即使Student已经知道了关系。只有当Teacher插入或删除时才会处发对关系表的操作。所以,当关系的两头都用inverse="true"是不对的,就会导致任何操作都不处发对关系表的操作。当两端都是inverse="false"或是default值是,在代码对关系显示的维护也是不对的,会导致在关系表中插入两次关系。
在一对多关系中inverse就更有意义了。在多对多中,在哪端inverse="true"效果差不多(在效率上)。但是在一对多中,如果要一方维护关 系,就会使在插入或是删除"一"方时去update"多"方的每一个与这个"一"的对象有关系的对象。而如果让"多"方面维护关系时就不会有update 操作,因为关系就是在多方的对象中的,直指插入或是删除多方对象就行了。当然这时也要遍历"多"方的每一个对象显示的操作修关系的变化体现到DB中。不管 怎样说,还是让"多"方维护关系更直观一些。
(1)对one-to-many而言,改变set,会让hibernate执行一系列的update语句, 不会delete/insert数据
(2)对many-to-many而言,改变set,只修改关系表的数据,不会影响many-to-many的另一方。
(3)虽然one-to-many和many-to-many的数据库操作不一样,但目的都是一个:维护数据的一致性。
另记:在进行Delete和updete操作时,要先把对象get出来使其从脱管态转到持久态,这样才能对其进行操作。
hibernate 多对多关系总结的更多相关文章
- Hibernate多对多关系映射(建表)
下边讲述Hibernate多对多关系映射. 多对多关系的表的结构为: 两个实体表,还包含一个关系表,关系表为复合主键,如果要使用Hibernate多对多关系映射,则关系表必须只包含两个字段,如果生成了 ...
- 菜鸟学习Hibernate——多对多关系映射
Hibernate中的关系映射,最常见的关系映射之一就是多对多关系映射例如用户与角色的关系,一个用户对应多个角色,一个角色对应多个用户.如图: Hibernate中如何来映射这两个的关系呢? 下面就为 ...
- Hibernate多对多关系映射
两张表的多对多关系,在数据库中通常是通过第三张中间表来实现的,第三张中间表放的是两张表各自的主键值,通过主键与主键的对应来体现表直接的关系.比如在权限系统中,一个用户可以拥有多种权限,而一种权限也可以 ...
- hibernate多对多关系配置
一.创建用户,角色实体类. 一名用户可以有多个角色.一个角色可以对于多名用户. 用户实体类 public class User { private int uId; private String uN ...
- Hibernate 多对一关系中,在多的一方进行数据的插入
先看两个映射关系: 部门: <?xml version="1.0"?> <!DOCTYPE hibernate-mapping PUBLIC "-//H ...
- hibernate多对多关系
package com.manytomany; import java.util.HashSet; import java.util.Set; public class Student { priva ...
- 12.Hibernate多对多关系
JavaBean的编写 Person private long pid ; private String name ; private Set<Role> roles = new Hash ...
- Hibernate学习第三天(2)(多对多关系映射)
1.1.1 Hibernate多对多关系的配置 1.1.1.1 创建表 l 用户表 CREATE TABLE `sys_user` ( `user_id` bigint(32) NO ...
- 如何决解项目中hibernate中多对多关系中对象转换json死循环
先写一下原因吧!我是写的SSH项目,在项目中我遇到的问题是把分页对象(也就是pageBean对象)转化为json数据,下面为代码: public class PageBean <T>{// ...
随机推荐
- Yii2 Pjax 与 ActionForm ,不刷新提交数据
<?php yii\widgets\Pjax::begin(['id'=>'phoneDetail']);?> <?php $form = ActiveForm::begin( ...
- MySQL查看修改存储引擎总结
文总结了MySQL下查看.修改存储引擎的一些方法.测试.验证环境为MySQL 5.6 1:查看MySQL的存储引擎信息 1.1 使用show engines命令. .csharpcode, .csha ...
- iOS网络编程笔记——XML文档解析
今天利用多余时间研究了一下XML文档解析,虽然现在移动端使用的数据格式基本为JSON格式,但是XML格式毕竟多年来一直在各种计算机语言之间使用,是一种老牌的经典的灵活的数据交换格式.所以我认为还是很有 ...
- JavaWeb之多语言国际化
这周打算把国际化.JDBC和XML学习一下,从下周就开始学习三大框架,再坚持一个半月吧就能入门JavaWeb了,上周周末两天过的真是生不如死,两天坐在家里,醒来就写博客,原本在公司也自己操作了一遍,其 ...
- Java标准注释配置
eclipse中java文件头注释格式设置 windows->preferences->java->Code Templates->comments->Type-> ...
- Linux之uniq命令
uniq - report or omit repeated lines 省去重复的行 参数: -i 忽略大小写字符的不同 -c 对重复的行进行记数 注意:uniq命令只会对相邻的重复的行进行去 ...
- ASP.NET MVC制作404跳转(非302和200)
前言:距离上次发文已经有几个月了! 这段时间李,制作了一个博客网站,现将博客文章选一些发表到博客园,顺便为自己网站打一下广告! 产生404的原因主要有以下: 1.浏览器和爬虫:某些浏览器会请求网站的f ...
- 浅谈对java中传参问题的理解
之前用的c/c++比较多,在c/c++中对于传参类型,无外乎就是传值.传引用.传指针这几种.但在java中,由于没有指针类型,其传参的方式也发生了相应的变化.在网上找了找,按我之前的理解,java中传 ...
- 用代码控制退出APP
+ (void)exitApplication { AppDelegate *app = [UIApplication sharedApplication].delegate; UIWindow *w ...
- [SinGuLaRiTy] 最短路计算代码库
[SinGuLaRiTy-1002] Copyright (c) SinGuLaRiTy 2017. All Rights Reserved. Dijkstra: 题目描述 有向图的单源点最短路问题( ...