首页 > 代码库 > hibernate 多对多 最佳实践

hibernate 多对多 最佳实践

首先 看我们的 ER 图 :涵盖了  一对一 ,一对多 ,多对多 的关系



对多 在 hibernate 中的 实现 :  一个 用户user ,拥有 多个角色 role; 一个 角色 属于 多个 用户user

其实 多对多 就 是双向的 一对多,我们使用一个 中间表 user_role 来保存 user ,role 的 主键,来 确定 它们的 关联关系,

减少 数据的低级冗余,提高 可扩展 性


User.java 及 映射文件

public class User implements java.io.Serializable {
    private static final long serialVersionUID = 1636556781734875928L;
    private Long id;
    private String username;
    private String password;
    private String state;
    private Date createTime;

    private IdCard idCard;
    private Set<UserLog> userLogs;
    private Set<Role> roles;
}
<?xml version="1.0"?>
<!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.eliteams.quick4j.test.study.hibernate.example">
    <class name="User" table="user">
        <id name="id" type="java.lang.Long">
            <column name="id" />
            <generator class="identity" />
        </id>
        <property name="username" type="string">
            <column name="username" length="50">
            </column>
        </property>
        <property name="password" type="string">
            <column name="password" length="64">
            </column>
        </property>
        <property name="state" type="string">
            <column name="state" length="32">
            </column>
        </property>
        <property name="createTime" type="timestamp">
            <column name="create_time" length="19">
            </column>
        </property>

        <one-to-one name="idCard" cascade="all">
        </one-to-one>

        <set name="userLogs" inverse="true" cascade="delete">
            <key column="user_id"></key>
            <one-to-many class="UserLog" />
        </set>

        <set name="roles" table="user_role" cascade="save-update">
            <key column="user_id"></key>
            <many-to-many column="role_id" class="Role"></many-to-many>
        </set>
    </class>
</hibernate-mapping>

Role.java 及 映射文件

import java.util.Set;

public class Role implements java.io.Serializable {
    private static final long serialVersionUID = -5094780060641842069L;
    private Long id;
    private String roleName;
    private String roleSign;
    private String description;
    private Set<User> users;
}
<?xml version="1.0"?>
<!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.eliteams.quick4j.test.study.hibernate.example">
    <class name="Role" table="role" catalog="quick4j">
        <id name="id" type="java.lang.Long">
            <column name="id" />
            <generator class="identity" />
        </id>
        <property name="roleName" type="string">
            <column name="role_name" length="32">
            </column>
        </property>
        <property name="roleSign" type="string">
            <column name="role_sign" length="128">
            </column>
        </property>
        <property name="description" type="string">
            <column name="description" length="256">
            </column>
        </property>

        <set name="users" table="user_role" inverse="true">
            <key column="role_id"></key>
            <many-to-many column="user_id" class="User"></many-to-many>
        </set>
    </class>
</hibernate-mapping>

多对多 最佳实践:

我们可以把 user 看成 主表, role 看成 从表;

在 主表 user 多对多中 设置  cascade="save-update" ,表明 在 新增或 更改 user 的 时候 会级联 操作role,



新增 一个 用户 user,和他的role, hibernate 是 先 插入 user , 在 插入 role ,然后再 中间表 添加 数据;

而在删除user 中 ,则 只删除中间表 和 user

 


这不正是我们想要的吗, 

我们 当然不想在 删除 一个 用户user  的时候 把 它 对应的 角色 role 删除,因为  这个 角色 role 可能 是其他 用户的 角色;

只要解除 关系 即可;

而在角色 role 中,我们设置 inverse="true" ,放弃维护 关系,因为 我们一般是 为 用户 user 分配 角色 role ,减少不必要的更新语句。


到这里 讲完了 一对一 ,一对多 ,多对多的关系  映射 及 一些比较好的 配置, 应该 根据 业务 ,灵活应用 hibernate ,hibernate 是 一个 非常 好的orm 映射框架,

在 我 看来 比 mybatis 更 灵活 , 更 高效 ,前提 是 你 要熟练 它, 后续 有时间会 将 一些 hibernate 优化 相关的 操作。


hibernate 多对多 最佳实践