如何在没有无限递归的情况下获得实体映射?

Posted

技术标签:

【中文标题】如何在没有无限递归的情况下获得实体映射?【英文标题】:How can i get entity mapping without infinite recursion? 【发布时间】:2021-06-09 17:05:07 【问题描述】:

我有三个表和三个实体类。

CREATE TABLE public.users (
    id bigserial NOT NULL,
    email_address varchar(255) NOT NULL,
    password varchar(100) NOT NULL,
    "name" varchar(50) NOT NULL,
    phone_number varchar(15) NOT NULL,
    status int2 NULL DEFAULT 1,
    created_time timestamp(0) NULL DEFAULT now(),
    updated_time timestamp(0) NULL,
    image bytea NULL,
    user_type int2 NULL DEFAULT 0,
    CONSTRAINT users_pk PRIMARY KEY (id),
    CONSTRAINT users_un UNIQUE (email_address)
);

CREATE TABLE public.modules (
    id bigserial NOT NULL,
    "name" varchar(100) NOT NULL,
    description varchar(2000) NULL,
    status int2 NULL,
    CONSTRAINT modules_pk PRIMARY KEY (id),
    CONSTRAINT modules_un UNIQUE (name)
);

CREATE TABLE public.module_user_mapper (
    id bigserial NOT NULL,
    user_id int8 NOT NULL,
    module_id int8 NOT NULL,
    CONSTRAINT module_user_mapper_pk PRIMARY KEY (id)
);
ALTER TABLE public.module_user_mapper ADD CONSTRAINT modules_module_id_fkey FOREIGN KEY (module_id) REFERENCES modules(id);
ALTER TABLE public.module_user_mapper ADD CONSTRAINT modules_user_id_fkey FOREIGN KEY (user_id) REFERENCES users(id);

实体类

@Entity
@Table(name = "users")
@Data
@JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class, property = "id")
public class Users implements Serializable 

    private static final long serialVersionUID = 1L;
    
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Basic(optional = false)
    @Column(name = "id")
    private Long id;
    
    @Basic(optional = false)
    @NotNull
    @Size(min = 1, max = 255)
    @Column(name = "email_address")
    private String emailAddress;
    
    @Basic(optional = false)
    @NotNull
    @Size(min = 1, max = 100)
    @Column(name = "password")
    private String password;
    
    @Basic(optional = false)
    @NotNull
    @Size(min = 1, max = 50)
    @Column(name = "name")
    private String name;
    
    @Basic(optional = false)
    @NotNull
    @Size(min = 1, max = 15)
    @Column(name = "phone_number")
    private String phoneNumber;
    
    @Column(name = "status")
    private Short status;
    @Column(name = "created_time")
    @Temporal(TemporalType.TIMESTAMP)
    private Date createdTime;
    
    @Column(name = "updated_time")
    @Temporal(TemporalType.TIMESTAMP)
    private Date updatedTime;
    
    @Column(name = "image")
    private byte[] image;
    @Column(name = "user_type")
    private Short userType;
    
    @OneToMany(cascade = CascadeType.ALL, mappedBy = "userId")
    private Collection<ModuleUserMapper> moduleUserMapperCollection;


@Entity
@Table(name = "modules")
@Data
@JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class, property = "id")
public class Modules implements Serializable 

    private static final long serialVersionUID = 1L;
    
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Basic(optional = false)
    @Column(name = "id")
    private Long id;
    
    @Basic(optional = false)
    @NotNull
    @Size(min = 1, max = 100)
    @Column(name = "name")
    private String name;
    
    @Size(max = 2000)
    @Column(name = "description")
    private String description;
    
    @Column(name = "status")
    private Short status;
    
    @OneToMany(cascade = CascadeType.ALL, mappedBy = "moduleId")
    private Collection<ModuleUserMapper> moduleUserMapperCollection;


@Entity
@Table(name = "module_user_mapper")
@Data
@JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class, property = "id")
public class ModuleUserMapper implements Serializable 

    private static final long serialVersionUID = 1L;
    
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Basic(optional = false)
    @Column(name = "id")
    private Long id;
    
    @JoinColumn(name = "module_id", referencedColumnName = "id")
    @ManyToOne(optional = false)
    private Modules moduleId;
    
    @JoinColumn(name = "user_id", referencedColumnName = "id")
    @ManyToOne(optional = false)
    private Users userId;

当我访问获取所有用户时 - 我需要所有用户及其模块,而无需无限递归。 当我访问获取所有模块时 - 我需要所有模块及其用户而无需无限递归。

目前我正在尝试访问获取所有用户 - 以无限递归获取所有用户及其模块。 我尝试使用 @JsonIgnore,但我删除了子实体。

我正在使用 SpringBoot 版本 2.1.6.RELEASE & spring boot JPA

无限递归意味着 - 获取所有用户 = 用户 -> 模块 -> 用户 -> 模块等

如果我的实体映射或表创建有任何错误,请帮助我?

【问题讨论】:

“循环”是什么意思?听起来您正在寻找急切的获取策略。 将“循环”改为“无限递归” 我想你想说的是关于 N+1 问题:***.com/questions/32453989/… 【参考方案1】:

查看您的代码示例,在我看来,您实际上是在尝试模拟您的ModuleUser 实体之间的Many-to-Many 关系。如果是这样的话,也许这会回答你的问题?

hibernate @ManyToMany bidirectional eager fetching

【讨论】:

以上是关于如何在没有无限递归的情况下获得实体映射?的主要内容,如果未能解决你的问题,请参考以下文章

如何在没有连接列的情况下映射一对一关系(实体通过它们的 ID 连接)?

如何在没有 AttributeConverter 或 customUserType 的情况下使用 Hibernate 5.2.10 MySQL JSON 支持映射到 Java 实体类?

如何在避免复杂对象的情况下将 dto 映射到实体

杰克逊映射无限递归。春季数据休息

在春季使用多对一映射时获得无限的Json响应[重复]

Hibernate注解