国产片侵犯亲女视频播放_亚洲精品二区_在线免费国产视频_欧美精品一区二区三区在线_少妇久久久_在线观看av不卡

服務(wù)器之家:專(zhuān)注于服務(wù)器技術(shù)及軟件下載分享
分類(lèi)導(dǎo)航

PHP教程|ASP.NET教程|Java教程|ASP教程|編程技術(shù)|正則表達(dá)式|C/C++|IOS|C#|Swift|Android|VB|R語(yǔ)言|JavaScript|易語(yǔ)言|vb.net|

服務(wù)器之家 - 編程語(yǔ)言 - Java教程 - spring data jpa使用詳解(推薦)

spring data jpa使用詳解(推薦)

2021-04-20 14:16牛奮lch Java教程

這篇文章主要介紹了spring data jpa使用詳解(推薦),小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧

使用spring data jpa開(kāi)發(fā)已經(jīng)有一段時(shí)間了,這期間學(xué)習(xí)了一些東西,也遇到了一些問(wèn)題,在這里和大家分享一下。

前言:

spring data簡(jiǎn)介:

spring data是一個(gè)用于簡(jiǎn)化數(shù)據(jù)庫(kù)訪問(wèn),并支持云服務(wù)的開(kāi)源框架。其主要目標(biāo)是使得對(duì)數(shù)據(jù)的訪問(wèn)變得方便快捷,并支持map-reduce框架和云計(jì)算數(shù)據(jù)服務(wù)。 spring data 包含多個(gè)子項(xiàng)目:

commons - 提供共享的基礎(chǔ)框架,適合各個(gè)子項(xiàng)目使用,支持跨數(shù)據(jù)庫(kù)持久化

jpa - 簡(jiǎn)化創(chuàng)建 jpa 數(shù)據(jù)訪問(wèn)層和跨存儲(chǔ)的持久層功能

hadoop - 基于 spring 的 hadoop 作業(yè)配置和一個(gè) pojo 編程模型的 mapreduce 作業(yè)

key-value  - 集成了 redis 和 riak ,提供多個(gè)常用場(chǎng)景下的簡(jiǎn)單封裝

document - 集成文檔數(shù)據(jù)庫(kù):couchdb 和 mongodb 并提供基本的配置映射和資料庫(kù)支持

graph - 集成 neo4j 提供強(qiáng)大的基于 pojo 的編程模型

graph roo addon - roo support for neo4j

jdbc extensions - 支持 oracle rad、高級(jí)隊(duì)列和高級(jí)數(shù)據(jù)類(lèi)型

mapping - 基于 grails 的提供對(duì)象映射框架,支持不同的數(shù)據(jù)庫(kù)

examples - 示例程序、文檔和圖數(shù)據(jù)庫(kù)

guidance - 高級(jí)文檔

一、spring data jpa簡(jiǎn)介

spring data jpa是spring在orm框架,以及jpa規(guī)范的基礎(chǔ)上,封裝的一套jpa應(yīng)用框架,并提供了一整套的數(shù)據(jù)訪問(wèn)層解決方案。

二、spring data jpa的功能

spring data jpa的功能非常的強(qiáng)大,這里我們先跳過(guò)環(huán)境搭建這一步,來(lái)一睹spring data jpa的“芳容”。

spring data jpa提供給用戶(hù)使用的,主要有以下幾個(gè)接口:

  1. repository:僅僅是一個(gè)標(biāo)識(shí),表明任何繼承它的均為倉(cāng)庫(kù)接口類(lèi),方便spring自動(dòng)掃描識(shí)別
  2. crudrepository:繼承repository,實(shí)現(xiàn)了一組crud相關(guān)的方法
  3. pagingandsortingrepository:繼承crudrepository,實(shí)現(xiàn)了一組分頁(yè)排序相關(guān)的方法
  4. jparepository:繼承pagingandsortingrepository,實(shí)現(xiàn)一組jpa規(guī)范相關(guān)的方法
  5. jpaspecificationexecutor:比較特殊,不屬于repository體系,實(shí)現(xiàn)一組jpa criteria查詢(xún)相關(guān)的方法。

三、spring data jpa的接口

1、crudrepository接口

建立一個(gè)entity類(lèi):

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
@entity
@table(name="user")
public class user {
  @id
  @generatedvalue
  private integer id;   
  //賬號(hào)
  private string account;
  //姓名
  private string name;   
  //密碼
  private string password;   
  // 郵箱
  private string email;
}

編寫(xiě)接口,并繼承crudrepository接口:

?
1
2
public interface userrepository extends crudrepository<user, integer> {   
}

編寫(xiě)測(cè)試類(lèi)(為了更直觀的看到效果,所有測(cè)試類(lèi)都沒(méi)有使用斷言,直接使用的打印語(yǔ)句):

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
public class userrepositorytest {
  @autowired
  private userrepository dao;
   
  @test//保存
  public void testsave(){
    user user = new user();
    user.setname("chhliu");
    user.setaccount("10000");
    user.setemail("chhliu@.com");
    user.setpassword("123456");
    dao.save(user);
  }
   
