初识Hibernate(三)之多表关系维护

来源:互联网 发布:javascript获取子元素 编辑:程序博客网 时间:2024/05/29 06:30

多对多关系以介绍

上一节讨论了Hibernate一对多关系的维护,这节讨论多对多关系的维护

在实际生活中,有很多多对多的例子:
比如老师和学生的关系.职员和职位的关系..等等.

由于多对多关系中不能在两个关系表中插入对应的主键作为外键,所以要新建一张表来维护两者的关系

我用支援和职位的背景作为Demo实例

数据库表与实体表的模型图

用户表的对应关系

这里写图片描述

角色表的对应关系

这里写图片描述

配置实体映射的文件

User的实体表

package com.tangbaobao.domain;import java.util.HashSet;import java.util.Set;/*** @author 唐学俊* @version 创建时间:2017年11月22日 下午1:56:49* */public class User {    /*CREATE TABLE `sys_user` (              `user_id` bigint(32) NOT NULL AUTO_INCREMENT COMMENT '用户id',              `user_code` varchar(32) NOT NULL COMMENT '用户账号',              `user_name` varchar(64) NOT NULL COMMENT '用户名称',              `user_password` varchar(32) NOT NULL COMMENT '用户密码',              `user_state` char(1) NOT NULL COMMENT '1:正常,0:暂停',              PRIMARY KEY (`user_id`)            ) ENGINE=InnoDB AUTO_INCREMENT=9 DEFAULT CHARSET=utf8;*/    private Long user_id;    private String user_code;    private String user_name;    private String user_password;    private Character user_state;    private Set<Role> roles = new HashSet<Role>();    public Set<Role> getRoles() {        return roles;    }    public void setRoles(Set<Role> roles) {        this.roles = roles;    }    public Long getUser_id() {        return user_id;    }    public void setUser_id(Long user_id) {        this.user_id = user_id;    }    public String getUser_code() {        return user_code;    }    public void setUser_code(String user_code) {        this.user_code = user_code;    }    public String getUser_name() {        return user_name;    }    public void setUser_name(String user_name) {        this.user_name = user_name;    }    public String getUser_password() {        return user_password;    }    public void setUser_password(String user_password) {        this.user_password = user_password;    }    public Character getUser_state() {        return user_state;    }    public void setUser_state(Character user_state) {        this.user_state = user_state;    }    @Override    public String toString() {        return "User [user_id=" + user_id + ", user_code=" + user_code + ", user_name=" + user_name + ", user_password="                + user_password + ", user_state=" + user_state + "]";    }}

1.User.hbm.xml

<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE hibernate-mapping PUBLIC     "-//Hibernate/Hibernate Mapping DTD 3.0//EN"    "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">    <hibernate-mapping package="com.tangbaobao.domain">        <class name="User" table="sys_user">            <id name ="user_id">                <generator class="native"></generator>            </id>            <property name="user_code"></property>            <property name="user_name"></property>            <property name="user_password"></property>            <property name="user_state"></property>            <!--                 name:集合属性名                table:配置中间表名                key                    column:外键:别人引用我                    class:我与那个类是多对多关系                    Many                     column:我引用别人的主键             -->            <!-- 多对多关系 -->            <set name="roles" table ="sys_user_role">                <key column="user_id"></key>                <many-to-many class="Role" column="role_id"></many-to-many>            </set>        </class>    </hibernate-mapping>

Role的实体表

package com.tangbaobao.domain;/*** @author 唐学俊* @version 创建时间:2017年11月22日 下午2:02:21* */import java.util.HashSet;import java.util.Set;public class Role {/*  CREATE TABLE `sys_role` (              `role_id` bigint(32) NOT NULL AUTO_INCREMENT,              `role_name` varchar(32) NOT NULL COMMENT '角色名称',              `role_memo` varchar(128) DEFAULT NULL COMMENT '备注',              PRIMARY KEY (`role_id`)            ) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=utf8;*/    private Long role_id;    private String role_name;    private String role_memo;    private Set<User> users = new HashSet<User>();    public Long getRole_id() {        return role_id;    }    public void setRole_id(Long role_id) {        this.role_id = role_id;    }    public String getRole_name() {        return role_name;    }    public void setRole_name(String role_name) {        this.role_name = role_name;    }    public String getRole_memo() {        return role_memo;    }    public void setRole_memo(String role_memo) {        this.role_memo = role_memo;    }    public Set<User> getUsers() {        return users;    }    public void setUsers(Set<User> users) {        this.users = users;    }}

