Есть три таблицы user, group, user2group. Связь много ко многим.
Если прописать мапинг только в классе User, то контроллер выдает json который и нужен.
@ManyToMany(fetch = FetchType.LAZY)
@JoinTable(name = "user2group",
joinColumns = { @JoinColumn(name = "user_id") },
inverseJoinColumns = { @JoinColumn(name = "group_id") })
private Set
Но если мапим связанные данные в классе Group, то при попытке получить список групп с привязанными к ним клиентами, контроллер начинает выдавать json, но при этом бесконечно проваливается в связанные сущности.
Мапинг для класса Group сейчас у меня следующий:
@ManyToMany(mappedBy = "groups")
private Set
Записи я получаю следующим образом
Session session = sessionFactory.getCurrentSession();
Query query = session.createQuery("FROM User");
List
Также, на случай если это важно. По началу при обращении к соответствующему урлу, вылетало исключение, которое починилось установкой следующего нагугленного свойства при инициализации бина LocalSessionFactory
properties.put("hibernate.enable_lazy_load_no_trans", true);
Вопрос. Чтобы получать json единой вложенности, нужны какие-то особенные настройки хибернейта? Или прописывать особый маппинг?
В ходе гугления вопроса мне начало казаться, что особо ни у кого не возникает подобной сложности, может тут подход нужен иной?
Задача
Возможность получить всех юзеров, где к каждому юзеру будет прикреплен список групп, в которых он числится.
Пример:
[
{id:1, name:"user1", groups:[{id:1, title:"group1"}, {id:5, title:"group5"}]},
{id:2, name:"user2", groups:[]},
{id:3, name:"user3", groups:[{id:3, title:"group3"}]},
]
Возможность получить все группы, где к каждой группе будет прикреплен список юзеров, которые числятся в этой группе
Пример:
[
{id:1, title:"group1", users:[{id:1, name:"user1"}, {id:5, name:"user5"}]},
{id:2, title:"group2", users:[]},
{id:3, title:"group3", users:[{id:3, name:"user3"}]},
]
Ответ
Не очень хорошая практика - отдавать ваши ORM-сущности непосредственно наружу.
Во-первых, вы смешиваете разные задачи в одном классе.
Во-вторых, вы отдаете наружу все его состояние, которое, возможно, не стоит отдавать.
В третьих, когда-нибудь вам потребуется отдавать для разных задач разный набор полей.
Обычно, эта проблема решается паттерном DTO (Data Transfer Object).
Вы просто создаете классы UserDto и GroupDto, которые содержат только необходимые поля, геттеры-сеттеры, конструктор по-умолчанию и JSON-аннотации. При отдаче наружу в слое представления (контроллере) перекладываете поля из ORM-объектов в DTO-объекты. Можно это делать как вручную (завести static-метод в DTO), так и использовать какой-нибудь маппер вроде Dozer.
Для получения групп с вложенными в нее пользователями, нужно завести отдельную DTO, например, как GroupWithUsersDto в примере ниже.
public class GroupDto {
@JsonProperty("id")
private Long id;
@JsonProperty("title")
private String title;
// сеттеры-геттеры
public static GroupDto fromModel(Group group) {
GroupDto dto = new GroupDto();
dto.setId(group.getId());
dto.setTitle(group.getTitle());
return dto;
}
public class UserDto {
@JsonProperty("id")
private Long id;
@JsonProperty("name")
private String name;
// сеттеры-геттеры
public static UserWithGroupsDto fromModel(User user) {
UserWithGroupsDto dto = new UserWithGroupsDto();
dto.setId(user.getId());
dto.setName(user.getName());
return dto;
}
}
Для выдачи пользователей с их группами:
public class UserWithGroupsDto {
@JsonProperty("id")
private Long id;
@JsonProperty("name")
private String name;
@JsonProperty("groups")
private List
// сеттеры-геттеры
public static UserWithGroupsDto fromModel(User user) {
UserWithGroupsDto dto = new UserWithGroupsDto();
dto.setId(user.getId());
dto.setName(user.getName());
List
for (Group group : user.getGroups()) {
groupDtos.add(GroupDto.fromModel(group));
}
dto.setGroups(groupDtos);
return dto;
}
}
Для выдачи групп с пользователями:
public class GroupWithUsersDto{
@JsonProperty("id")
private Long id;
@JsonProperty("title")
private String title;
@JsonProperty("users")
private List
// сеттеры-геттеры
public static GroupWithUsersDto fromModel(Group group) {
GroupWithUsersDto dto = new GroupWithUsersDto();
dto.setId(group.getId());
dto.setTitle(group.getTitle());
List
for (User user : group.getUsers()) {
usersDtos.add(UserDto.fromModel(user));
}
dto.setUsers(usersDtos);
return dto;
}
Комментариев нет:
Отправить комментарий