門戶網(wǎng)站開發(fā)過程百度霸屏推廣多少錢一個月
文章目錄
- 問題
- 處理
- PostgreSQL排序相關(guān)
- JPA相關(guān)介紹
問題
- 我們項目使用
Spring Boot
構(gòu)建,使用JHipster
生成業(yè)務(wù)代碼,包含基礎(chǔ)的增刪改查代碼 - 使用
PostgreSQL
作為業(yè)務(wù)數(shù)據(jù)庫,使用自動生成的JPA
構(gòu)建數(shù)據(jù)更新語查詢 - 在查詢某個實體類的列表時,沒有指定排序字段,查詢返回按照添加順序倒序返回,這樣也符合我們的需求
- 在修改了某個實體后,發(fā)現(xiàn)它在列表里的順序變動了。順序變動,沒有固定排序,會對客戶使用系統(tǒng)造成困惑
- 一開始以為是在查詢時加了修改時間倒序,查看代碼后發(fā)現(xiàn),沒有更新時間字段,查詢時也沒有加排序字段
- 這里放一段查詢代碼示例:
Specification<AreaConfig> specification = (Specification<AreaConfig>) (root, query, cb) ->{List<Predicate> predicateList = new ArrayList<>();Join<AreaConfig, SmartIntersection> join = root.join("smartIntersection", JoinType.LEFT);predicateList.add(cb.equal(join.get("id").as(Long.class), smartIntersection.getId()));Predicate[] pre = new Predicate[predicateList.size()];pre = predicateList.toArray(pre);return query.where(pre).getRestriction();};return areaConfigRepository.findAll(specification);
處理
- 查閱文檔之后知曉:使用
SELECT
語句查詢表中的數(shù)據(jù)時,PostgreSQL
不確保按照一定的順序返回結(jié)果 - 這就要求,查詢時,如果想要每次都按照一定順序返回,就要指定排序字段
- 一種寫法時,在調(diào)用
Repository
查詢方法(如.findAll
)時傳遞參數(shù)指定Sort
,代碼示例如下:
Specification<GreenWaveRouteConfig> specification = (Specification<GreenWaveRouteConfig>) (root, query, cb) ->{List<Predicate> predicateList = new ArrayList<>();Join<GreenWaveRouteConfig, GreenWaveRoute> join = root.join("greenWaveRoute", JoinType.LEFT);predicateList.add(cb.equal(join.get("id").as(Long.class), routeId));Predicate[] pre = new Predicate[predicateList.size()];pre = predicateList.toArray(pre);return query.where(pre).getRestriction();};return greenWaveRouteConfigRepository.findAll(specification, Sort.by("index"));
- 另一種寫法是,在
specification
里使用query.orderBy
指定排序
Specification<SignalManualControlLog> specification = (root, query, cb) ->{List<Predicate> predicateList = new ArrayList<>();if (intersectionId != null) {predicateList.add(cb.equal(root.get("intersectionId").as(Long.class), intersectionId));}//時間倒序query.orderBy(cb.desc(root.get("opTime")));Predicate[] pre = new Predicate[predicateList.size()];pre = predicateList.toArray(pre);return query.where(pre).getRestriction();};List<SignalManualControlLog> controlLogs = manualControlLogRepository.findAll(specification);
PostgreSQL排序相關(guān)
- 在一般情況下,PostgreSQL查詢的結(jié)果集會按照指定的排序規(guī)則返回。如果你使用了
ORDER BY
子句,那么查詢結(jié)果會按照該子句指定的排序規(guī)則返回。 - 然而,在某些情況下,PostgreSQL返回結(jié)果可能不是按照期望的順序。這通常是由于數(shù)據(jù)的物理存儲方式、索引使用、并行查詢或查詢優(yōu)化器等因素導(dǎo)致的。如果數(shù)據(jù)表上沒有合適的索引或統(tǒng)計信息,PostgreSQL可能會選擇不同的訪問路徑,導(dǎo)致結(jié)果的順序與預(yù)期不符。
- 為了確保結(jié)果按照指定的順序返回,你可以使用
ORDER BY
子句明確指定排序規(guī)則。另外,你還可以考慮使用適當(dāng)?shù)乃饕蚪y(tǒng)計信息來幫助PostgreSQL優(yōu)化查詢執(zhí)行計劃,以確保結(jié)果按照預(yù)期的順序返回。 - 此外,PostgreSQL也提供了一些查詢提示和指令,比如
ORDER BY
子句中的ORDER BY ... USING
,以及SET
命令中的random_page_cost
等,可以用來影響PostgreSQL查詢優(yōu)化器的行為,以確保結(jié)果按照一定的順序返回。 - 總的來說,雖然在一般情況下PostgreSQL會按照指定的排序規(guī)則返回結(jié)果,但是在一些特殊情況下可能會出現(xiàn)結(jié)果順序不符合預(yù)期的情況。因此,在編寫查詢語句時,應(yīng)該使用
ORDER BY
子句來明確指定排序規(guī)則,以確保結(jié)果的順序是可預(yù)測的。
JPA相關(guān)介紹
-
JPA(Java Persistence API)是一種用于管理Java應(yīng)用程序中持久化數(shù)據(jù)的API。它為開發(fā)人員提供了一種方便的方法來在數(shù)據(jù)庫中存儲、檢索和管理對象。在使用JPA的過程中,開發(fā)人員經(jīng)常需要執(zhí)行各種類型的查詢來檢索數(shù)據(jù)。以下是一些常見的JPA查詢介紹:
-
- JPQL(Java Persistence Query Language)查詢:JPQL是一種面向?qū)ο蟮牟樵冋Z言,類似于SQL,但是針對實體對象進(jìn)行查詢。它使用實體類和其屬性名稱而不是表名和列名來執(zhí)行查詢。開發(fā)人員可以使用JPQL來執(zhí)行復(fù)雜的查詢操作,如連接查詢、聚合函數(shù)、條件過濾等。
TypedQuery<Customer> query = entityManager.createQuery("SELECT c FROM Customer c WHERE c.age > 18", Customer.class);
List<Customer> customers = query.getResultList();
-
- 命名查詢:JPA還允許開發(fā)人員定義命名查詢,以便在需要時輕松地引用和重用它們。開發(fā)人員可以在實體類上使用@NamedQuery注解來定義命名查詢,然后在代碼中使用實體管理器的createNamedQuery方法執(zhí)行該命名查詢。
@NamedQuery(name="Customer.findAllAdults", query="SELECT c FROM Customer c WHERE c.age > 18")
public class Customer {//...
}TypedQuery<Customer> query = entityManager.createNamedQuery("Customer.findAllAdults", Customer.class);
List<Customer> customers = query.getResultList();
-
- Criteria API查詢:JPA還提供了Criteria API,它允許開發(fā)人員使用類型安全的查詢構(gòu)建器來動態(tài)地構(gòu)建查詢。Criteria API可以用于構(gòu)建復(fù)雜的查詢,而不需要編寫任何字符串形式的查詢語句。
CriteriaBuilder cb = entityManager.getCriteriaBuilder();
CriteriaQuery<Customer> query = cb.createQuery(Customer.class);
Root<Customer> root = query.from(Customer.class);
query.select(root).where(cb.greaterThan(root.get("age"), 18));
List<Customer> customers = entityManager.createQuery(query).getResultList();
- 除了上述介紹的查詢方式外,JPA還支持原生SQL查詢、存儲過程調(diào)用等其他查詢方式。開發(fā)人員可以根據(jù)具體的業(yè)務(wù)需求選擇適合的查詢方式來操作持久化數(shù)據(jù)。