  @test//批量保存
  public void testsave1(){
    list<user> users = new arraylist<user>();
    user user = new user();
    user.setname("tanjie");
    user.setaccount("10000");
    user.setemail("tanjie@.com");
    user.setpassword("123456");
    users.add(user);
    user = new user();
    user.setname("esdong");
    user.setaccount("10000");
    user.setemail("esdong@.com");
    user.setpassword("123456");
    users.add(user);
    user = new user();
    user.setname("qinhongfei");
    user.setaccount("10000");
    user.setemail("qinhongfei@.com");
    user.setpassword("123456");
    users.add(user);
    user = new user();
    user.setname("huizhang");
    user.setaccount("10000");
    user.setemail("huizhang@.com");
    user.setpassword("123456");
    users.add(user);
    user = new user();
    user.setname("caican");
    user.setaccount("10000");
    user.setemail("caican@.com");
    user.setpassword("123456");
    users.add(user);
    dao.save(users);
  }
   
  @test//更新
  public void testupdate(){
    user user = dao.findone(1);
    user.setpassword("123890");// 要想這樣實(shí)現(xiàn)更新的功能,需要在service層加上@transaction事物注解
  }
   
  @test//刪除
  public void testdelete(){
    dao.delete(2);
  }
   
  @test//查詢(xún)所有
  public void testfindall(){
    list<user> users = (list<user>) dao.findall();
    system.out.println(json.tojsonstring(users));
  }
   
  @test//判斷指定的id對(duì)象是否存在
  public void testisexist(){
    boolean isexist = dao.exists(8);
    system.out.println(isexist);
  }
   
  @test//通過(guò)id列表來(lái)查詢(xún)
  public void testfinduserbyids(){
    list<integer> listids = new arraylist<integer>();
    listids.add(2);
    listids.add(4);
    listids.add(7);
    list<user> users = (list<user>) dao.findall(listids);
    system.out.println(json.tojsonstring(users));
  }
}

大家可以看出,到這里,我就只寫(xiě)了一個(gè)接口類(lèi),并沒(méi)有實(shí)現(xiàn)這個(gè)接口類(lèi),就可以完成基本的crud操作。因?yàn)檫@個(gè)接口會(huì)自動(dòng)為域?qū)ο髣?chuàng)建增刪改查方法,供業(yè)務(wù)層直接使用。

該接口的定義如下,總共提供了11個(gè)方法,基本上可以滿足簡(jiǎn)單的crud操作以及批量操作:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
@norepositorybean
public interface crudrepository<t, id extends serializable> extends repository<t, id> {
  <s extends t> s save(s entity);//保存
  <s extends t> iterable<s> save(iterable<s> entities);//批量保存
  t findone(id id);//根據(jù)id查詢(xún)一個(gè)對(duì)象
  boolean exists(id id);//判斷對(duì)象是否存在
  iterable<t> findall();//查詢(xún)所有的對(duì)象
  iterable<t> findall(iterable<id> ids);//根據(jù)id列表查詢(xún)所有的對(duì)象
  long count();//計(jì)算對(duì)象的總個(gè)數(shù)
  void delete(id id);//根據(jù)id刪除
  void delete(t entity);//刪除對(duì)象
  void delete(iterable<? extends t> entities);//批量刪除
  void deleteall();//刪除所有
}

2、pagingandsortingrepository接口

pagingandsortingrepository接口繼承了crudrepository接口。

編寫(xiě)接口,并繼承pagingandsortingrepository接口

?
1
2
3
public interface userrepositorywithorder extends
    pagingandsortingrepository<user, integer> { 
}

編寫(xiě)測(cè)試類(lèi):

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
@runwith(springjunit4classrunner.class)
@contextconfiguration(locations = { "classpath:applicationcontext-config.xml" })
@transactionconfiguration(defaultrollback = false)
@transactional
public class userrepositorywithordertest {
  @autowired
  private userrepositorywithorder dao;
   
  @test
  public void testorder(){
    sort sort = new sort(direction.desc, "id");
    pageable pageable = new pagerequest(0, 5, sort);
    page<user> page = dao.findall(pageable);
    system.out.println(json.tojsonstring(page));
    system.out.println(page.getsize());
  }
}

只要繼承了這個(gè)接口,spring data jpa就已經(jīng)為你提供了分頁(yè)和排序的功能了。該接口的定義如下,主要提供了兩個(gè)方法,供使用,其中t是要操作的實(shí)體類(lèi),id是實(shí)體類(lèi)主鍵的類(lèi)型

?
1
2
3
4
5
@norepositorybean
public interface pagingandsortingrepository<t, id extends serializable> extends crudrepository<t, id> {
  iterable<t> findall(sort sort);// 不帶分頁(yè)的排序
  page<t> findall(pageable pageable);// 帶分頁(yè)的排序
}

3、jparepository接口

如果業(yè)務(wù)需要即提供crud操作,又需要提供分頁(yè)以及排序功能,那么就可以直接繼承這個(gè)接口。該接口繼承了pagingandsortingrepository接口。

接口定義如下:

?
1
2
3
4
5
6
7
8
9
public interface jparepository<t, id extends serializable> extends pagingandsortingrepository<t, id> {
  list<t> findall();//查詢(xún)所有對(duì)象,不排序
  list<t> findall(sort sort);//查詢(xún)所有對(duì)象,并排序
  <s extends t> list<s> save(iterable<s> entities);//批量保存
  void flush();//強(qiáng)制緩存與數(shù)據(jù)庫(kù)同步
  t saveandflush(t entity);//保存并強(qiáng)制同步
  void deleteinbatch(iterable<t> entities);//批量刪除
  void deleteallinbatch();//刪除所有
}

