我的系統需要添加過濾器,我想知道是否有任何這樣的查詢
SELECT *
FROM posts p
when byDate is not null then (where p.createAt BETWEEN :startDate AND :endDate)
when byType is not null then (where p.type = :type)
我知道該查詢無效,但我希望在一個查詢中獲取請求所在的任何位置的資料(沒有過濾器或所有過濾器或某些過濾器)。
我的目標是創建一個查詢來實作所有案例。
uj5u.com熱心網友回復:
當您可以提前知道要運行的實際查詢時,撰寫大型 SQL 查詢通常不是一個好主意。
如果您想在運行查詢之前根據您知道的條件運行不同的查詢,您可以使用 JPA 或 Spring 中的不同方法
春天
您可以使用Spring Data 查詢方法定義不同的查詢嗎?
public class PostRepository implements JpaRepository<Post, Long> {
List<Post> findByCreatedAtBetween(Date startDate, Date endDate);
List<Post> findByTypeIs(String type);
}
然后在代碼的某個地方,您可以:
List<Post> results = null;
if (byDate != null) {
results = repository.findByCreatedAtBetween(startDate, endDate);
} else if (byType != null) {
results = repository.findByTypeIs(type);
} else {
results = repository.findAll();
}
標準
使用條件,您可以在運行時創建動態查詢并執行它:
public class PostRepository implements PostRepositoryCustom {
@PersistenceContext
private EntityManager em;
@Override
public List<Post> findPosts(Filter filter) {
CriteriaBuilder cb = entityManager.getCriteriaBuilder();
CriteriaQuery<User> query = cb.createQuery(Post.class);
Root<User> user = query.from(Post.class);
if ((filter.getByDate() != null)) {
// byDate is not null
ParameterExpression<Date> startDate = builder.parameter( Date.class );
ParameterExpression<Date> endDate = builder.parameter( Date.class );
query.where(builder.between( b.get( "createdAt" ), startDate, endDate));
return em.createQuery(query)
.setParameter(startDate, ...)
.setParameter(endDate, ...)
.getResultList();
}
if (filter.getByType() != null) {
ParameterExpression<Date> typeParam = builder.parameter( Date.class );
query.where(builder.and(root.get("type"), typeParam));
return em.createQuery(query)
.setParameter(typeParam, ...)
.getResultList();
}
return entityManager.createQuery(query)
.getResultList();
}
}
假設您的物體具有欄位type和createdAt. 如果您事先不知道您的查詢是什么樣的,這種方法很有效。例如,當您不知道必須添加多少條件時。
但是,如果我已經知道要運行哪個查詢,那么我更喜歡使用 HQL/JPQL。
高品質
如果您的查詢沒有改變并且您已經知道它們的樣子,我發現使用HQL更容易定義它們:
public class PostRepository implements PostRepositoryCustom {
@PersistenceContext
private EntityManager em;
@Override
public List<Post> findPosts(Filter filter) {
if (filter.getByDate() != null) {
return em.createQuery("from Post p where p.createdAt between :startDate and :endDate", Post.class)
.setParameter("startDate", ...)
.setParameter("endDate", ...)
.getResultList();
}
if (filter.getByType() != null) {
return em.createQuery("from Post p where p.type =:type", Post.class)
.setParameter("type", ...)
.getResultList();
}
return em.createQuery("from Post", Post.class)
.getResultList();
}
}
您可以重構代碼以使其更優雅,但它應該給您一個想法。請注意,如果您需要在不同的服務中重用相同的查詢,使用 annotation 定義它們可能會有所幫助@NamedQuery。
過濾器
在 Hibernate(不是 JPA)中,您還可以定義過濾器。它們是可以在運行時應用的 SQL 過濾條件:
@Entity
@FilterDef(name = Post.BY_DATE, defaultCondition = "createdAt between :startDate and :endDate", parameters = {@ParamDef(name = "startDate", type = "date"), @ParamDef(name = "startDate", type = "date") })
@FilterDef(name = Post.BY_TYPE, defaultCondition = "type = :type", parameters = @ParamDef(name = "startDate", type = "date"))
@Filter(name = Post.BY_DATE)
@Filter(name = Post.BY_TYPE)
class Post {
static final String BY_DATE = "Post.byDateFilter";
static final String BY_TYPE = "Post.byFilter"
private String type;
private Date createdAt;
...
}
然后:
public class PostRepository implements PostRepositoryCustom {
@PersistenceContext
private EntityManager em;
@Override
public List<Post> findPosts(Filter filter) {
enableFilters(em);
return em.createQuery("from Post", Post.class).getResultList();
}
private void enableFilters(Filter filter, EntityManager em) {
if (filter.getByDate() != null) {
em.unwrap(Session.class)
.enableFilter( Post.BY_DATE )
.setParameter("startDate", ...)
.setParameter("endDate", ...);
} else if (filter.getByType() != null) {
em.unwrap(Session.class)
.enableFilter( Post.BY_TYPE )
.setParameter("type", ...);
}
}
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/net/495509.html
