Spring Data JPA 的使用

上一篇Spring JavaConfig中配置數(shù)據(jù)源使用了JPA,這里就介紹一下Spring data jpa的常用方法.

spring data jpa介紹

什么是JPA

JPA(Java Persistence API)是Sun官方提出的Java持久化規(guī)范。它為Java開發(fā)人員提供了一種對象/關(guān)聯(lián)映射工具來管理Java應(yīng)用中的關(guān)系數(shù)據(jù)。

Spring Data JPA 是 Spring 基于 ORM 框架、JPA 規(guī)范的基礎(chǔ)上封裝的一套JPA應(yīng)用框架油坝,可使開發(fā)者用極簡的代碼即可實現(xiàn)對數(shù)據(jù)的訪問和操作涂籽。它提供了包括增刪改查等在內(nèi)的常用功能考传,且易于擴展!學(xué)習(xí)并使用 Spring Data JPA 可以極大提高開發(fā)效率坚俗!

spring data jpa讓我們解脫了DAO層的操作禽作,基本上所有CRUD都可以依賴于它來實現(xiàn)

簡單查詢

基本查詢也分為兩種尸昧,一種是spring data默認(rèn)已經(jīng)實現(xiàn),一種是根據(jù)查詢的方法來自動解析成SQL旷偿。

spring data jpa 默認(rèn)預(yù)先生成了一些基本的CURD的方法烹俗,例如:增、刪狸捅、改等等

public interface ItemRepository extends JpaRepository<Item, Integer>, JpaSpecificationExecutor<Item> {
//空的衷蜓,可以什么都不用寫
}
@Test
public void test1() throws Exception {
    Item item = new Item();
    itemRepository.save(item);
    List<Item> itemList = itemRepository.findAll();
    Item one = itemRepository.findOne(1);
    itemRepository.delete(item);
    long count = itemRepository.count();
}

自定義簡單查詢

Item findByItemName(String itemName);

List<Item> findByItemNameLike(String itemName);

Long deleteByItemId(Integer id);

List<Item> findByItemNameLikeOrderByItemNameDesc(String itemName);

具體的關(guān)鍵字,使用方法和生產(chǎn)成SQL如下表所示

Keyword Sample JPQL snippet
And findByLastnameAndFirstname … where x.lastname = ?1 and x.firstname = ?2
Or findByLastnameOrFirstname … where x.lastname = ?1 or x.firstname = ?2
Is,Equals findByFirstnameIs,findByFirstnameEquals … where x.firstname = ?1
Between findByStartDateBetween … where x.startDate between ?1 and ?2
LessThan findByAgeLessThan … where x.age < ?1
LessThanEqual findByAgeLessThanEqual … where x.age ? ?1
GreaterThan findByAgeGreaterThan … where x.age > ?1
GreaterThanEqual findByAgeGreaterThanEqual … where x.age >= ?1
After findByStartDateAfter … where x.startDate > ?1
Before findByStartDateBefore … where x.startDate < ?1
IsNull findByAgeIsNull … where x.age is null
IsNotNull,NotNull findByAge(Is)NotNull … where x.age not null
Like findByFirstnameLike … where x.firstname like ?1
NotLike findByFirstnameNotLike … where x.firstname not like ?1
StartingWith findByFirstnameStartingWith … where x.firstname like ?1 (parameter bound with appended %)
EndingWith findByFirstnameEndingWith … where x.firstname like ?1 (parameter bound with prepended %)
Containing findByFirstnameContaining … where x.firstname like ?1 (parameter bound wrapped in %)
OrderBy findByAgeOrderByLastnameDesc … where x.age = ?1 order by x.lastname desc
Not findByLastnameNot … where x.lastname <> ?1
In findByAgeIn(Collection ages) … where x.age in ?1
NotIn findByAgeNotIn(Collection age) … where x.age not in ?1
TRUE findByActiveTrue() … where x.active = true
FALSE findByActiveFalse() … where x.active = false
IgnoreCase findByFirstnameIgnoreCase … where UPPER(x.firstame) = UPPER(?1)