4、jpaspecificationexecutor接口

該接口提供了對(duì)jpa criteria查詢(xún)的支持。注意,這個(gè)接口很特殊,不屬于repository體系,而spring data jpa不會(huì)自動(dòng)掃描識(shí)別,所以會(huì)報(bào)找不到對(duì)應(yīng)的bean,我們只需要繼承任意一個(gè)繼承了repository的子接口或直接繼承repository接口,spring data jpa就會(huì)自動(dòng)掃描識(shí)別,進(jìn)行統(tǒng)一的管理。

編寫(xiě)接口如下:

?
1
2
3
public interface specificationexecutorrepository extends crudrepository<user, integer>,
    jpaspecificationexecutor<user> { 
}

service類(lèi):

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
@service
public class specificationexecutorrepositorymanager {
  @autowired
  private specificationexecutorrepository dao;
  /**
   * 描述:根據(jù)name來(lái)查詢(xún)用戶(hù)
   */
  public user finduserbyname(final string name){
    return dao.findone(new specification<user>() {
       
      @override
      public predicate topredicate(root<user> root, criteriaquery<?> query,
          criteriabuilder cb) {
        predicate predicate = cb.equal(root.get("name"), name);
        return predicate;
      }
    });
  }
   
  /**
   * 描述:根據(jù)name和email來(lái)查詢(xún)用戶(hù)
   */
  public user finduserbynameandemail(final string name, final string email){
    return dao.findone(new specification<user>() {
       
      @override
      public predicate topredicate(root<user> root,
          criteriaquery<?> query, criteriabuilder cb) {
        list<predicate> list = new arraylist<predicate>();
        predicate predicate1 = cb.equal(root.get("name"), name);
        predicate predicate2 = cb.equal(root.get("email"), email);
        list.add(predicate1);
        list.add(predicate2);
        // 注意此處的處理
        predicate[] p = new predicate[list.size()];
        return cb.and(list.toarray(p));
      }
    });
  }
   
  /**
   * 描述:組合查詢(xún)
   */
  public user finduserbyuser(final user uservo){
    return dao.findone(new specification<user>() {
       
      @override
      public predicate topredicate(root<user> root,
          criteriaquery<?> query, criteriabuilder cb) {
        predicate predicate = cb.equal(root.get("name"), uservo.getname());
        cb.and(predicate, cb.equal(root.get("email"), uservo.getemail()));
        cb.and(predicate, cb.equal(root.get("password"), uservo.getpassword()));
        return predicate;
      }
    });
  }
   
  /**
   * 描述:范圍查詢(xún)in方法,例如查詢(xún)用戶(hù)id在[2,10]中的用戶(hù)
   */
  public list<user> finduserbyids(final list<integer> ids){
    return dao.findall(new specification<user>() {
 
      @override
      public predicate topredicate(root<user> root,
          criteriaquery<?> query, criteriabuilder cb) {
        return root.in(ids);
      }
    });
  }
   
  /**
   * 描述:范圍查詢(xún)gt方法,例如查詢(xún)用戶(hù)id大于9的所有用戶(hù)
   */
  public list<user> finduserbygtid(final int id){
    return dao.findall(new specification<user>() {
 
      @override
      public predicate topredicate(root<user> root,
          criteriaquery<?> query, criteriabuilder cb) {
        return cb.gt(root.get("id").as(integer.class), id);
      }
    });
  }
   
  /**
   * 描述:范圍查詢(xún)lt方法,例如查詢(xún)用戶(hù)id小于10的用戶(hù)
   */
  public list<user> finduserbyltid(final int id){
    return dao.findall(new specification<user>() {
 
      @override
      public predicate topredicate(root<user> root,
          criteriaquery<?> query, criteriabuilder cb) {
        return cb.lt(root.get("id").as(integer.class), id);
      }
    });
  }
   
  /**
   * 描述:范圍查詢(xún)between方法,例如查詢(xún)id在3和10之間的用戶(hù)
   */
  public list<user> finduserbetweenid(final int start, final int end){
    return dao.findall(new specification<user>() {
 
      @override
      public predicate topredicate(root<user> root,
          criteriaquery<?> query, criteriabuilder cb) {
        return cb.between(root.get("id").as(integer.class), start, end);
      }
    });
  }
   
  /**
   * 描述:排序和分頁(yè)操作
   */
  public page<user> finduserandorder(final int id){
    sort sort = new sort(direction.desc, "id");
    return dao.findall(new specification<user>() {
 
      @override
      public predicate topredicate(root<user> root,
          criteriaquery<?> query, criteriabuilder cb) {
        return cb.gt(root.get("id").as(integer.class), id);
      }
    }, new pagerequest(0, 5, sort));
  }
   
  /**
   * 描述:只有排序操作
   */
  public list<user> finduserandordersecondmethod(final int id){
    return dao.findall(new specification<user>() {
 
      @override
      public predicate topredicate(root<user> root,
          criteriaquery<?> query, criteriabuilder cb) {
        cb.gt(root.get("id").as(integer.class), id);
        query.orderby(cb.desc(root.get("id").as(integer.class)));
        return query.getrestriction();
      }
    });
  }
}

