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>{// ...
随机推荐
- idea中编译项目报错 java: javacTask: 源版本 1.8 需要目标版本 1.8
问题如上面所叙: > idea中编译项目报错 java: javacTask: 源版本 1.8 需要目标版本 1.8 解决方案: > Setting->Compiler->Ja ...
- Java对象序列化
Java 1.1增添了一种有趣的特性,名为“对象序列化”(Object Serialization).它面向那些实现了Serializable接口的对象,可将它们转换成一系列字节,并可在以后完全恢复回 ...
- Ext JS 6学习文档–第1章–ExtJS入门指南
Ext JS 入门指南 前言 本来我是打算自己写一个系列的 ExtJS 6 学习笔记的,因为 ExtJS 6 目前的中文学习资料还很少.google 搜索资料时找到了一本国外牛人写的关于 ExtJS ...
- Linux+Nginx+Asp.net Core部署
上篇<Docker基础入门及示例>文章介绍了Docker部署,以及相关.net core 的打包示例.这篇文章我将以oss.offical.site站点为例,主要介绍下在linux机器下完 ...
- PHP生成随机水印图片
基于PHP的GD图形库,自己生成一张图片.仅限初识GD库,实例学习. 一.需求 网站的布局用到了类似慕课网课程列表的风格,每一个课程是一个banner图,图下面是标题加简介.因为课程的数量较大没有为所 ...
- 给IIS添加网站配置权限
1.新建一个网站,填好名字,路径和主机名端口等等 2.为网站添加一个用户 3.用户隶属于Guests,和IIS_IUSRS 4.把网站的完全控制权限赋给刚才的用户. 在网站右键--编辑权限--安全 或 ...
- geoR文档翻译
说来惭愧,很久没有更新自己的博客了.期间个人生活经历了很多变故,心理上的打击尤甚.加之没有取得好的科研成果,痛定思痛,还是下苦功夫多多学习. 最近对比验证各种方法的插值精度,用到了R语言地统计学包,由 ...
- css-dialog样式实现弹框蒙层全屏无需JS计算高度兼容IE7
<!DOCTYPE html><html><head> <meta charset="UTF-8"> <title> ...
- Linux 下使用网易的SMTP服务器 发送邮件
最近在研究服务器高可用集群 (HA)…… 尝试配置keepalived, 却发现其全局配置(global_defs )中发送邮件的SMTP服务器配置只有简单 smtp_server 一个选项. 那么, ...
- 分布式文件管理系统_FastDFS集群
简单介绍 1,client storage tracker的关系 先用一幅图来解释用户如何访问一个通过DFS管理的文件 一般来说,一台服务器只有一个storage server,多个storage s ...