Biorąc pod uwagę pokaz slajdów, który zawiera slajdy i inną tabelę (SeenSlideshow), w której są przechowywane informacje o pracownikach, którzy widzieli pokaz slajdów.
@Data
@Entity
@Wither
@Table(name = "slideshow")
public class Slideshow {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "id")
private Integer id;
@Enumerated(EnumType.STRING)
@Column(name = "status", nullable = false)
private SlideshowStatus status;
@Enumerated(EnumType.STRING)
@Column(name = "persona", nullable = false)
private SlideshowPersona persona;
@Embedded
private Post post;
@OneToMany(fetch = FetchType.EAGER, cascade = CascadeType.ALL, orphanRemoval = true)
@JoinColumn(name = "slideshow_id")
@OrderBy("slide_order asc")
private List<Slide> slides;
@Embedded
private Conclusion conclusion;
@CreationTimestamp
private LocalDateTime createdAt;
private LocalDateTime publishedAt;
@Transient
private boolean seen;
public Slideshow() {
}
public Slideshow(Integer id, SlideshowStatus status, SlideshowPersona persona, Post post, Conclusion conclusion, LocalDateTime createdAt, LocalDateTime publishedAt, boolean seen) {
this.id = id;
this.status = status;
this.persona = persona;
this.post = post;
this.conclusion = conclusion;
this.createdAt = createdAt;
this.publishedAt = publishedAt;
this.seen = seen;
}
}
SeenSlideshow:
@Data
@Builder
@AllArgsConstructor
@Entity
@Table(name = "seen_slideshow")
public class SeenSlideshow {
@EmbeddedId
private SeenSlideshowIdentity pk;
@MapsId("employeeId")
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "employee_id")
private Employee employee;
@MapsId("slideshowId")
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "slideshow_id")
private Slideshow slideshow;
public SeenSlideshow() { }
public SeenSlideshow(Employee employee, Slideshow slideshow) {
this.pk = SeenSlideshowIdentity.builder()
.employeeId(employee != null ? employee.getId() : null)
.slideshowId(slideshow != null ? slideshow.getId() : null)
.build();
this.slideshow = slideshow;
this.employee = employee;
}
}
Jak mogę utworzyć zapytanie, które:
- jest podzielony na strony
- wypełnij przejściowe pole
seen
klasySlideshow
- pozwala na sortowanie według tego pola
seen
, na podstawie danego pracownika (parametr zapytania) - pobrać listę slajdów w tym samym czasie
- ma filtry dynamiczne (zwykle używam do tego przykładu lub specyfikacji)
Udało mi się spełnić pierwsze 3 wymagania, ale nie 4 i 5.
Mogę zastosować obejście 4, ale kiedy próbowałem użyć zapytania według przykładu lub specyfikacji, nie zadziałało, ponieważ żądanie, którego używam, wygląda następująco:
@Query(
value = "select new Slideshow(s.id, s.status, s.persona, s.post, s.conclusion, s.createdAt, s.publishedAt, (SELECT COUNT(ss.pk.slideshowId) > 0 FROM SeenSlideshow ss WHERE s.id = ss.pk.slideshowId and ss.pk.employeeId = :employeeId) as seen ) from Slideshow s",
countQuery = "select count(s) from Slideshow s"
)
Page<Slideshow> findForEmployee(String employeeId, Pageable pageable);
Ponieważ potrzebuję parametru do obliczenia pola seen
, nie mogę dodać żadnego Example<Slideshow>
ani Specification<Slideshow>
.
Kiedy dodam specyfikację, Spring JPA traktuje ją jako prosty nieużywany parametr, a filtry dynamiczne nie są stosowane.
Jak możemy wykonać dynamiczne zapytanie z podzapytaniem w klauzuli select?
1 odpowiedź
Udało mi się zaimplementować obejście za pomocą pomysłu Alana (które nie pasowało dokładnie do tego, czego chciałem, ponieważ moja wartość zależy od podłączonego użytkownika).
To nie jest idealne rozwiązanie, ale stworzyłem widok z kolumnami pokazu slajdów + employee_id
+ obliczone pole seen
.
create view employee_slideshow as
(select s.*, e.id as employee_id, (select COUNT(ss.slideshow_id) > 0 from seen_slideshow ss where ss.slideshow_id = s.id and ss.employee_id = e.id) as seen
from slideshow s, employee e
group by s.id, e.id)
Widok ten może być stronicowany, sortowany i filtrowany przez pracownika.
Następnie stworzyłem encję pasującą do tego widoku, wraz z jej repozytorium:
@Entity
@Table(name = "employee_slideshow")
public class EmployeeSlideshow {
@Id
private Integer id;
// and the other slideshow fields
private boolean seen;
private String employeeId;
}
Nie tego oczekiwałem po Spring JPA, ale przy małej wolumetrii to będzie w porządku.
Podobne pytania
Powiązane pytania
Nowe pytania
java
Java to język programowania wysokiego poziomu. Użyj tego tagu, jeśli masz problemy z używaniem lub zrozumieniem samego języka. Ten tag jest rzadko używany samodzielnie i jest najczęściej używany w połączeniu z [spring], [spring-boot], [jakarta-ee], [android], [javafx], [hadoop], [gradle] i [maven].
@Formula
lub utworzyć widok bazy danych, który można zmapować do istniejącej jednostki za pomocą JPA@SecondaryTable
. stackoverflow.com/questions/53176186/…