測(cè)試類(lèi):

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
@runwith(springjunit4classrunner.class)
@contextconfiguration(locations = { "classpath:applicationcontext-config.xml" })
@transactionconfiguration(defaultrollback = false)
@transactional
public class specificationexecutorrepositorymanagertest {
  @autowired
  private specificationexecutorrepositorymanager manager;
  @test
  public void testfinduserbyname(){
    user user = manager.finduserbyname("chhliu");
    system.out.println(json.tojsonstring(user));
  }
   
  @test
  public void testfinduserbynameandemail(){
    user user = manager.finduserbynameandemail("chhliu", "chhliu@.com");
    system.out.println(json.tojsonstring(user));
  }
   
  @test
  public void testfinduserbyuservo(){
    user user = new user();
    user.setname("chhliu");
    user.setemail("chhliu@.com");
    user u = manager.finduserbyuser(user);
    system.out.println(json.tojsonstring(u));
  }
   
  @test
  public void testfinduserbyids(){
    list<user> users = manager.finduserbyids(new arraylist<integer>(arrays.aslist(1,3,5,6)));
    system.out.println(json.tojsonstring(users));
  }
   
  @test
  public void testfinduserbygtid(){
    list<user> users = manager.finduserbygtid(5);
    system.out.println(json.tojsonstring(users));
  }
   
  @test
  public void testfinduserbyltid(){
    list<user> users = manager.finduserbyltid(5);
    system.out.println(json.tojsonstring(users));
  }
   
  @test
  public void testfinduserbetweenid(){
    list<user> users = manager.finduserbetweenid(4, 9);
    system.out.println(json.tojsonstring(users));
  }
   
  @test
  public void testfinduserandorder(){
    page<user> users = manager.finduserandorder(1);
    system.out.println(json.tojsonstring(users));
  }
   
  @test
  public void testfinduserandordersecondmethod(){
    list<user> users = manager.finduserandordersecondmethod(1);
    system.out.println(json.tojsonstring(users));
  }
}

5、repository接口

這個(gè)接口是最基礎(chǔ)的接口,只是一個(gè)標(biāo)志性的接口,沒(méi)有定義任何的方法,那這個(gè)接口有什么用了?既然spring data jpa提供了這個(gè)接口,自然是有它的用處,例如,我們有一部分方法是不想對(duì)外提供的,比如我們只想提供增加和修改方法,不提供刪除方法,那么前面的幾個(gè)接口都是做不到的,這個(gè)時(shí)候,我們就可以繼承這個(gè)接口,然后將crudrepository接口里面相應(yīng)的方法拷貝到repository接口就可以了。

總結(jié):上述五個(gè)接口,開(kāi)發(fā)者到底該如何選擇?其實(shí)依據(jù)很簡(jiǎn)單,根據(jù)具體的業(yè)務(wù)需求,選擇其中之一。因?yàn)楦鱾€(gè)接口之間并不存在功能強(qiáng)弱的問(wèn)題。

四、spring data jpa的查詢(xún)

1、使用 @query 創(chuàng)建查詢(xún)

@query 注解的使用非常簡(jiǎn)單,只需在聲明的方法上面標(biāo)注該注解,同時(shí)提供一個(gè) jp ql 查詢(xún)語(yǔ)句即可。很多開(kāi)發(fā)者在創(chuàng)建 jp ql 時(shí)喜歡使用命名參數(shù)來(lái)代替位置編號(hào),@query 也對(duì)此提供了支持。jp ql 語(yǔ)句中通過(guò)": 變量"的格式來(lái)指定參數(shù),同時(shí)在方法的參數(shù)前面使用 @param 將方法參數(shù)與 jp ql 中的命名參數(shù)對(duì)應(yīng)。此外,開(kāi)發(fā)者也可以通過(guò)使用 @query 來(lái)執(zhí)行一個(gè)更新操作,為此,我們需要在使用 @query 的同時(shí),用 @modifying 來(lái)將該操作標(biāo)識(shí)為修改查詢(xún),這樣框架最終會(huì)生成一個(gè)更新的操作,而非查詢(xún)操作。

編寫(xiě)接口,如下:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
/**
 * 描述:自定義查詢(xún),當(dāng)spring data jpa無(wú)法提供時(shí),需要自定義接口,此時(shí)可以使用這種方式
 */
public interface userdefinebyself extends jparepository<user, integer> {
  /**
   * 命名參數(shù)
   * 描述:推薦使用這種方法,可以不用管參數(shù)的位置
   */
  @query("select u from user u where u.name = :name")
  user finduserbyname(@param("name") string name);
   
  /**
   * 索引參數(shù)
   * 描述:使用?占位符
   */
  @query("select u from user u where u.email = ?1")// 1表示第一個(gè)參數(shù)
  user finduserbyemail(string email);
   
  /**
   * 描述:可以通過(guò)@modifying和@query來(lái)實(shí)現(xiàn)更新
   * 注意:modifying queries的返回值只能為void或者是int/integer
   */
  @modifying
  @query("update user u set u.name = :name where u.id = :id")
  int updateuserbyid(@param("name") string name, @param("id") int id);
}

