Supposons que vous ayez une table avec cette structure.
J'utilise la spécification lorsque je souhaite émettre une requête légèrement compliquée à l'aide de Spring Data JPA, mais lorsque l'utilisation existe, un problème est survenu avec la structure d'entité suivante. (Setter / getter omis) À propos, la version de Spring Boot est 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;
}
En utilisant ces entités, la clause existe pour "obtenir un utilisateur qui possède au moins un télé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")));
};
}
}
Faire comme
userRepository.findAll(Specifications.where(UserRepository.existsPhone()));
Lorsque j'ai exécuté, une StackOverflowError s'est produite.
Apparemment, il semble qu'il ait été référencé de manière circulaire comme Utilisateur → Téléphone → Utilisateur → Téléphone → .... ..
Donc, si je supprime la référence utilisateur du téléphone comme suit, l'erreur a disparu.
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")));
};
}
}
Je ne fais même pas référence à l'utilisateur depuis le téléphone, est-ce que ça va?
Recommended Posts