问题描述
首先想问一下,系统的用户和角色关系一般是不是多对多的关系呢?本人之前未做过,所以不甚了解~!其次,我现在假定的是多对多双向的关系,(单向也行),现在就出现了问题:三张表:user,role,user_role关联关系:cascade=all保存用户user的时候,hibernate会自动在三张表中都插入一条记录,这就不合要求了,角色表一般都不会随意更改的,更不能在增加一个用户的时候就在角色表里面插入一条数据吧~!如果把关联关系cascade设置为none,hibernate又会报错,意思是说我在保存用户的时候要先保存role,但是我的role是一个瞬时对象,导致插入role表出错,结果就是user插入了,关联表和role表都没插入,并且后台报错~!我想的就是,增加一个用户的时候,向用户表增加一条记录,然后在中间表中对应插入多条(插入数目由选择的角色数目确定),角色表不改变,角色表的作用最好是只在增加用户的时候列出可用的角色列表即可~!我知道这个功能,使用硬编码手动存储应该也可以实现,但是我觉得hibernate应该有这样的功能,并且手动存储也不利于数据库设计能力的提升吧~!求高手指点~!或者其他方式也可~!分不多,见谅!~
解决方案
解决方案二:
很明显是多对多的关系假设user:id,namerole:id,nameuser_role:id,user_id,role_id;这样就实现了多对多的关系,一个用户可以有多个角色,一个角色对应多个用户你插入一个用户的时候,只需要向user_role表中插入数据就可以了也就是说你说的那种是可以实现的,那么这个时候需要看你的hibernate如何配置啦User类:publicintid;publicStringname;privateList<Role>roles;//在其set方法上添加注解@oneToManyRole:intid,intname;List<User>users//在set方法上添加注解@oneToMany我想这样应该可以解决你的问题
解决方案三:
引用1楼zy353003874的回复:
很明显是多对多的关系假设user:id,namerole:id,nameuser_role:id,user_id,role_id;这样就实现了多对多的关系,一个用户可以有多个角色,一个角色对应多个用户你插入一个用户的时候,只需要向user_role表中插入数据就可以了也就是说你说的那种是可以实现的,那么这个时候需要看你的hibernate如何配置啦User类:publicintid;publicStringname;privateList<Role>roles;//在其set方法上添加注解@oneToManyRole:intid,intname;List<User>users//在set方法上添加注解@oneToMany我想这样应该可以解决你的问题
刚试了一下,还是会在三个表中都插入~!不知道是不是我写的有问题People类:privateSet<RoleInfo>peopleRole=newHashSet<RoleInfo>();hbm<setname="peopleRole"table="people_role"lazy="true"><keycolumn="peoplecode"/><many-to-manycolumn="roleId"class="RoleInfo"unique="true"/></set>role:privateSet<XPeople>rolePeople=newHashSet<XPeople>();hbm不配置action中:xpeople.getPeopleRole().add(roleInfo);registerService.save(xpeople);就是从页面拿到roleInfo对象(包含用户选择的角色的id),在赋给xpeople,存储xpeople,结果存入了三个表。。。
解决方案四:
这么晚了都还不睡觉
解决方案五:
配置一下<setname="rolePeople"table="role_people"lazy="true"><keycolumn="rolecode"/><many-to-manycolumn="peopleId"class="People"unique="true"/></set>
解决方案六:
你把它的sql语句打印出来看看呢?
解决方案七:
把你的unique去掉
解决方案八:
一般多对多都分解成多对一和一对多来处理
解决方案九:
引用5楼zy353003874的回复:
你把它的sql语句打印出来看看呢?
打印出来就是三个insert....单向双向都试了cascade也配过了inverse也配过了unique也配过了难道多对多要么只插入一个主表,要么就插入三个表?不能只插入一个主表一个中间表吗?~!?
解决方案十:
我们重新来理一下问题吧,你是想要实现manytomany单向还是双向,如果是单向,我用注解来给你举个例子拿学生和老师之间的关系来举一个例子哈!Teacher:privateSet<Student>students;@ManyToMany@JoinTable(name="t_s",joinColumns={@JoinColumn(name="t_id")},inverseJoinColumns={@JoinColumn(name="s_id")})/*t_s,表示生成外键表的名字,joinColumns表示和teacher表中id对应的字段,之所以是数组有可能某个表示联合主键inverseJoinColumns表示和student表中id对应的字段*/publicSet<Student>getStudents(){returnstudents;}Student:@EntitypublicclassStudent{privateintid;privateStringname;@Id@GeneratedValuepublicintgetId(){returnid;}}
如果是双向的话:ManyToMany双向:Teacher类如上不改变Student:privateSet<Teacher>teachers;@ManyToMany(mappedBy="students")publicSet<Teacher>getTeachers(){returnteachers;}
采用配置文件的方式:单向:xml映射:Teacher.hbm.xml文件映射:<hibernate-mappingpackage="cn.study.domain"><classname="Teacher"><idname="id"><generatorclass="native"></generator></id><propertyname="name"></property><!--key中的column表示对应于当前这个类(即Teacher)的id的那一列叫什么名字--><setname="students"table="t_s"><keycolumn="t_id"></key><many-to-manyclass="Student"column="s_id"></many-to-many></set></class></hibernate-mapping>
双向:xml映射:Teacher.hbm.xml内容如单向:Student.hbm.xml更改如下:<setname="teachers"table="t_s"><keycolumn="s_id"></key>//相对于本类,即Student<many-to-manyclass="Teacher"column="t_id"></many-to-many></set>
解决方案十一:
其实很简单,你已经想到了级联。user_role里不要设置级联。user和role设置级联
解决方案十二:
引用9楼zy353003874的回复:
我们重新来理一下问题吧,你是想要实现manytomany单向还是双向,如果是单向,我用注解来给你举个例子拿学生和老师之间的关系来举一个例子哈!Teacher:privateSet<Student>students;@ManyToMany@JoinTable(name="t_s",joinColumns={@JoinColumn(name="t_id")},inverseJoinColumns={@JoinColumn(name="s_id")})/*t_s,表示生成外键表的名字,joinColumns表示和teacher表中id对应的字段,之所以是数组有可能某个表示联合主键inverseJoinColumns表示和student表中id对应的字段*/publicSet<Student>getStudents(){returnstudents;}Student:@EntitypublicclassStudent{privateintid;privateStringname;@Id@GeneratedValuepublicintgetId(){returnid;}}如果是双向的话:ManyToMany双向:Teacher类如上不改变Student:privateSet<Teacher>teachers;@ManyToMany(mappedBy="students")publicSet<Teacher>getTeachers(){returnteachers;}
采用配置文件的方式:单向:xml映射:Teacher.hbm.xml文件映射:<hibernate-mappingpackage="cn.study.domain"><classname="Teacher"><idname="id"><generatorclass="native"></generator></id><propertyname="name"></property><!--key中的column表示对应于当前这个类(即Teacher)的id的那一列叫什么名字--><setname="students"table="t_s"><keycolumn="t_id"></key><many-to-manyclass="Student"column="s_id"></many-to-many></set></class></hibernate-mapping>
双向:xml映射:Teacher.hbm.xml内容如单向:Student.hbm.xml更改如下:<setname="teachers"table="t_s"><keycolumn="s_id"></key>//相对于本类,即Student<many-to-manyclass="Teacher"column="t_id"></many-to-many></set>
先谢谢你耐心的回答!我现在的情况和你给的例子的配置是一样的,多对多,单向双向都试过,cascade加与不加我也试过,就比如以你的配置,我在页面添加用户,后台这么写//前台的bean有两个//xpeople表示用户基本信息//roleInfo表示用户勾选的角色信息,//roleInfo和XPeople是多对多xpeople.getPeopleRole().add(roleInfo);registerService.save(xpeople);这个时候如果我设置了级联关系cascade="all",那么save完成之后会出现insertintopeopleInfo.....insertintopeople_role....insertintoroleinfo....这样就在角色表里面插入数据了,不行如果不设定级联hibernate会报错,说我指向了一个瞬时对象,实际就是说我保存用户时关联了角色,需要先保存角色,再保存用户,但是由于我没有设置级联,所以保存就报错~最后的结果就是,只插入了peopleinfo,其余的两个没有改变--因为报错如果我不设定级联,为了消除上面的错误,这么写xpeople.getPeopleRole().add(roleInfo);registerService.saveRole(roleInfo);registerService.save(xpeople);效果也是会在角色表里面插入数据,因为是我自己保存了!最后的结果就是,设定级联要么插三个表,要么只插一个表!!!不好使啊!!!
解决方案十三:
引用10楼x0516的回复:
其实很简单,你已经想到了级联。user_role里不要设置级联。user和role设置级联
你说的不是很理解首先我不能在role里面插入数据,所以如果user和role设置了级联,那么不就是我现在的情况吗--插入user会级联插入role!所以我觉得应该是user和user_role设定级联,保存user,也保存user_role,而role不用插入数据,只需要起到一个提供数据参考的作用!!!是这样吗?能实现吗?求指点
解决方案十四:
引用11楼seguzhizi的回复:
Quote: 引用9楼zy353003874的回复:
我们重新来理一下问题吧,你是想要实现manytomany单向还是双向,如果是单向,我用注解来给你举个例子拿学生和老师之间的关系来举一个例子哈!Teacher:privateSet<Student>students;@ManyToMany@JoinTable(name="t_s",joinColumns={@JoinColumn(name="t_id")},inverseJoinColumns={@JoinColumn(name="s_id")})/*t_s,表示生成外键表的名字,joinColumns表示和teacher表中id对应的字段,之所以是数组有可能某个表示联合主键inverseJoinColumns表示和student表中id对应的字段*/publicSet<Student>getStudents(){returnstudents;}Student:@EntitypublicclassStudent{privateintid;privateStringname;@Id@GeneratedValuepublicintgetId(){returnid;}}如果是双向的话:ManyToMany双向:Teacher类如上不改变Student:privateSet<Teacher>teachers;@ManyToMany(mappedBy="students")publicSet<Teacher>getTeachers(){returnteachers;}
采用配置文件的方式:单向:xml映射:Teacher.hbm.xml文件映射:<hibernate-mappingpackage="cn.study.domain"><classname="Teacher"><idname="id"><generatorclass="native"></generator></id><propertyname="name"></property><!--key中的column表示对应于当前这个类(即Teacher)的id的那一列叫什么名字--><setname="students"table="t_s"><keycolumn="t_id"></key><many-to-manyclass="Student"column="s_id"></many-to-many></set></class></hibernate-mapping>
双向:xml映射:Teacher.hbm.xml内容如单向:Student.hbm.xml更改如下:<setname="teachers"table="t_s"><keycolumn="s_id"></key>//相对于本类,即Student<many-to-manyclass="Teacher"column="t_id"></many-to-many></set>
先谢谢你耐心的回答!我现在的情况和你给的例子的配置是一样的,多对多,单向双向都试过,cascade加与不加我也试过,就比如以你的配置,我在页面添加用户,后台这么写//前台的bean有两个//xpeople表示用户基本信息//roleInfo表示用户勾选的角色信息,//roleInfo和XPeople是多对多xpeople.getPeopleRole().add(roleInfo);registerService.save(xpeople);这个时候如果我设置了级联关系cascade="all",那么save完成之后会出现insertintopeopleInfo.....insertintopeople_role....insertintoroleinfo....这样就在角色表里面插入数据了,不行如果不设定级联hibernate会报错,说我指向了一个瞬时对象,实际就是说我保存用户时关联了角色,需要先保存角色,再保存用户,但是由于我没有设置级联,所以保存就报错~最后的结果就是,只插入了peopleinfo,其余的两个没有改变--因为报错如果我不设定级联,为了消除上面的错误,这么写xpeople.getPeopleRole().add(roleInfo);registerService.saveRole(roleInfo);registerService.save(xpeople);效果也是会在角色表里面插入数据,因为是我自己保存了!最后的结果就是,设定级联要么插三个表,要么只插一个表!!!不好使啊!!!
insert三条语句是正确的呀?因为你一个人有了一个新的权限之后.,那么肯定是要更新表的呀,因为你XPeople中有一个list保存了RoelInfo的,同理其他也是的呀,要么就使用单向的