2.配置Role.hbm.xml

<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE hibernate-mapping PUBLIC     "-//Hibernate/Hibernate Mapping DTD 3.0//EN"    "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">    <hibernate-mapping package="com.tangbaobao.domain">        <class name="Role" table="sys_role">            <id name ="role_id">                <generator class="native"></generator>            </id>            <property name="role_name"></property>            <property name="role_memo"></property>            <set name="users" table="sys_user_role" >            <key column="role_id"></key><!-- 别人引用我的 -->                <many-to-many class="User" column="user_id"></many-to-many>            </set>        </class>    </hibernate-mapping>

对多对多关系进行操作

package com.tangbaobao.test;/*** @author 唐学俊* @version 创建时间:2017年11月22日 下午6:20:58* */import org.hibernate.Session;import org.hibernate.Transaction;import org.junit.Test;import com.tangbaobao.domain.Role;import com.tangbaobao.domain.User;import com.tangbaobao.utils.HibernateUtils;public class Test4 {    @Test    public void fun1() {        //获得session        Session session = HibernateUtils.getSession();        //开始事务        Transaction tx = session.beginTransaction();//      ----------------------------------------------        //操作        //1.创建两个User        User user1 = new User();        user1.setUser_name("唐学俊");        User user2 = new User();        user2.setUser_name("唐丽");        //2创建两个Role        Role role1 = new Role();        role1.setRole_name("学生");        Role role2 = new Role();        role2.setRole_name("老师");        //3用户表达关系        user1.getRoles().add(role1);        user1.getRoles().add(role2);        user2.getRoles().add(role1);        user2.getRoles().add(role2);        //4角色表达关系        role1.getUsers().add(user1);        role1.getUsers().add(user2);        role2.getUsers().add(user1);        role2.getUsers().add(user2);        //5调用save方法保存        session.save(role2);        session.save(role1);        session.save(user1);        session.save(user2);//      ----------------------------------------------        //提交事务        tx.commit();    }    //为用户增加角色    @Test    public void fun2() {        //获得session        Session session = HibernateUtils.getSession();        //开始事务        Transaction tx = session.beginTransaction();//      ----------------------------------------------        //操作        //1.获得唐学俊角色        User user = session.get(User.class, 1L);        //2创建一个角色        Role role = new Role();        role.setRole_name("CEO");        //3将角色绑定用户        user.getRoles().add(role);        //4将角色转换为持久状态        session.save(role);//      ----------------------------------------------        //提交事务        tx.commit();    }    //为用户解除角色    @Test    public void fun3() {        //获得session        Session session = HibernateUtils.getSession();        //开始事务        Transaction tx = session.beginTransaction();//      ----------------------------------------------        //操作        //1.获得唐学俊        User user = session.get(User.class, 1L);        //2.获取角色        Role role = session.get(Role.class, 2L);        //3.将角色从用户中移除        user.getRoles().remove(role);//      ----------------------------------------------        //提交事务        tx.commit();    }}

存在问题

多对多关系中,由第三张表维护其中的关系,如果在配置其对应关系时都配置,则会出现主键重复
像这样
这里写图片描述

解决办法就是其中的一方放弃维护主键,这里有两种解决办法

1.在java程序取消设置一方的关系

2.在一方的xml文件中配置属性inverse,放弃维护主键

<set name="users" table="sys_user_role" inverse="true" >    <key column="role_id"></key><!-- 别人引用我的 -->    <many-to-many class="User" column="user_id"></many-to-many></set>

用cascade简化操作

casecade是设置级联属性操作,可以在对象持久化到数据库库中简化操作
比如在上面的示例可以写成这样

在Role.hbm.xml中设置role的级联属性

<set name="users" table="sys_user_role" inverse="true" cascade="save-update">    <key column="role_id"></key><!-- 别人引用我的 -->    <many-to-many class="User" column="user_id"></many-to-many></set>

java程序中的变化

//5调用save方法保存        session.save(role2);        session.save(role1);        //session.save(user1);        //session.save(user2);

总结

学习hibernate多表操作可以将两种关系归类总结为以下

  1. 确定业务表
  2. 新建实体表
  3. 配置实体表映射文件,并将配置信息加入到主配置文件中
  4. 根据需求配置inverse属性
  5. 根据需求配置cascade属性简化操作
原创粉丝点击