Java Webプロジェクトでユーザーの階層モデルを開発しようとしています。 Java Spring、JPA、およびHibernateでデータベースデータオブジェクトを実装しました。 "User"には、同じタイプの "User"というOneToMany関係の子のリストがあります。Java JPAエンティティOneToManyが同じエンティティを使用すると、アセンブラのスタックオーバーフローが発生する
@Transactional(readOnly = true)
@Override
public PageDTO<UserDTO> getListByParent(String id, Pageable page) {
final User parent = userRepository.findOne(id);
if (parent == null) {
throw new IllegalStateException("User parent not exist.");
}
final Page<User> usersPage = userRepository.findAll(UserSpecifications.withParent(parent), page);
return UserAssembler.toDTOPage(usersPage);
}
を
サービス:
クラスユーザー
@Entity
@Table(name = "emsusers")
public class User extends DomainEntity implements Serializable {
@Column(name = "username", nullable = false, unique = true)
private String username;
@Column(name = "password", nullable = false)
private String password;
@JoinColumn(name = "role", nullable = false)
@OneToOne(fetch = FetchType.LAZY, cascade = CascadeType.PERSIST)
private Role role;
@JoinColumn(name = "parent")
@OneToOne(fetch = FetchType.LAZY, cascade = CascadeType.PERSIST)
private User parent;
@JoinColumn(name = "children")
@OneToMany(fetch = FetchType.LAZY, cascade = CascadeType.PERSIST)
private final Set<User> children;
@JoinColumn(name = "servers")
@ManyToMany(fetch = FetchType.LAZY, cascade = CascadeType.PERSIST)
private Set<Server> servers;
private User(String username, String password, Role role, User parent, Set<Server> servers) {
super(UUID.randomUUID().toString());
if (username == null) {
throw new IllegalArgumentException("username == null");
}
this.username = username;
if (password == null) {
throw new IllegalArgumentException("password == null");
}
this.password = password;
if (role == null) {
throw new IllegalArgumentException("role == null");
}
this.role = role;
this.parent = parent;
this.children = Sets.newHashSet();
if (servers == null) {
this.servers = Sets.newHashSet();
}
else {
this.servers = Sets.newHashSet(servers);
}
}
public String getUsername() {
return username;
}
public String getPassword() {
return password;
}
public Role getRole() {
return role;
}
public User getParent() {
return parent;
}
public ImmutableSet<User> getChildren() {
return ImmutableSet.copyOf(children);
}
public ImmutableSet<Server> getServers() {
return ImmutableSet.copyOf(servers);
}
public void updatePassword(String oldPassword, String newPassword) {
if (!this.password.equals(oldPassword)) {
throw new IllegalArgumentException("Wrong old password.");
}
if (oldPassword.equals(newPassword)) {
throw new IllegalArgumentException("New password is equal to old password.");
}
this.password = newPassword;
}
public void update(Role role, Set<Server> servers) {
this.role = role;
this.servers = Sets.newHashSet(servers);
}
public void addChild(User child) {
this.children.add(child);
}
public void delChild(User child) {
this.children.remove(child);
}
public static User of(String username, String password, Role role, User parent, Set<Server> servers) {
return new User(username, password, role, parent, servers);
}
// Solo per JPA
protected User() {
this.children = Sets.newHashSet();
}
}
は、今私は、いくつかのサービスを定義した例については、このサービスは、親ユーザから作成されたすべてのユーザーのページング可能なリストを返します
次に、クラスUserAssemblerはいくつかのメソッドを実装します。この場合、サービスあなたがメソッドを呼び出す "toListDTO" "toDTO" 方法を見ることができるように
public static List<UserDTO> toListDTO(Set<User> input) {
final List<UserDTO> users = new ArrayList<>();
for (User usr : input) {
users.add(toDTO(usr));
}
return users;
}
を一覧表示するように設定し変換
public static UserDTO toDTO(User input) {
final UserDTO dto = new UserDTO();
dto.setId(input.getIdentity());
dto.setUsername(input.getUsername());
dto.setPassword(input.getPassword());
dto.setRole(RoleAssembler.toDTO(input.getRole()));
if (input.getParent() != null) {
dto.setParent(UserAssembler.toDTO(input.getParent()));
}
if (input.getChildren().isEmpty() == false) {
dto.getChildren().addAll(toListDTO(input.getChildren()));
}
if (input.getServers() != null) {
dto.getServers().addAll(ServerAssembler.toListString(input.getServers()));
}
return dto;
}
にUserDTOに
変換ユーザー:2つの重要なメソッドを使用しますこのメソッドは "toDTO"メソッドを呼び出し、この再帰により、サービスがjson rest APIを生成するためにコントローラによって呼び出されたときに、Javaスタックオーバーフローエラーが発生します。
@BatchSizeアノテーションを使用してOneToManyの子を制限しようとしましたが、エラーを解決できません。
解決方法を教えてもらえますか?
ありがとうございました。
まあ、UserDTOには親UserDTOがあります。子UserDTOには親UserDTOがあり、子UserDTOなどがあります。したがって、無限回帰ループです。 Hibernateはそれについて何もできません。あなたのDTOの設計が問題です。あなたのDTOまたは子供に親を持つことを選択しますが、両方を選択することはできません。 –