注:@modifying注解里面有一個(gè)配置clearautomatically

它說(shuō)的是可以清除底層持久化上下文,就是entitymanager這個(gè)類(lèi),我們知道jpa底層實(shí)現(xiàn)會(huì)有二級(jí)緩存,也就是在更新完數(shù)據(jù)庫(kù)后,如果后面去用這個(gè)對(duì)象,你再去查這個(gè)對(duì)象,這個(gè)對(duì)象是在一級(jí)緩存,但是并沒(méi)有跟數(shù)據(jù)庫(kù)同步,這個(gè)時(shí)候用clearautomatically=true,就會(huì)刷新hibernate的一級(jí)緩存了, 不然你在同一接口中,更新一個(gè)對(duì)象,接著查詢(xún)這個(gè)對(duì)象,那么你查出來(lái)的這個(gè)對(duì)象還是之前的沒(méi)有更新之前的狀態(tài)

測(cè)試類(lèi):

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
@runwith(springjunit4classrunner.class)
@contextconfiguration(locations = { "classpath:applicationcontext-config.xml" })
@transactionconfiguration(defaultrollback = false)
@transactional
public class userdefinebyselftest {
  @autowired
  private userdefinebyself dao;
   
  @test
  public void testfinduserbyname(){
    user user = dao.finduserbyname("chhliu");
    assert.assertequals("chhliu", user.getname());
    system.out.println(user.getname());
  }
   
  @test
  public void testfinduserbyemail(){
    user user = dao.finduserbyemail("chhliu@.com");
    assert.assertequals("chhliu", user.getname());
    system.out.println(user.getname());
  }
   
  @test
  public void testupdateuserbyid(){
    dao.updateuserbyid("tanjie", 4);
  }
}

從測(cè)試代碼可以看出,我們同樣只定義了接口,沒(méi)有任何的實(shí)現(xiàn)類(lèi),但是卻實(shí)現(xiàn)了我們所需要的功能。

2、使用@namedqueries創(chuàng)建查詢(xún)

命名查詢(xún)是 jpa 提供的一種將查詢(xún)語(yǔ)句從方法體中獨(dú)立出來(lái),以供多個(gè)方法共用的功能。spring data jpa 對(duì)命名查詢(xún)也提供了很好的支持。用戶(hù)只需要按照 jpa 規(guī)范在 orm.xml 文件或者在代碼中使用 @namedquery(或 @namednativequery)定義好查詢(xún)語(yǔ)句,唯一要做的就是為該語(yǔ)句命名時(shí),需要滿足”domainclass.methodname()”的 命名規(guī)則。

編寫(xiě)接口:

?
1
2
3
public interface finduserbynamedqueryrepository extends jparepository<user, integer> {
  user finduserwithname(@param("name") string name);
}

編寫(xiě)類(lèi):

?
1
2
3
4
5
6
7
8
9
10
11
12
13
@entity
@namedqueries(value={
    @namedquery(name="user.finduserwithname",query="select u from user u where u.name = :name")
})
// 注意:此處如果是多個(gè)方法,那么需要使用@namedqueries,如果只有一個(gè)方法,則可以使用@namedquery,寫(xiě)法如下:@namedquery(name="user.finduserwithname",query="select u from user u where u.name = :name")
public class finduserbynamedquery {
  /**
   * 注意:此處必須要給這個(gè)實(shí)體類(lèi)定義一個(gè)唯一標(biāo)識(shí),否則會(huì)報(bào)異常
   */
  @id
  @generatedvalue
  private integer id;
}

注意:文中標(biāo)記為紅色的部分,需要一一對(duì)應(yīng),否則不滿足jpa 的規(guī)范。

測(cè)試類(lèi):

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
@runwith(springjunit4classrunner.class)
@contextconfiguration(locations = { "classpath:applicationcontext-config.xml" })
@transactionconfiguration(defaultrollback = false)
@transactional
public class finduserbynamedqueryrepositorytest {
  @autowired
  private finduserbynamedqueryrepository dao;
   
  @test
  public void testfinduserbyname(){
    user user = dao.finduserwithname("caican");
    system.out.println(json.tojsonstring(user));
  }
}

3、通過(guò)解析方法名創(chuàng)建查詢(xún)

顧名思義,就是根據(jù)方法的名字,就能創(chuàng)建查詢(xún),也許初聽(tīng)起來(lái),感覺(jué)很不可思議,等測(cè)試后才發(fā)現(xiàn),原來(lái)一切皆有可能。

編寫(xiě)接口:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
public interface simpleconditionqueryrepository extends jparepository<user, integer> {
  /**
   * 說(shuō)明:按照spring data 定義的規(guī)則,查詢(xún)方法以find|read|get開(kāi)頭
   * 涉及條件查詢(xún)時(shí),條件的屬性用條件關(guān)鍵字連接,要注意的是:條件屬性首字母需大寫(xiě)
   */   
  /**
   * 注:此處這個(gè)接口相當(dāng)于發(fā)送了一條sql:select u from user u where u.name = :name and u.email = :email
   * 參數(shù)名大寫(xiě),條件名首字母大寫(xiě),并且接口名中參數(shù)出現(xiàn)的順序必須和參數(shù)列表中的參數(shù)順序一致
   */
  user findbynameandemail(string name, string email);
   
