java - 如何使用集合创建 DTO 对象

标签 java spring dto

我正在使用 Spring 框架编写应用程序。我想为我的实体对象创建 dto 模型并在 spring Controller 中使用它。这并不难,但是我在数据库中的表之间有一个关系,我必须在我的实体对象中设置。

用户实体

    @Entity
@Table(name = "users")
public class User implements Serializable {

    private static final long serialVersionUID = 1L;
    @Id
    @GeneratedValue
    @Column(name = "id")
    private Integer id;
    @NotBlank
    @NotNull
    @Size(min = 3, max = 40)
    @Column(name = "username")
    private String username;
    @NotBlank
    @NotNull
    @Size(min = 3, max = 40)
    @Column(name = "password")
    private String password;
    @NotBlank
    @NotNull
    @Size(min = 3, max = 40)
    @Column(name = "firstName")
    private String firstName;
    @NotBlank
    @NotNull
    @Size(min = 3, max = 40)
    @Column(name = "lastName")
    private String lastName;
    @Size(min = 11, max = 11)
    @Column(name = "personalId")
    private String personalId;
    @Size(max = 40)
    @Column(name = "city")
    private String city;
    @Size(max = 40)
    @Column(name = "address")
    private String address;
    @NotBlank
    @NotNull
    @Email
    @Size(max = 40)
    @Column(name = "email")
    private String email;
    @Size(min = 9, max = 9)
    @Column(name = "phone")
    private String phone;
    @OneToMany(mappedBy = "user", cascade = CascadeType.ALL, fetch = FetchType.EAGER)
    private Set<UserRole> userRoleSet;

user_roles 实体

@Entity
@Table(name = "user_roles")
public class UserRole implements Serializable {

    private static final long serialVersionUID = 1L;

    @Id
    @GeneratedValue
    @Column(name = "id")
    private Integer id;
    @NotNull
    @Size(max = 40)
    @Column(name = "name")
    private String name;
    @JoinColumn(name = "userId")
    @ManyToOne(targetEntity = User.class)
    private User user;

表 user 与 user_role 表存在一对多的关系。 我为此实体创建了一个 DTO 对象:

用户Dto

public class UserDto {

    private Integer id;
    @NotBlank
    @NotNull
    @Size(min = 3, max = 40)
    private String username;
    @NotBlank
    @NotNull
    @Size(min = 3, max = 40)
    private String password;
    @NotBlank
    @NotNull
    @Size(min = 3, max = 40)
    private String firstName;
    @NotBlank
    @NotNull
    @Size(min = 3, max = 40)
    private String lastName;
    @Size(min = 11, max = 11)
    private String personalId;
    @Size(min = 3, max = 40)
    private String city;
    @Size(min = 3, max = 40)
    private String address;
    @NotBlank
    @NotNull
    @Email
    @Size(max = 40)
    private String email;
    @Size(min = 9, max = 9)
    private String phone;
    private Set<UserRoleDto> userRoleSetDto;

userRoleDto

public class UserRoleDto {

