Suppose you have a table with this structure.
If you want to issue a slightly complicated query using Spring Data JPA, use Specification, but if you use exists, the following Entity structure caused a problem. (Setter / getter omitted) By the way, the version of Spring Boot is 1.5.4.RELEASE.
User.java
@Entity
public class User {
@Id
private String userId;
private String name;
@OneToMany(mappedBy = "user", cascade = CascadeType.ALL)
private List<Phone> services;
}
Phone.java
@Entity
public class Phone {
@Id
private Integer phoneId;
@ManyToOne
@JoinColumn(name = "USER_ID")
private User user;
private Integer type;
private String number;
}
Using these Entity, the exists clause to "get User who has at least one Phone"
public interface UserRepository extends CrudRepository<User, Integer>, JpaSpecificationExecutor<User> {
static Specification<User> existsPhone() {
return (root, query, cb) -> {
Subquery<Integer> subquery = query.subquery(Integer.class);
Root<Phone> subRoot = subquery.from(Phone.class);
return cb.exists(subquery.select(cb.literal(1)).where(
cb.equal(root, subRoot.get("user").get("userId")));
};
}
}
Make like
userRepository.findAll(Specifications.where(UserRepository.existsPhone()));
When I executed, a StackOverflowError occurred.
Apparently, it seems that it has been circularly referenced as User → Phone → User → Phone → .... ..
So, if I remove the User reference from Phone as follows, the error disappeared.
User.java
@Entity
public class User {
@Id
private String userId;
private String name;
@OneToMany(cascade = CascadeType.ALL)
@JoinColumn(name = "userId")
private List<Phone> services;
}
Phone.java
@Entity
public class Phone {
@Id
private Integer phoneId;
private String userId;
private Integer type;
private String number;
}
public interface UserRepository extends CrudRepository<User, Integer>, JpaSpecificationExecutor<User> {
static Specification<User> existsPhone() {
return (root, query, cb) -> {
Subquery<Integer> subquery = query.subquery(Integer.class);
Root<Phone> subRoot = subquery.from(Phone.class);
return cb.exists(subquery.select(cb.literal(1)).where(
cb.equal(root, subRoot.get("userId")));
};
}
}
I don't even refer to User from Phone, so is this okay?
Recommended Posts