  /**
   * 注:此處這個(gè)接口相當(dāng)于發(fā)送了一條sql:select u from user u where u.name = ?1 or u.password = ?2
   */
  list<user> findbynameorpassword(string name, string password);
   
  /**
   * 注:此處這個(gè)接口相當(dāng)于發(fā)送了一條sql:select u from user u where u.id between ?1 and ?2
   */
  list<user> findbyidbetween(integer start, integer end);
   
  /**
   * 注:此處這個(gè)接口相當(dāng)于發(fā)送了一條sql:select u from user u where u.id < ?1
   */
  list<user> findbyidlessthan(integer end);
   
  /**
   * 注:此處這個(gè)接口相當(dāng)于發(fā)送了一條sql:select u from user u where u.id > ?1
   */
  list<user> findbyidgreaterthan(integer start);
   
  /**
   * 注:此處這個(gè)接口相當(dāng)于發(fā)送了一條sql:select u from user u where u.name is null
   */
  list<user> findbynameisnull();
   
  /**
   * 注:此處這個(gè)接口相當(dāng)于發(fā)送了一條sql:select u from user u where u.name is not null
   */
  list<user> findbynameisnotnull();
   
  /**
   * 注:此處這個(gè)接口相當(dāng)于發(fā)送了一條sql:select u from user u where u.name like ?1
   */
  list<user> findbynamelike(string name);
   
  /**
   * 注:此處這個(gè)接口相當(dāng)于發(fā)送了一條sql:select u from user u where u.name not like ?1
   */
  list<user> findbynamenotlike(string name);
   
  /**
   * 注:此處這個(gè)接口相當(dāng)于發(fā)送了一條sql:select u from user u where u.password = ?1 order by u.id desc
   */
  list<user> findbypasswordorderbyiddesc(string password);
   
  /**
   * 注:此處這個(gè)接口相當(dāng)于發(fā)送了一條sql:select u from user u where u.name <> ?1
   */
  list<user> findbynamenot(string name);
   
  /**
   * 注:此處這個(gè)接口相當(dāng)于發(fā)送了一條sql:select u from user u where u.id in ?1
   */
  list<user> findbyidin(list<integer> ids);
   
  /**
   * 注:此處這個(gè)接口相當(dāng)于發(fā)送了一條sql:select u from user u where u.id not in ?1
   */
  list<user> findbyidnotin(list<integer> ids);
}

測(cè)試類(lèi)(注釋部分為實(shí)際發(fā)送的sql語(yǔ)句):

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
@runwith(springjunit4classrunner.class)
@contextconfiguration(locations = { "classpath:applicationcontext-config.xml" })
@transactionconfiguration(defaultrollback = false)
@transactional
public class simpleconditionqueryrepositorytest {
  @autowired
  private simpleconditionqueryrepository dao;
   
  /**
   * select
    user0_.id as id0_,
    user0_.account as account0_,
    user0_.email as email0_,
    user0_.name as name0_,
    user0_.password as password0_
  from
    user user0_
  where
    user0_.name=?
    and user0_.email=? limit ?
   */
  @test
  public void testfinduserbynameandemail(){
    user user = dao.findbynameandemail("chhliu", "chhliu@.com");
    system.out.println(json.tojsonstring(user));
  }
   
  /**
   * select
    user0_.id as id1_,
    user0_.account as account1_,
    user0_.email as email1_,
    user0_.name as name1_,
    user0_.password as password1_
  from
    user user0_
  where
    user0_.name=?
    or user0_.password=?
   */
  @test
  public void testfinduserbynameorpassword(){
    list<user> users = dao.findbynameorpassword("chhliu", "123456");
    system.out.println(json.tojsonstring(users));
  }
   
  /**
   * select
    user0_.id as id1_,
    user0_.account as account1_,
    user0_.email as email1_,
    user0_.name as name1_,
    user0_.password as password1_
  from
    user user0_
  where
    user0_.id between ? and ?
   */
  @test
  public void testfindbyidbetween(){
    list<user> users = dao.findbyidbetween(5, 8);
    system.out.println(json.tojsonstring(users));
  }
   
  /**
   * select
    user0_.id as id1_,
    user0_.account as account1_,
    user0_.email as email1_,
    user0_.name as name1_,
    user0_.password as password1_
  from
    user user0_
  where
    user0_.id<?
   */
  @test
  public void testfindbyidlessthan(){
    list<user> users = dao.findbyidlessthan(4);
    system.out.println(json.tojsonstring(users));
  }
   
  /**
   * select
    user0_.id as id0_,
    user0_.account as account0_,
    user0_.email as email0_,
    user0_.name as name0_,
    user0_.password as password0_
  from
    user user0_
  where
    user0_.id>?
   */
  @test
  public void testfindbyidgreaterthan(){
    list<user> users = dao.findbyidgreaterthan(6);
    system.out.println(json.tojsonstring(users));
  }
   
  /**
   * select
    user0_.id as id0_,
    user0_.account as account0_,
    user0_.email as email0_,
    user0_.name as name0_,
    user0_.password as password0_
  from
    user user0_
  where
    user0_.name is null
   */
  @test
  public void testfindbynameisnull(){
    list<user> users = dao.findbynameisnull();
    system.out.println(json.tojsonstring(users));
  }
   
