Angenommen, Sie haben eine Tabelle mit dieser Struktur.
Wenn Sie mit Spring Data JPA eine etwas komplizierte Abfrage ausführen möchten, verwenden Sie Specification. Wenn Sie jedoch vorhanden verwenden, hat die folgende Entitätsstruktur ein Problem verursacht. (Setter / Getter weggelassen) Die Version von Spring Boot ist übrigens 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;
}
Bei Verwendung dieser Entität gibt es die Klausel "Für einen Benutzer mit mindestens einem Telefon".
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")));
};
}
}
Machen Sie wie
userRepository.findAll(Specifications.where(UserRepository.existsPhone()));
Bei der Ausführung ist ein StackOverflowError aufgetreten.
Anscheinend wurde es zirkulär als Benutzer → Telefon → Benutzer → Telefon → .... bezeichnet. ..
Wenn ich also die Benutzerreferenz wie folgt vom Telefon entferne, ist der Fehler verschwunden.
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")));
};
}
}
Ich beziehe mich nicht einmal auf den Benutzer vom Telefon. Ist das in Ordnung?
Recommended Posts