我正在使用 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/