  /**
   * select
    user0_.id as id1_,
    user0_.account as account1_,
    user0_.email as email1_,
    user0_.name as name1_,
    user0_.password as password1_
  from
    user user0_
  where
    user0_.name is not null
   */
  @test
  public void testfindbynameisnotnull(){
    list<user> users = dao.findbynameisnotnull();
    system.out.println(json.tojsonstring(users));
  }
   
  /**
   * select
    user0_.id as id1_,
    user0_.account as account1_,
    user0_.email as email1_,
    user0_.name as name1_,
    user0_.password as password1_
  from
    user user0_
  where
    user0_.name like ?
   */
  @test
  public void testfindbynamelike(){
    list<user> users = dao.findbynamelike("chhliu");
    system.out.println(json.tojsonstring(users));
  }
   
  /**
   * select
    user0_.id as id0_,
    user0_.account as account0_,
    user0_.email as email0_,
    user0_.name as name0_,
    user0_.password as password0_
  from
    user user0_
  where
    user0_.name not like ?
   */
  @test
  public void testfindbynamenotlike(){
    list<user> users = dao.findbynamenotlike("chhliu");
    system.out.println(json.tojsonstring(users));
  }
   
  /**
   * select
    user0_.id as id0_,
    user0_.account as account0_,
    user0_.email as email0_,
    user0_.name as name0_,
    user0_.password as password0_
  from
    user user0_
  where
    user0_.password=?
  order by
    user0_.id desc
   */
  @test
  public void testfindbypasswordorderbyiddesc(){
    list<user> users = dao.findbypasswordorderbyiddesc("123456");
    system.out.println(json.tojsonstring(users));
  }
   
  /**
   * select
    user0_.id as id1_,
    user0_.account as account1_,
    user0_.email as email1_,
    user0_.name as name1_,
    user0_.password as password1_
  from
    user user0_
  where
    user0_.name<>?
   */
  @test
  public void testfindbynamenot(){
    list<user> users = dao.findbynamenot("chhliu");
    system.out.println(json.tojsonstring(users));
  }
   
  /**
   * select
    user0_.id as id1_,
    user0_.account as account1_,
    user0_.email as email1_,
    user0_.name as name1_,
    user0_.password as password1_
  from
    user user0_
  where
    user0_.id in (
      ? , ? , ? , ?
    )
   */
  @test
  public void testfindbyidin(){
    list<user> users = dao.findbyidin(new arraylist<integer>(arrays.aslist(3,4,6,8)));
    system.out.println(json.tojsonstring(users));
  }
   
  /**
   * select
    user0_.id as id0_,
    user0_.account as account0_,
    user0_.email as email0_,
    user0_.name as name0_,
    user0_.password as password0_
  from
    user user0_
  where
    user0_.id not in (
      ? , ? , ? , ?
    )
   */
  @test
  public void testfindbyidnotin(){
    list<user> users = dao.findbyidnotin(new arraylist<integer>(arrays.aslist(3,4,6,8)));
    system.out.println(json.tojsonstring(users));
  }
}

這里,我們只定義了一個(gè)接口,接口里面只有方法,但是沒(méi)有任何的實(shí)現(xiàn),卻完成了各種操作。

看到這里,估計(jì)很多人都會(huì)問(wèn),spring data jpa是怎么做到的了?原來(lái),框架在進(jìn)行方法名解析時(shí),會(huì)先把方法名多余的前綴截取掉,比如 find、findby、read、readby、get、getby,然后對(duì)剩下部分進(jìn)行解析。并且如果方法的最后一個(gè)參數(shù)是 sort 或者 pageable 類(lèi)型,也會(huì)提取相關(guān)的信息,以便按規(guī)則進(jìn)行排序或者分頁(yè)查詢(xún)。在創(chuàng)建查詢(xún)時(shí),我們通過(guò)在方法名中使用屬性名稱(chēng)來(lái)表達(dá),比如 findbyidin()。框架在解析該方法時(shí),首先剔除 findby,然后對(duì)剩下的屬性進(jìn)行解析。

在查詢(xún)時(shí),通常需要同時(shí)根據(jù)多個(gè)屬性進(jìn)行查詢(xún),且查詢(xún)的條件也格式各樣(大于某個(gè)值、在某個(gè)范圍等等),spring data jpa 為此提供了一些表達(dá)條件查詢(xún)的關(guān)鍵字,大致如下:

and --- 等價(jià)于 sql 中的 and 關(guān)鍵字,比如 findbyusernameandpassword(string user, striang pwd)

or --- 等價(jià)于 sql 中的 or 關(guān)鍵字,比如 findbyusernameoraddress(string user, string addr)

between --- 等價(jià)于 sql 中的 between 關(guān)鍵字,比如 findbysalarybetween(int max, int min)

lessthan --- 等價(jià)于 sql 中的 "<",比如 findbysalarylessthan(int max)

greaterthan --- 等價(jià)于 sql 中的">",比如 findbysalarygreaterthan(int min)

isnull --- 等價(jià)于 sql 中的 "is null",比如 findbyusernameisnull()

isnotnull --- 等價(jià)于 sql 中的 "is not null",比如 findbyusernameisnotnull()

notnull --- 與 isnotnull 等價(jià)