    private Integer id;
    @NotNull
    @Size(min = 3, max = 40)
    private String name;
    private UserDto userDto;

我的 Controller 重定向到一个包含用户列表的页面

@SuppressWarnings("unchecked")
@RequestMapping(value = "/admin/adminlist", method = RequestMethod.GET)
public ModelAndView goAdminList() {
    ModelAndView mav = new ModelAndView("admin/adminlist");
    List<UserDto> admins = prepareUserListDto(userService.getAdminList());
    mav.addObject("admins", admins);
    return mav;
}

在这个 Controller 中,我使用方法 prepareUserListDto 准备用户列表到 userdto 列表:

private List<UserDto> prepareUserListDto(List<User> users) {
    List<UserDto> userDtoList = null;
    if (users != null && !users.isEmpty()) {
        userDtoList = new ArrayList<UserDto>();
        UserDto userDto = null;
        for (User user : users) {
            userDto = new UserDto();
            userDto.setId(user.getId());
            userDto.setUsername(user.getUsername());
            userDto.setPassword(user.getPassword());
            userDto.setFirstName(user.getFirstName());
            userDto.setLastName(user.getLastName());
            userDto.setEmail(user.getEmail());
            userDto.setUserRoleSetDto(prepareUserRoleDtoSet(user
                    .getUserRoleSet()));
            userDtoList.add(userDto);
        }
    }
    return userDtoList;
}

此方法调用方法将 userRole 准备为 userRoleDto

private Set<UserRoleDto> prepareUserRoleDtoSet(Set<UserRole> userRoles) {
    Set<UserRoleDto> userRoleDtoSet = null;
    if (userRoles != null && !userRoles.isEmpty()) {
        userRoleDtoSet = new HashSet<UserRoleDto>();
        UserRoleDto userRoleDto = null;
        for (UserRole userRole : userRoles) {
            userRoleDto = new UserRoleDto();
            userRoleDto.setId(userRole.getId());
            userRoleDto.setName(userRole.getName());
            userRoleDto.setUserDto(prepareUserDto(userRole.getUser()));
            userRoleDtoSet.add(userRoleDto);
        }
    }
    return userRoleDtoSet;
}

但是这个方法再次调用方法:

private UserDto prepareUserDto(User user) {
    UserDto userDto = new UserDto();
    userDto.setId(user.getId());
    userDto.setUsername(user.getUsername());
    userDto.setPassword(user.getPassword());
    userDto.setFirstName(user.getFirstName());
    userDto.setLastName(user.getLastName());
    userDto.setEmail(user.getEmail());
    userDto.setUserRoleSetDto(prepareUserRoleDtoSet(user.getUserRoleSet()));
    return userDto;
}

总而言之,当我尝试显示管理员列表时,我进行了递归调用,但出现此错误:

java.lang.StackOverflowError org.hibernate.collection.internal.PersistentSet.isEmpty(PersistentSet.java:166) pl.piotr.ibank.controller.AdminController.prepareUserRoleDtoSet(AdminController.java:170) pl.piotr.ibank.controller.AdminController.prepareUserDto(AdminController.java:139) pl.piotr.ibank.controller.AdminController.prepareUserRoleDtoSet(AdminController.java:177) pl.piotr.ibank.controller.AdminController.prepareUserDto(AdminController.java:139) pl.piotr.ibank.controller.AdminController.prepareUserRoleDtoSet(AdminController.java:177) pl.piotr.ibank.controller.AdminController.prepareUserDto(AdminController.java:139) pl.piotr.ibank.controller.AdminController.prepareUserRoleDtoSet(AdminController.java:177) pl.piotr.ibank.controller.AdminController.prepareUserDto(AdminController.java:139) pl.piotr.ibank.controller.AdminController.prepareUserRoleDtoSet(AdminController.java:177) pl.piotr.ibank.controller.AdminController.prepareUserDto(AdminController.java:139)

第 139 行是 userDto.setUserRoleSetDto(prepareUserRoleDtoSet(user.getUserRoleSet()));private UserDto prepareUserDto(User user)方法和第 177 行是 private UserDto prepareUserDto(User user)private Set<UserRoleDto> prepareUserRoleDtoSet(Set<UserRole> userRoles)方法。

如何为这个实体写dto?如果它没有约束,这很容易,但我的实体在 user 和 user_role 之间有约束,我不知道如何解决。

最佳答案

UserDto 和 UserRoleDto 之间存在双向关系。

如果你真的需要保持双向关系,我会修改你的代码如下:

private UserDto prepareUserDto(User user) {
    UserDto userDto = new UserDto();
    userDto.setId(user.getId());
    userDto.setUsername(user.getUsername());
    userDto.setPassword(user.getPassword());
    userDto.setFirstName(user.getFirstName());
    userDto.setLastName(user.getLastName());
    userDto.setEmail(user.getEmail());
    userDto.setUserRoleSetDto(prepareUserRoleDtoSet(user.getUserRoleSet(), userDto));
    return userDto;
}

这会将正在创建的 userDto 传递给 prepareUserRoleDtoSet。

private Set<UserRoleDto> prepareUserRoleDtoSet(Set<UserRole> userRoles, UserDto userDto) {
    Set<UserRoleDto> userRoleDtoSet = null;
    if (userRoles != null && !userRoles.isEmpty()) {
        userRoleDtoSet = new HashSet<UserRoleDto>();
        UserRoleDto userRoleDto = null;
        for (UserRole userRole : userRoles) {
            userRoleDto = new UserRoleDto();
            userRoleDto.setId(userRole.getId());
            userRoleDto.setName(userRole.getName());
            userRoleDto.setUserDto(userDto);
            userRoleDtoSet.add(userRoleDto);
        }
    }
    return userRoleDtoSet;
}

关于java - 如何使用集合创建 DTO 对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27150200/

相关文章:

java - Java 中的范围简化

Spring 和多模块设置

java - 创建名为 'org.springframework.scheduling.annotation.proxyasyncconfiguration' 的 bean 时出错

java - 列出差异 : DTO, VO,实体,域,模型

java - 实体和DTO之间的区别

java - javafx中窗口大小增加时如何设置自动调整大小?

java - 在单例中使用 "private static final String"变量的最佳实践

java - Spring:xsi:schemaLocation无法从spring.schemas读取配置

c# - 在哪里处理 DTO<-> 业务对象转换

Java Regex 在拆分前检查前一个字符