You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在不使用@Mapsid的情况下用JPA Hibernate关联三个实体

不使用@MapsId实现JPA Hibernate三实体关联(Users、Roles、Project)

根据你的数据库设计,我们可以通过复合主键类+中间关联实体的方式,在不使用@MapsId注解的前提下完成三实体的关联映射。

1. 定义复合主键类

中间表has的主键由user_id、role_id、project_id组成,需要先创建一个可序列化的复合主键类:

import java.io.Serializable;
import java.util.Objects;

public class HasId implements Serializable {
    private Long userId;
    private Long roleId;
    private Long projectId;

    // JPA要求的无参构造器
    public HasId() {}

    public HasId(Long userId, Long roleId, Long projectId) {
        this.userId = userId;
        this.roleId = roleId;
        this.projectId = projectId;
    }

    // 复合主键必须实现equals和hashCode
    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        HasId hasId = (HasId) o;
        return Objects.equals(userId, hasId.userId) &&
                Objects.equals(roleId, hasId.roleId) &&
                Objects.equals(projectId, hasId.projectId);
    }

    @Override
    public int hashCode() {
        return Objects.hash(userId, roleId, projectId);
    }

    // getter和setter方法
    public Long getUserId() { return userId; }
    public void setUserId(Long userId) { this.userId = userId; }
    public Long getRoleId() { return roleId; }
    public void setRoleId(Long roleId) { this.roleId = roleId; }
    public Long getProjectId() { return projectId; }
    public void setProjectId(Long projectId) { this.projectId = projectId; }
}

2. 实现中间关联实体Has

这个实体映射到中间表,通过@EmbeddedId嵌入复合主键,同时手动关联三个主实体:

import javax.persistence.*;

@Entity
@Table(name = "has")
public class Has {
    @EmbeddedId
    private HasId id;

    @ManyToOne
    @JoinColumn(name = "user_id", insertable = false, updatable = false, referencedColumnName = "user_id")
    private Users user;

    @ManyToOne
    @JoinColumn(name = "role_id", insertable = false, updatable = false, referencedColumnName = "role_id")
    private Roles role;

    @ManyToOne
    @JoinColumn(name = "project_id", insertable = false, updatable = false, referencedColumnName = "project_id")
    private Project project;

    public Has() {}

    public Has(HasId id) {
        this.id = id;
    }

    // 手动维护主键与关联实体的绑定关系
    public void setUser(Users user) {
        this.user = user;
        if (id == null) id = new HasId();
        id.setUserId(user.getUserId());
    }

    public void setRole(Roles role) {
        this.role = role;
        if (id == null) id = new HasId();
        id.setRoleId(role.getRoleId());
    }

    public void setProject(Project project) {
        this.project = project;
        if (id == null) id = new HasId();
        id.setProjectId(project.getProjectId());
    }

    // getter和setter
    public HasId getId() { return id; }
    public void setId(HasId id) { this.id = id; }
    public Users getUser() { return user; }
    public Roles getRole() { return role; }
    public Project getProject() { return project; }
}

注:insertable = false, updatable = false是因为主键字段已由HasId维护,关联字段无需参与插入/更新操作。

3. 主实体双向关联配置(以Users为例)

在Users中添加@OneToMany实现与Has的双向关联,Roles和Project配置逻辑完全一致:

import javax.persistence.*;
import java.util.List;

@Entity
@Table(name = "users")
public class Users {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "user_id")
    private Long userId;

    // 你的其他字段,如username、password等
    private String username;
    private String password;

    @OneToMany(mappedBy = "user", cascade = CascadeType.ALL, orphanRemoval = true)
    private List<Has> hasList;

    public Users() {}

    // 便捷方法:快速添加/移除关联关系
    public void addHas(Has has) {
        hasList.add(has);
        has.setUser(this);
    }

    public void removeHas(Has has) {
        hasList.remove(has);
        has.setUser(null);
    }

    // 省略其他字段的getter/setter
    public Long getUserId() { return userId; }
    public void setUserId(Long userId) { this.userId = userId; }
    public String getUsername() { return username; }
    public void setUsername(String username) { this.username = username; }
    public String getPassword() { return password; }
    public void setPassword(String password) { this.password = password; }
    public List<Has> getHasList() { return hasList; }
    public void setHasList(List<Has> hasList) { this.hasList = hasList; }
}

4. 使用示例

// 创建基础实体
Users user = new Users();
user.setUsername("test_user");
user.setPassword("123456");

Roles role = new Roles();
role.setRoleName("PROJECT_ADMIN");

Project project = new Project();
project.setProjectName("Demo_Project");

// 创建关联关系
Has has = new Has();
has.setUser(user);
has.setRole(role);
has.setProject(project);

// 绑定到用户的关联列表
user.addHas(has);

// 持久化到数据库
entityManager.persist(user);
entityManager.persist(role);
entityManager.persist(project);
entityManager.persist(has);

内容的提问来源于stack exchange,提问作者Julen Amedo Gibaja

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.08 22:45:37