Иногда вам нужно получить некоторые данные с сервера в JavaScript, JSON является довольно хорошим выбором для этой задачи.
Давайте поиграем с примером «Работодатель — Сотрудник — Выгода» из отображений JPA Demystified (эпизод 1) — @OneToMany и @ManyToOne . Мы будем использовать его внутри веб-приложения на основе Spring Framework .
Наш первый контроллер вернет список сотрудников в качестве тела ответа, в нашем случае MappingJacksonHttpMessageConverter будет автоматически использоваться для преобразования значения, возвращаемого методом handleGet, в ответ, отправляемый клиенту.
|
01
02
03
04
05
06
07
08
09
10
11
12
|
@Controller@RequestMapping('/employee-list.json')public class EmployeeListController { @Autowired private EmployerDAO employerDAO; @RequestMapping(method = RequestMethod.GET) @ResponseBody public List<Employee> handleGet(@RequestParam('employerId') Long employerId) { return employerDAO.getEmployees(employerId); }} |
Когда мы пытаемся получить данные в первый раз, мы сталкиваемся с красивым исключением: JsonMappingException: бесконечная рекурсия (StackOverflowError) — вызвано двунаправленными ссылками между Employer — Employee — Benefit.
В поисках возможного решения я обнаружил заметку Обработка двунаправленных ссылок, используя декларативный метод (ы) , и после прочтения я исправил сущности домена следующим образом:
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
|
@Entity@Table(name = 'EMPLOYERS')public class Employer implements Serializable {... @JsonManagedReference('employer-employee') @OneToMany(mappedBy = 'employer', cascade = CascadeType.PERSIST) public List getEmployees() { return employees; }...}@Entity@Table(name = 'EMPLOYEES')public class Employee implements Serializable {... @JsonManagedReference('employee-benefit') @OneToMany(mappedBy = 'employee', cascade = CascadeType.PERSIST) public List getBenefits() { return benefits; } @JsonBackReference('employer-employee') @ManyToOne(optional = false) @JoinColumn(name = 'EMPLOYER_ID') public Employer getEmployer() { return employer; }...}@Entity@Table(name = 'BENEFITS')public class Benefit implements Serializable {... @JsonBackReference('employee-benefit') @ManyToOne(optional = false) @JoinColumn(name = 'EMPLOYEE_ID') public Employee getEmployee() { return employee; }...} |
После внесения вышеуказанных изменений я наконец смог получить ответ JSON, возвращаемый моим кодом:
|
1
|
[{'id':1, 'benefits':[{'name':'Healthy Employees', 'id':1, 'type':'HEALTH_COVERAGE', 'startDate':1104534000000, 'endDate':null}, {'name':'Gold Autumn','id':2,'type':'RETIREMENT_PLAN','startDate':1104534000000,'endDate':null},{'name':'Always Secured','id':3,'type':'GROUP_TERM_LIFE','startDate':1104534000000,'endDate':null}],'firstName':'John'},{'id':2,'benefits':[],'firstName':'Mary'},{'id':3,'benefits':[],'firstName':'Eugene'}] |
И как обычно несколько ссылок на десерт:
Справка: JSON — Джексон на помощь от нашего партнера по JCG Миха? Ja? Tak в блоге Мысли Чернокнижника