J'essaie de configurer OneToMany et ManyToOne mapping dans le projet Spring Data, mais j'ai quelques problèmes.
J'ai donc deux entités: Employeur et Projet . Un employeur pourrait avoir plusieurs projets.
Classes d'entités:
Employeur.Java
@Entity
@Table (name="Employer")
public class Employer {
@Id
@SequenceGenerator(name="my_seq", sequenceName="GLOBAL_SEQUENCE")
@GeneratedValue(strategy = GenerationType.SEQUENCE ,generator="my_seq")
@Column (name="employer_id")
private int id;
@Column (name="name")
private String name;
@JoinColumn (name="employer_id")
@OneToMany(mappedBy = "employer", cascade = CascadeType.ALL, fetch = FetchType.EAGER)
private Set<Project> project = new HashSet<Project>();
......................
}
Project.Java
@Entity
@Table (name="Project")
public class Project {
@Id
@SequenceGenerator(name="my_seq", sequenceName="GLOBAL_SEQUENCE")
@GeneratedValue(strategy = GenerationType.SEQUENCE ,generator="my_seq")
@Column (name="project_id")
private int id;
@Column (name="name")
private String name;
@ManyToOne
@JoinColumn(name="employer_id", nullable = false)
private Employer employer;
......................
}
Classes de référentiel:
public interface EmployerRepository extends JpaRepository<Employer, Integer> {
}
public interface ProjectRepository extends JpaRepository<Project, Integer> {
}
Services:
@Service
public class EmployerServiceImpl implements EmployerService {
@Autowired
private EmployerRepository employerRepository;
@Override
public List<Employer> getAllEmployers() {
return employerRepository.findAll();
}
}
@Service
public class ProjectServiceImpl implements ProjectService {
@Autowired
private ProjectRepository projectRepository;
@Override
public List<Project> getAllProjects() {
return projectRepository.findAll();
}
}
Contrôleur:
@Controller
public class MainController {
private EmployerService employerService;
private ProjectService projectService;
@Autowired(required = true)
@Qualifier(value = "employerService")
public void setEmployerService(EmployerService employerService) {
this.employerService = employerService;
}
@Autowired(required = true)
@Qualifier(value = "projectService")
public void setProjectService(ProjectService projectService) {
this.projectService = projectService;
}
@RequestMapping(value="/employers", method=RequestMethod.GET)
public @ResponseBody List<Employer> getEmployers(@RequestParam(value = "name", required = false) String name) {
return employerService.getAllEmployers();
}
..............................
}
Table des employeurs:
EMPLOYER_ID . NAME
......................
1 . Google
2 . Oracle
3 . Facebook
Table de projet:
PROJECT_ID . NAME . EMPLOYER_ID
.......................................
1 . Create web site . 1
2 . Create reporting . 2
3 . Create web service . 3
4 . Fixing web site . 1
J'attends quelque chose comme ça:
[{"id":1,"name":"Google","project":[{"id":1,"name":"Create web site"}, {"id":4,"name":"Fixing web site"}},
{"id":2,"name":"Oracle","project":{"id":2,"name":"Create reporting"}},
{"id":3,"name":"Facebook","project":{"id":3,"name":"Create web service"}}]
Mais la méthode getEmployers
de la classe controller
renvoie celle-ci:
[{"id":1,"name":"Oracle","project":[{"id":4,"name":"Fixing web site",
"employer":{"id":1,"name":"Oracle","project":[{"id":4,"name":"Fixing web site",
"employer":{"id":1,"name":"Oracle","project":[{"id":4,"name":"Fixing web site",
"employer":{"id":1,"name":"Oracle","project":[{"id":4,"name":"Fixing web site",
"employer":{"id":1,"name":"Oracle","project":[{"id":4,"name":"Fixing web site",
"employer":{"id":1,"name":"Oracle","project":[{"id":4,"name":"Fixing web site","employer":
...................
Veuillez m'excuser si cette question a été discutée à plusieurs reprises, mais je n'ai trouvé aucune réponse appropriée.
Merci d'avance!
Vous avez une association bidirectionnelle entre Employer
name__s et Project
name__s. En outre, vous avez configuré les deux côtés de l'association pour qu'ils soient chargés EAGER
name__ly (les associations @ManyToOne
sont extraites par défaut EAGER
name__ly et vous avez également forcé l'extraction du côté @OneToMany
avec EAGER
name__ly. En raison de cette configuration, lorsque l'infrastructure de sérialisation charge le Employer
name__s, il trouve des Project
name__s valides qui ont des liens en arrière vers le Employer
name__s et finissent par rester bloqués dans une boucle cyclique.
Pour obtenir le résultat souhaité, vous devez marquer le côté @ManyToOne
(sur l'entité Project
name__) à extraire LAZY
name__ly comme @ManyTone(fetch = FetchType.LAZY)
.
Ajoutez le @JsonManagedReference dans la partie suivante de la relation (classe User.Java):
@Entity
public class User implements Serializable {
@Id
@GeneratedValue(strategy=GenerationType.IDENTITY)
private long id;
@Column(name="name")
private String name;
@ManyToMany
@JoinTable(name="users_roles",joinColumns=@JoinColumn(name = "user_fk"), inverseJoinColumns=@JoinColumn(name = "role_fk"))
@JsonManagedReference
private Set<Role> roles = new HashSet<Role>();
...
Ajoutez le @JsonBackReference dans la partie arrière de la relation (par exemple, la classe Role.Java):
@Entity
public class Role implements Serializable {
@Id
@GeneratedValue(strategy=GenerationType.IDENTITY)
private int id;
@ManyToMany(mappedBy="roles")
@JsonBackReference
private Set<User> users = new HashSet<User>();
...
Cela fonctionne très bien pour moi. :-)