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

多对多关系以介绍

上一节讨论了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属性简化操作
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值