Я работаю над проектом отдыха, используя Spring Boot и Hibernate, и в настоящее время пытаюсь понять, как справиться с моей json-сериализацией.
Схема, показанная в приведенном выше ERD, отображается Hibernate и работает нормально.
Проблема возникает, когда я делаю запрос на получение контроллера. Насколько я понимаю, Spring теперь пытается сериализовать цепочку объектов с помощью Jackson. Поскольку и родительский, и дочерний объекты имеют атрибуты друг друга, мы попадаем в бесконечный цикл рекурсии.
Теперь я изучил @JsonIgnore, @JsonView, @JsonManagedReference и @JsonBackReference, но, похоже, они работают только для отношений «один ко многим».
Я ищу ситуацию, когда, например, когда я делаю запрос GET к /users/{id}
, я получаю пользовательский объект, включая все его атрибуты отношений (назовем его полным объектом), но сами атрибуты отношений не показывают их атрибуты отношений (минимизированные объекты). Это прекрасно работает с аннотациями, упомянутыми выше, но как мне заставить это работать и по-другому?
Желаемый ответ для: /users/{id}
{ // full user object
id: 1,
username: 'foo',
// password can be JsonIgnored because of obvious reasons
role: { // minimized role object
id: 1,
name: 'bar'
// NO USERS LIST
}
area: { //minimized area object
id: 2,
name: 'some val'
// NO USERS LIST
// NO TABLES LIST
}
}
Желаемый ответ для /userrole/{id}
{ // full role object
id: 1,
name: 'waiter'
users: [
{ // minmized user object
id: 1,
username: 'foo'
// password can be JsonIgnored because of obvious reasons
// NO ROLE OBJECT
// NO AREA OBJECT
},
{ // minmized user object
id: 1,
username: 'foo'
// password can be JsonIgnored because of obvious reasons
// NO ROLE OBJECT
// NO AREA OBJECT
}
]
}
В общем: мне нужен полный объект, когда запрос делается непосредственно к объекту, и минимизированный объект, когда запрашивается косвенно.
Есть идеи? Надеюсь, мое объяснение достаточно ясно.
ОБНОВИТЬ
POJO Area, User и UserRole, как указано в разделах комментариев.
Пользователь
@Entity
@Table(name = "users", schema = "public", catalog = "PocketOrder")
public class User {
private int id;
private String username;
private String psswrd;
private List<Area> areas;
private UserRole Role;
@Id
@Column(name = "id", nullable = false)
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
@Basic
@Column(name = "username", nullable = false, length = 20)
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
@Basic
@JsonIgnore
@Column(name = "psswrd", nullable = true, length = 40)
public String getPsswrd() {
return psswrd;
}
public void setPsswrd(String psswrd) {
this.psswrd = psswrd;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
User user = (User) o;
if (id != user.id) return false;
if (username != null ? !username.equals(user.username) : user.username != null) return false;
if (psswrd != null ? !psswrd.equals(user.psswrd) : user.psswrd != null) return false;
return true;
}
@Override
public int hashCode() {
int result = id;
result = 31 * result + (username != null ? username.hashCode() : 0);
result = 31 * result + (psswrd != null ? psswrd.hashCode() : 0);
return result;
}
@ManyToMany(mappedBy = "users")
public List<Area> getAreas() {
return areas;
}
public void setAreas(List<Area> areas) {
this.areas = areas;
}
@ManyToOne
@JoinColumn(name = "role_fk", referencedColumnName = "id", nullable = false)
public UserRole getRole() {
return Role;
}
public void setRole(UserRole role) {
Role = role;
}
}
Роль пользователя
@Entity
@javax.persistence.Table(name = "userroles", schema = "public", catalog = "PocketOrder")
public class UserRole {
private int id;
private String name;
private List<User> users;
@Id
@Column(name = "id", nullable = false)
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
@Basic
@Column(name = "name", nullable = false, length = 20)
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
UserRole userRole = (UserRole) o;
if (id != userRole.id) return false;
if (name != null ? !name.equals(userRole.name) : userRole.name != null) return false;
return true;
}
@Override
public int hashCode() {
int result = id;
result = 31 * result + (name != null ? name.hashCode() : 0);
return result;
}
@OneToMany(mappedBy = "role")
public List<User> getUsers() {
return users;
}
public void setUsers(List<User> users) {
users = users;
}
}
Площадь
@Entity
@javax.persistence.Table(name = "areas", schema = "public", catalog = "PocketOrder")
public class Area {
private int id;
private String name;
private List<User> users;
private List<Table> tables;
@Id
@Column(name = "id", nullable = false)
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
@Basic
@Column(name = "name", nullable = false, length = 20)
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Area area = (Area) o;
if (id != area.id) return false;
if (name != null ? !name.equals(area.name) : area.name != null) return false;
return true;
}
@Override
public int hashCode() {
int result = id;
result = 31 * result + (name != null ? name.hashCode() : 0);
return result;
}
@ManyToMany
@JoinTable(name = "areas_users", catalog = "PocketOrder", schema = "public", joinColumns = @JoinColumn(name = "area_fk", referencedColumnName = "id", nullable = false), inverseJoinColumns = @JoinColumn(name = "user_fk", referencedColumnName = "id", nullable = false))
public List<User> getUsers() {
return users;
}
public void setUsers(List<User> users) {
this.users = users;
}
@OneToMany(mappedBy = "area")
public List<Table> getTables() {
return tables;
}
public void setTables(List<Table> tables) {
this.tables = tables;
}
}