Есть две связные сущности: Organization самодостаточна, Site имеет ссылку на нее:
import javax.persistence.*;
import java.util.HashSet;
import java.util.Set;
@Entity
public class Site extends AbstractIdentifiable {
@OneToOne(optional = false)
private Organization organization;
@ManyToMany(mappedBy = "sites", fetch = FetchType.EAGER, cascade = CascadeType.ALL)
private Set<Member> members = new HashSet<>();
@OneToMany(mappedBy = "site", fetch = FetchType.EAGER, cascade = CascadeType.ALL)
private Set<Location> locations = new HashSet<>();
public Site() {
}
public Organization getOrganization() {
return organization;
}
public void setOrganization(Organization organization) {
this.organization = organization;
}
public Set<Member> getMembers() {
return members;
}
public void setMembers(Set<Member> members) {
this.members = members;
}
public Set<Location> getLocations() {
return locations;
}
public void setLocations(Set<Location> locations) {
this.locations = locations;
}
}
import javax.persistence.*;
import javax.validation.constraints.NotBlank;
import java.io.Serializable;
import java.util.HashSet;
import java.util.Objects;
import java.util.Set;
@Entity
public class Organization extends AbstractIdentifiable implements Serializable {
@Column(nullable = false)
@NotBlank
private String title;
@OneToOne(mappedBy = "organization", cascade = CascadeType.ALL)
private Site site;
@OneToOne(mappedBy = "organization", cascade = CascadeType.ALL)
private Advertiser advertiser;
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public Site getSite() {
return site;
}
public void setSite(Site site) {
this.site = site;
}
public Advertiser getAdvertiser() {
return advertiser;
}
public void setAdvertiser(Advertiser advertiser) {
this.advertiser = advertiser;
}
}
Когда я сериализую Site приложение зацикливается из-за циклических ссылок. Поставить @JsonIgnore в сущности Organization у поля site нельзя, ибо в другом месте программы потребуется сериализовать сущность Organization как корневую, с сериализацией Organization как вложенной сущности. На помощь приходит MixIn. Делаю так:
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.helan.adkiosk.entitiy.Advertiser;
import com.helan.adkiosk.entitiy.Site;
public interface OrganizationMixIn {
@JsonIgnore
public Site getSite();
@JsonIgnore
public Advertiser getAdvertiser();
}
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.helan.adkiosk.entitiy.Location;
import com.helan.adkiosk.entitiy.Member;
import java.util.Set;
public interface SiteWithOrganizationMixIn {
@JsonIgnore
public Set<Member> getMembers();
@JsonIgnore
public Set<Location> getLocations();
}
public String index() throws JsonProcessingException {
ObjectMapper mapperWithMixIn = new ObjectMapper();
mapperWithMixIn.addMixIn(Site.class, SiteWithOrganizationMixIn.class);
mapperWithMixIn.addMixIn(Organization.class, OrganizationMixIn.class);
return mapperWithMixIn.writeValueAsString(siteRepository.findAll());
}
Все работает как и задумывалось. Не устраивает только то, что я должен явно указывать поля в каждом MixIn, которые я не хочу сериализовывать с помощью аннотации JsonIgnore. Есть ли возможность реализовать обратную логику: по умолчанию сериализация отключена для всех полей, и в каждом MixIn я должен включить определенные поля? Или еще лучше, Изначально в сущности я указываю поля, которые сериализуются, а затем добавляю еще требуемые в каждом MixIn?
Еще вопрос, в mvc могу ли я не создавать в явном виде ObjectMapper и вызывать сериализацию в строку, а указать с помощью какой-нибудь аннотации используемые в сериализации набор MixIn и возвращать ссылку объект из метода контроллера?