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

如何编写ASS_USER_OFF_LOC表对应的JPA实体类

如何编写ASS_USER_OFF_LOC表对应的JPA实体类

我来帮你一步步实现这个实体类,结合你现有的实体结构和目标表的约束,下面是具体的方案和代码:

首先,先明确目标表的核心特性:

  • 主键是USER列(对应用户表的USER_ID),意味着每个用户只能有一条关联记录
  • 外键OFFICE和LOCAL联合关联到ASS_OFF_LOC表的复合主键(CODE_OFFICE和CODE_LOCAL)
  • 三个字段都不允许为NULL

实体类实现方案

我们可以创建名为AssUserOffLoc的实体类,下面是完整代码,同时我会逐段解释关键注解的作用:

import jakarta.persistence.*;
import java.io.Serializable;
import java.util.Objects;

@Entity
@Table(name = "ASS_USER_OFF_LOC")
public class AssUserOffLoc implements Serializable {

    private static final long serialVersionUID = 1L;

    // 方案1:直接将User作为主键(符合表的主键约束,每个用户一条记录)
    @Id
    @ManyToOne(fetch = FetchType.LAZY, optional = false)
    @JoinColumn(name = "USER", nullable = false, updatable = false)
    private User user;

    // 关联到AssOffLoc实体(通过联合外键OFFICE和LOCAL)
    @ManyToOne(fetch = FetchType.LAZY, optional = false)
    @JoinColumns({
        @JoinColumn(
            name = "OFFICE",
            referencedColumnName = "CODE_OFFICE",
            nullable = false
        ),
        @JoinColumn(
            name = "LOCAL",
            referencedColumnName = "CODE_LOCAL",
            nullable = false
        )
    })
    private AssOffLoc assOffLoc;

    // 无参构造方法(JPA要求必须提供)
    public AssUserOffLoc() {
        super();
    }

    // 便捷构造方法:通过User和AssOffLoc实例创建
    public AssUserOffLoc(User user, AssOffLoc assOffLoc) {
        this.user = user;
        this.assOffLoc = assOffLoc;
    }

    // Getter和Setter
    public User getUser() {
        return user;
    }

    // 用户主键不允许修改,所以setUser可以做限制,或者直接不提供(根据业务需求)
    public void setUser(User user) {
        // 因为主键不可修改,所以如果当前已有用户,不允许替换
        if (this.user != null) {
            throw new IllegalStateException("用户关联不可修改");
        }
        this.user = user;
    }

    public AssOffLoc getAssOffLoc() {
        return assOffLoc;
    }

    public void setAssOffLoc(AssOffLoc assOffLoc) {
        this.assOffLoc = assOffLoc;
    }

    // equals和hashCode:基于主键User(因为每个用户唯一一条记录)
    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        AssUserOffLoc that = (AssUserOffLoc) o;
        return Objects.equals(user, that.user);
    }

    @Override
    public int hashCode() {
        return Objects.hash(user);
    }
}

关键部分解释

  1. 主键设计:
    直接使用User实体作为@Id,完美匹配表的主键约束(每个用户仅一条记录)。updatable = false确保主键不会被意外修改,fetch = FetchType.LAZY启用懒加载,避免不必要的用户数据查询。

  2. 关联AssOffLoc实体:
    因为AssOffLoc的主键是复合键(办公室编码+本地编码),所以用@JoinColumns指定两个外键列:

    • OFFICE列关联到ASS_OFF_LOC表的CODE_OFFICE
    • LOCAL列关联到ASS_OFF_LOC表的CODE_LOCAL
      这样JPA就能正确识别联合外键,关联到AssOffLoc实体。
  3. 约束与业务规则:

    • optional = false和nullable = false对应表中的非空约束
    • setUser方法中添加了修改限制,符合“用户主键不可变更”的业务逻辑(因为每个用户只能有一条记录,一旦关联就不能换用户)

备选方案(显式映射用户ID主键)

如果你更倾向于直接映射数据库的USER列作为主键(而非实体对象),可以用下面的写法,核心逻辑一致:

@Entity
@Table(name = "ASS_USER_OFF_LOC")
public class AssUserOffLoc implements Serializable {

    private static final long serialVersionUID = 1L;

    @Id
    @Column(name = "USER", nullable = false, updatable = false)
    private long userId;

    @ManyToOne(fetch = FetchType.LAZY, optional = false)
    @JoinColumn(name = "USER", insertable = false, updatable = false, nullable = false)
    private User user;

    @ManyToOne(fetch = FetchType.LAZY, optional = false)
    @JoinColumns({
        @JoinColumn(name = "OFFICE", referencedColumnName = "CODE_OFFICE", nullable = false),
        @JoinColumn(name = "LOCAL", referencedColumnName = "CODE_LOCAL", nullable = false)
    })
    private AssOffLoc assOffLoc;

    // 无参构造方法
    public AssUserOffLoc() {
        super();
    }

    // 便捷构造方法
    public AssUserOffLoc(long userId, AssOffLoc assOffLoc) {
        this.userId = userId;
        this.assOffLoc = assOffLoc;
    }

    // Getter和Setter
    public long getUserId() {
        return userId;
    }

    public void setUserId(long userId) {
        if (this.userId != 0) {
            throw new IllegalStateException("用户ID不可修改");
        }
        this.userId = userId;
    }

    public User getUser() {
        return user;
    }

    public void setUser(User user) {
        if (user != null) {
            this.userId = user.getUserId();
        }
        this.user = user;
    }

    public AssOffLoc getAssOffLoc() {
        return assOffLoc;
    }

    public void setAssOffLoc(AssOffLoc assOffLoc) {
        this.assOffLoc = assOffLoc;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        AssUserOffLoc that = (AssUserOffLoc) o;
        return userId == that.userId;
    }

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

这种写法中,userId作为显式主键,user字段仅做关联查询用(insertable = false, updatable = false避免重复维护)。

备注:内容来源于stack exchange,提问作者paniko

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.13 19:17:59