分頁查詢

Page<Item> findALL(Pageable pageable);
@Test
public void test1() throws Exception {
    int page=1,size=10;
    Sort sort = new Sort(Sort.Direction.DESC, "id");//根據(jù)id降序排序
    Pageable pageable = new PageRequest(page, size, sort);
    Page<Item> pageResult = itemRepository.findALL(pageable);
    List<Item> itemList = pageResult.getContent();
}

自定義SQL查詢

在SQL的查詢方法上面使用@Query注解尘喝,如涉及到刪除和修改在需要加上@Modifying.也可以根據(jù)需要添加 @Transactional 對事物的支持

//自定分頁查詢 一條查詢數(shù)據(jù),一條查詢數(shù)據(jù)量
@Query(value = "select i from Item i",
        countQuery = "select count(i.itemId) from Item i")
Page<Item> findall(Pageable pageable);

//nativeQuery = true 本地查詢  就是使用原生SQL查詢
@Query(value = "select * from item  where item_id = ?1", nativeQuery = true)
Item findAllItemById(int id);

@Transactional
@Modifying
@Query("delete from Item i where i.itemId = :itemId")
void deleteInBulkByItemId(@Param(value = "itemId") Integer itemId);

//#{#entityName}就是指定的@Entity,這里就是Item
 @Query("select i from #{#entityName} i where i.itemId = ?1")
 Item findById(Integer id);

命名查詢

在實體類上使用@NameQueries注解

在自己實現(xiàn)的DAO的Repository接口里面定義一個同名的方法

然后就可以使用了,Spring會先找是否有同名的NamedQuery斋陪,如果有朽褪,那么就不會按照接口定義的方法來解析。

//命名查詢
@NamedQueries({
        @NamedQuery(name = "Item.findItemByitemPrice",
                query = "select i from Item i where i.itemPrice between ?1 and ?2"),
        @NamedQuery(name = "Item.findItemByitemStock",
                query = "select i from Item i where i.itemStock between ?1 and ?2"),
})
@Entity
@Data
public class Item implements Serializable {
    @Id
    @GeneratedValue
    @Column(name = "item_id")
    private int itemId;
    private String itemName;
    private Integer itemPrice;
    private Integer itemStock;
 }
/**
 * 這里是在domain實體類里@NamedQuery寫對應(yīng)的HQL
 * @NamedQuery(name = "Item.findItemByitemPrice",
               baseQuery = "select i from Item i where i.itemPrice between ?1 and ?2"),
 * @param price1
 * @param price2
 * @return
 */
List<Item> findItemByitemPrice(Integer price1, Integer price2);
List<Item> findItemByitemStock(Integer stock1, Integer stock2);

那么spring data jpa是怎么通過這些規(guī)范來進行組裝成查詢語句呢?

Spring Data JPA框架在進行方法名解析時无虚,會先把方法名多余的前綴截取掉缔赠,比如 find、findBy友题、read嗤堰、readBy、get度宦、getBy踢匣,然后對剩下部分進行解析。

