#java #hibernate #spring_mvc
Есть три таблицы user, group, user2group. Связь много ко многим. Если прописать мапинг только в классе User, то контроллер выдает json который и нужен. @ManyToMany(fetch = FetchType.LAZY) @JoinTable(name = "user2group", joinColumns = { @JoinColumn(name = "user_id") }, inverseJoinColumns = { @JoinColumn(name = "group_id") }) private Setgroups = new HashSet (); Но если мапим связанные данные в классе Group, то при попытке получить список групп с привязанными к ним клиентами, контроллер начинает выдавать json, но при этом бесконечно проваливается в связанные сущности. Мапинг для класса Group сейчас у меня следующий: @ManyToMany(mappedBy = "groups") private Set users = new HashSet (); Записи я получаю следующим образом Session session = sessionFactory.getCurrentSession(); Query query = session.createQuery("FROM User"); List users = query.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"}]}, ]
Ответы
Ответ 1
Не очень хорошая практика - отдавать ваши 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 Listgroups; // сеттеры-геттеры public static UserWithGroupsDto fromModel(User user) { UserWithGroupsDto dto = new UserWithGroupsDto(); dto.setId(user.getId()); dto.setName(user.getName()); List groupDtos = new ArrayList<>(); 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 usersDtos = new ArrayList<>(); for (User user : group.getUsers()) { usersDtos.add(UserDto.fromModel(user)); } dto.setUsers(usersDtos); return dto; } Ответ 2
Можно повесить в классе Group на поле @ManyToMany(mappedBy = "groups") private Setusers = new HashSet (); аннотацию @JsonIgnore Или использовать слой DTO package my.company.model; import javax.persistence.*; import java.util.Date; import java.util.List; import java.util.Set; @Entity @Table(name = "users") public class User { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private long id; private String name; private String surname; private String password; private String email; @Column(name="time_registration") private Date timeRegistration; @ManyToMany(fetch = FetchType.LAZY) @JoinTable(name = "users_to_roles", joinColumns = {@JoinColumn(name = "user_id")}, inverseJoinColumns = @JoinColumn(name = "role_id")) private Set roles; @OneToMany(mappedBy = "user", fetch = FetchType.LAZY) private List albums; @ManyToMany(fetch = FetchType.LAZY) @JoinTable(name = "users_to_dialogs", joinColumns = {@JoinColumn(name = "user_id")}, inverseJoinColumns = @JoinColumn(name = "dialog_id")) private List
Комментариев нет:
Отправить комментарий