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转换问题