假如創(chuàng)建如下的查詢:findByUserDepUuid()戈抄,框架在解析該方法時离唬,首先剔除 findBy,然后對剩下的屬性進行解析
  1. 先判斷 userDepUuid (根據(jù) POJO 規(guī)范划鸽,首字母變?yōu)樾懀┦欠駷椴樵儗嶓w的一個屬性输莺,如果是戚哎,則表示根據(jù)該屬性進行查詢;如果沒有該屬性嫂用,繼續(xù)第二步型凳;
  2. 從右往左截取第一個大寫字母開頭的字符串此處為Uuid),然后檢查剩下的字符串是否為查詢實體的一個屬性嘱函,如果是啰脚,則表示根據(jù)該屬性進行查詢;如果沒有該屬性实夹,則重復(fù)第二步橄浓,繼續(xù)從右往左截取亮航;最后假設(shè)user為查詢實體的一個屬性荸实;
  3. 接著處理剩下部分(DepUuid),先判斷 user 所對應(yīng)的類型是否有depUuid屬性缴淋,如果有准给,則表示該方法最終是根據(jù) Doc.user.depUuid 的取值進行查詢;否則繼續(xù)按照步驟 2 的規(guī)則從右往左截取重抖,最終表示根據(jù) Doc.user.dep.uuid 的值進行查詢露氮。
  4. 可能會存在一種特殊情況,比如 Doc包含一個 user 的屬性钟沛,也有一個 userDep 屬性畔规,此時會存在混淆『尥常可以明確在屬性之間加上 "_" 以顯式表達意圖叁扫,比如 findByUser_DepUuid() 或者 findByUserDep_uuid()

原文鏈接:Spring Data JPA 的使用 | 火堯

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市畜埋,隨后出現(xiàn)的幾起案子莫绣,更是在濱河造成了極大的恐慌,老刑警劉巖悠鞍,帶你破解...
    沈念sama閱讀 210,978評論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件对室,死亡現(xiàn)場離奇詭異,居然都是意外死亡咖祭,警方通過查閱死者的電腦和手機掩宜,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 89,954評論 2 384
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來心肪,“玉大人锭亏,你說我怎么就攤上這事∮舶埃” “怎么了慧瘤?”我有些...
    開封第一講書人閱讀 156,623評論 0 345
  • 文/不壞的土叔 我叫張陵戴已,是天一觀的道長。 經(jīng)常有香客問我锅减,道長糖儡,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,324評論 1 282
  • 正文 為了忘掉前任怔匣,我火速辦了婚禮握联,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘每瞒。我一直安慰自己金闽,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 65,390評論 5 384
  • 文/花漫 我一把揭開白布剿骨。 她就那樣靜靜地躺著代芜,像睡著了一般。 火紅的嫁衣襯著肌膚如雪浓利。 梳的紋絲不亂的頭發(fā)上挤庇,一...
    開封第一講書人閱讀 49,741評論 1 289
  • 那天,我揣著相機與錄音贷掖,去河邊找鬼嫡秕。 笑死,一個胖子當(dāng)著我的面吹牛苹威,可吹牛的內(nèi)容都是我干的昆咽。 我是一名探鬼主播,決...
    沈念sama閱讀 38,892評論 3 405
  • 文/蒼蘭香墨 我猛地睜開眼屠升,長吁一口氣:“原來是場噩夢啊……” “哼潮改!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起腹暖,我...
    開封第一講書人閱讀 37,655評論 0 266
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎翰萨,沒想到半個月后脏答,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,104評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡亩鬼,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,451評論 2 325
  • 正文 我和宋清朗相戀三年殖告,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片雳锋。...
    茶點故事閱讀 38,569評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡黄绩,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出玷过,到底是詐尸還是另有隱情爽丹,我是刑警寧澤筑煮,帶...
    沈念sama閱讀 34,254評論 4 328
  • 正文 年R本政府宣布,位于F島的核電站粤蝎,受9級特大地震影響真仲,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜初澎,卻給世界環(huán)境...
    茶點故事閱讀 39,834評論 3 312
  • 文/蒙蒙 一秸应、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧碑宴,春花似錦软啼、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,725評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至捕仔,卻和暖如春匕积,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背榜跌。 一陣腳步聲響...
    開封第一講書人閱讀 31,950評論 1 264
  • 我被黑心中介騙來泰國打工闪唆, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人钓葫。 一個月前我還...
    沈念sama閱讀 46,260評論 2 360
  • 正文 我出身青樓悄蕾,卻偏偏與公主長得像,于是被迫代替她去往敵國和親础浮。 傳聞我的和親對象是個殘疾皇子帆调,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 43,446評論 2 348

推薦閱讀更多精彩內(nèi)容