欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

hibernate注解联表查询以及联表导致的死循环

程序员文章站 2022-04-13 14:09:20
...

好不容易解决了hibernate注解导致联表查询死循环的问题,这里记录一下

BaseEntity
@Setter
@Getter
@MappedSuperclass
@EntityListeners(AuditingEntityListener.class)
public class BaseEntity implements Serializable {
	// ...
	@Column(name = "create_time")
    @CreationTimestamp
    private Timestamp createTime;

    @Column(name = "update_time")
    @UpdateTimestamp
    private Timestamp updateTime;

    public String toString() {
        ToStringBuilder builder = new ToStringBuilder(this);
        Field[] fields = this.getClass().getDeclaredFields();
        try {
            for (Field f : fields) {
                f.setAccessible(true);
                builder.append(f.getName(), f.get(this)).append("\n");
            }
        } catch (Exception e) {
            builder.append("toString builder encounter an error");
        }
        return builder.toString();
    }

    public @interface Create {
    }

    public @interface Update {
    }
}
SysMember
@Entity
@Data
@Table(name = "sys_member")
public class SysMember extends BaseEntity {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "id")
    @NotNull(groups = {Update.class})
    private Long id;

	// 用户可以主动查看权限,fetch为主动,解决lazy导致的获取roleSet时sql连接已断开的问题
    @ManyToMany(fetch = FetchType.EAGER)
    @ApiModelProperty(value = "用户权限")
    // JoinTable 设置中间表,joinColumns为当前实体的标识,inverseJoinColumns为被查询的实体标识
    @JoinTable(name = "sys_role_member",
            joinColumns = {@JoinColumn(name = "member_id", referencedColumnName = "id")},
            inverseJoinColumns = {@JoinColumn(name = "role_id", referencedColumnName = "id")})
    private Set<SysRole> roleSet;

	// 重写equals方法,主要是jpa在对数据进行更新时会以equals为判断依据,不重写容易出现各种奇怪的问题
    @Override
    public boolean equals(Object o) {
        if (this == o) {
            return true;
        }
        if (o == null || getClass() != o.getClass()) {
            return false;
        }
        SysMember role = (SysMember) o;
        return Objects.equals(id, role.id);
    }

	// copy方法,主要是用于设定值的时候去除空值
    public void copy(SysMember source) {
        BeanUtil.copyProperties(source, this, CopyOptions.create().setIgnoreNullValue(true));
    }
}
SysMenu
@Entity
@Data
@Table(name = "sys_menu")
public class SysMenu extends BaseEntity {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "id")
    @NotNull(groups = {Update.class})
    private Long id;

	// 关键的JsonIgnore,这个注解用于解决调用api时,roleSet无限循环查询,最终导致内存溢出或者时json转换错误
    @JsonIgnore
    @ManyToMany(fetch = FetchType.EAGER)
    @JoinTable(name = "sys_role_menu",
            joinColumns = {@JoinColumn(name = "menu_id", referencedColumnName = "id")},
            inverseJoinColumns = {@JoinColumn(name = "role_id", referencedColumnName = "id")})
    private Set<SysRole> roleSet;

    @Override
    public boolean equals(Object o) {
        if (this == o) {
            return true;
        }
        if (o == null || getClass() != o.getClass()) {
            return false;
        }
        SysMenu role = (SysMenu) o;
        return Objects.equals(id, role.id);
    }

    public void copy(SysMenu source) {
        BeanUtil.copyProperties(source, this, CopyOptions.create().setIgnoreNullValue(true));
    }
}
SysRole
@Entity
@Data
@Table(name = "sys_role")
public class SysRole extends BaseEntity {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "id")
    @NotNull(groups = {Update.class})
    private Long id;
	
	// 权限可以主动查询菜单,便于调取,
    @ManyToMany(fetch = FetchType.EAGER)
    @ApiModelProperty(value = "权限菜单")
    @JoinTable(name = "sys_role_menu",
            joinColumns = {@JoinColumn(name = "role_id", referencedColumnName = "id")},
            inverseJoinColumns = {@JoinColumn(name = "menu_id", referencedColumnName = "id")})
    private Set<SysMenu> menuSet;

	// 权限通过绑定相应的member实体中的roleSet数据
    @JsonIgnore
    @ApiModelProperty(value = "用户权限")
    @ManyToMany(mappedBy = "roleSet")
    private Set<SysMember> memberSet;

    @Override
    public boolean equals(Object o) {
        if (this == o) {
            return true;
        }
        if (o == null || getClass() != o.getClass()) {
            return false;
        }
        SysRole role = (SysRole) o;
        return Objects.equals(id, role.id);
    }

    public void copy(SysRole source) {
        BeanUtil.copyProperties(source, this, CopyOptions.create().setIgnoreNullValue(true));
    }
}

通过主要的几个注释
@ManyToMany
@ManyToOne
@OneToMany来联表查询
通过设定
@JsonIgnore
忽略json转换问题