我正在使用Spring Boot和Hibernate开展一个休息项目,目前正在尝试弄清楚如何处理我的json序列化。
上面的ERD中显示的模式由Hibernate映射并且工作正常。
当我向控制器发出get请求时出现问题。我的理解是Spring现在尝试使用Jackson序列化对象链。因为父对象和子对象都有另一个作为属性,所以我们发现自己遇到了无限递归循环。
现在我已经研究过@JsonIgnore,@ JsonView,@ JasonManagedReference和@JsonBackReference,但这些似乎只适用于一对多的关系。
我正在寻找的是一种情况,例如当我向/users/{id}
发出GET请求时,我得到的用户对象包括它的所有关系属性(让我们称之为完整对象),但这种关系属性本身不显示它们的关系属性(最小化对象)。这适用于上面提到的注释,但我如何以其他方式使这项工作?
对所需的回复:/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在评论部分中的要求。
@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;
}
}
答案 0 :(得分:1)
尝试在特定点使用 @JsonSerialize :
样本:
1 - 映射您的字段
@JsonSerialize(using = ExampleSampleSerializer.class)
@ManyToOne
private Example example;
2 - 创建自定义jackson序列化程序(这里可以控制序列化)
public class ExampleSampleSerializer extends JsonSerializer<Example> {
@Override
public void serialize(Example value, JsonGenerator jsonGenerator, SerializerProvider serializers) throws IOException, JsonProcessingException {
jsonGenerator.writeStartObject();
jsonGenerator.writeFieldName("first");
jsonGenerator.writeNumber(value.getFirstValue());
jsonGenerator.writeFieldName("second");
jsonGenerator.writeNumber(value.getSecondValue());
jsonGenerator.writeFieldName("third");
jsonGenerator.writeNumber(value.getAnyAnotherClass().getThirdValue());
jsonGenerator.writeEndObject();
}
}
答案 1 :(得分:0)
我处理多对多关系的方法是使用
@JsonIgnore
在一个实体上。
例如,我们有Person和Child实体。一个人可以有多个孩子,反之亦然。
在Person
上,我们有:
public class Person
{
//Other fields ommited
@ManyToMany(fetch = FetchType.LAZY, cascade = CascadeType.PERSIST)
@JoinTable(name = "person_child",
joinColumns = {
@JoinColumn(name = "person_id", referencedColumnName = "id", nullable = false,
updatable = false)
},
inverseJoinColumns = {
@JoinColumn(name = "child_id", referencedColumnName = "id", nullable =
false, updatable = false)
})
private Set<Child> children = new HashSet<>() ;
}
在Child
上,我们有:
public class Child
{
@JsonIgnore
@ManyToMany(mappedBy = "children", fetch = FetchType.LAZY)
private Set<Person> people = new HashSet<>() ;
}
现在,当我们获得一个Person时,我们还将获得他所有关联的孩子。但是,当我们得到一个Child时,我们就不会得到所有的People,因为上面有@JsonIgnore批注。 这样可以解决“无限递归”问题,并引发此问题。
我的解决方法是编写查询以使所有与特定child_id
相连的人。
在下面,您可能会看到我的代码:
public interface PersonDAO extends JpaRepository<Person, Long>
{
@Query(value = "SELECT * " +
" FROM person p INNER JOIN person_child j " +
"ON p.id = j.person_id WHERE j.child_id = ?1 ", nativeQuery = true)
public List<Person> getPeopleViaChildId(long id);
}
每当我想从孩子那里得到所有人时,我都会使用它。