like --- 等價(jià)于 sql 中的 "like",比如 findbyusernamelike(string user)

notlike --- 等價(jià)于 sql 中的 "not like",比如 findbyusernamenotlike(string user)

orderby ---等價(jià)于 sql 中的 "order by",比如 findbyusernameorderbysalaryasc(string user)

not --- 等價(jià)于 sql 中的 "! =",比如 findbyusernamenot(string user)

in --- 等價(jià)于 sql 中的 "in",比如 findbyusernamein(collection<string> userlist) ,方法的參數(shù)可以是 collection 類(lèi)型,也可以是數(shù)組或者不定長(zhǎng)參數(shù)

notin --- 等價(jià)于 sql 中的 "not in",比如 findbyusernamenotin(collection<string> userlist) ,方法的參數(shù)可以是 collection 類(lèi)型,也可以是數(shù)組或者不定長(zhǎng)參數(shù)

五、創(chuàng)建查詢(xún)的順序

spring data jpa 在為接口創(chuàng)建代理對(duì)象時(shí),如果發(fā)現(xiàn)同時(shí)存在多種上述情況可用,它該優(yōu)先采用哪種策略呢?為此,<jpa:repositories> 提供了 query-lookup-strategy 屬性,用以指定查找的順序。它有如下三個(gè)取值:

create --- 通過(guò)解析方法名字來(lái)創(chuàng)建查詢(xún)。即使有符合的命名查詢(xún),或者方法通過(guò) @query 指定的查詢(xún)語(yǔ)句,都將會(huì)被忽略。

create-if-not-found --- 如果方法通過(guò) @query 指定了查詢(xún)語(yǔ)句,則使用該語(yǔ)句實(shí)現(xiàn)查詢(xún);如果沒(méi)有,則查找是否定義了符合條件的命名查詢(xún),如果找到,則使用該命名查詢(xún);如果兩者都沒(méi)有找到,則通過(guò)解析方 法名字來(lái)創(chuàng)建查詢(xún)。這是 query-lookup-strategy 屬性的默認(rèn)值。

use-declared-query --- 如果方法通過(guò) @query 指定了查詢(xún)語(yǔ)句,則使用該語(yǔ)句實(shí)現(xiàn)查詢(xún);如果沒(méi)有,則查找是否定義了符合條件的命名查詢(xún),如果找到,則使用該命名查詢(xún);如果兩者都沒(méi)有找到,則拋出異常。

六、spring data jpa 對(duì)事務(wù)的支持

細(xì)心的讀者也許從上面的代碼中看出了一些端倪,我們?cè)谑褂胹pring data jpa的時(shí)候,只是定義了接口,在使用的時(shí)候,直接注入就可以了,并沒(méi)有做與事物相關(guān)的任何處理,但實(shí)際上,事物已經(jīng)起到效果了,這又是為什么了?

默認(rèn)情況下,spring data jpa 實(shí)現(xiàn)的方法都是使用事務(wù)的。針對(duì)查詢(xún)類(lèi)型的方法,其等價(jià)于 @transactional(readonly=true);增刪改類(lèi)型的方法,等價(jià)于 @transactional。可以看出,除了將查詢(xún)的方法設(shè)為只讀事務(wù)外,其他事務(wù)屬性均采用默認(rèn)值。

如果用戶(hù)覺(jué)得有必要,可以在接口方法上使用 @transactional 顯式指定事務(wù)屬性,該值覆蓋 spring data jpa 提供的默認(rèn)值。同時(shí),開(kāi)發(fā)者也可以在業(yè)務(wù)層方法上使用 @transactional 指定事務(wù)屬性,這主要針對(duì)一個(gè)業(yè)務(wù)層方法多次調(diào)用持久層方法的情況。持久層的事務(wù)會(huì)根據(jù)設(shè)置的事務(wù)傳播行為來(lái)決定是掛起業(yè)務(wù)層事務(wù)還是加入業(yè)務(wù)層的事務(wù)。

以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持服務(wù)器之家。

原文鏈接:https://blog.csdn.net/liuchuanhong1/article/details/52042477

延伸 · 閱讀

精彩推薦
主站蜘蛛池模板: 五月婷婷在线视频 | 亚洲免费一区二区 | 国产美女精品视频免费观看 | 91色在线 | 久草视频国产 | 亚洲热妇 | 99久久精品国产一区二区三区 | 国产精品久久久久久久久久久久午夜片 | 中文字幕亚洲国产 | 黄频免费在线观看 | 欧美日韩在线看 | 99re热精品视频 | 九色国产 | 中文字幕高清在线 | av成人在线电影 | 亚洲精品欧美在线 | 亚洲经典一区 | 日本涩涩视频 | 在线视频 中文字幕 | 成人a视频在线观看 | 精品一区国产 | 青青草国产 | 日韩视频三区 | 欧美日韩综合视频 | 日韩黄网站 | 综合久久综合久久 | 黄色网址免费 | 欧美1区2区 | 秋霞特色aa大片 | 欧美电影免费网站 | 国产黄 | 日韩在线视频一区 | 午夜电影| av小说在线观看 | 在线精品国产 | 亚洲视频区 | 国产亚洲一区二区三区 | 成人激情在线 | 国产精品日韩高清伦字幕搜索 | 久久久精品呻吟 | 亚洲精品91|