<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                在前面的章節中,我們在`spring data JPA`的幫助下,使用`Teacher`類來映射了`teacher`表,使用`Klass`類來映射了`klass`表。本節中我們繼續展示`spring data JPA`在數據操作上強大的能力。 由于`Teacher`類定義了相關的屬性以及為這些屬性定義了相應的類型,所以`spring data JPA`才能夠根據`Teacher`類來對應生成相關的`teacher`表。故與其說我們前面講的`Teacher`類是對應`teacher` 表,不如說`Teacher`類映射的是`teacher`表**結構**。 | 序號 | JAVA類 | 數據表 | | --- | --- | --- | | 1 | 類名Teacher | 表名teacher | | 2 | 屬性名id | 字段名id | | 3 | 屬性類型Long | 字段類型bigint(long) | 在數據庫中,一張數據表主要以下述兩種要素組成:①表的定義(字段、外健、索引等);②表中所存儲的數據。下面,讓我們共同學習`spring data JPA`是如何處理表中的存儲數據的。 # Repository `Repository`直譯為`倉庫`,在`spring data JPA`中將存儲了數據的表看做一座數據倉庫,我們可以由這個倉庫中取數據,也可以在這個倉庫中添加數據,同時也可以進行刪除、修改的操作。如想建`klass`數據表對應的倉庫,則需要進行如下操作: 首先同controller及entity一樣,我們建立repository包。 ### 初始化JAVA接口文件 repository/KlassRepository.java ```java package com.mengyunzhi.springBootStudy.repository; import com.mengyunzhi.springBootStudy.entity.Klass; import org.springframework.data.repository.CrudRepository; /** * 班級倉庫 */ public interface? KlassRepository? extends? CrudRepository?<Klass?, Long?>{ } ``` * ? 類型定義為interface接口 * ? 按規范命名為`數據表名`+`Repository`(該命名僅為了方便記憶) * ? 該接口extends繼承CrudRepository?接口的同時,繼承了CrudRepository對數據表操作的功能。 * ? 該數據倉庫對應對Klass類對應的klass數據表進行操作 * ? 該數據表的主鍵類型為Long ### 自定義查詢方法 接本節定義的前后臺對接接口,我們需要將班級名稱中包括前臺傳入的值的所有班級數據查詢出來,那么我們可以在KlassRepository中如下定義查詢方法: repository/KlassRepository.java ```java import java.util.List; ... public interface KlassRepository extends CrudRepository<Klass, Long>{ List<Klass>? findAllByNameContains?(String name?); } ``` * ? 定義返回值為`List<Klass>`來說明我要查詢多條班級數據。 * ? 定義方法名為:查詢出字段`name`中包含有第一個參數的所有數據。 * ? 定義第一個傳入參數的類型。 ### 調用 我們來到想對班級表進行查詢操作的controller/KlassController中,使用下面的方法進行數據表的查詢操作: controller/KlassController.java ``` import org.springframework.beans.factory.annotation.Autowired; @RestController @RequestMapping("Klass") public class KlassController { private static final Logger logger = LoggerFactory.getLogger(KlassController.class); @Autowired ? KlassRepository klassRepository; @GetMapping public List<Klass> getAll(@RequestParam String name) { return this.klassRepository.findAllByNameContains(name);? } } ``` * ? 自動的向當前對象中注入一個實現了KlassRepository接口的對象。 * ? 調用該對象的findAllByNameContains()方法來完成數據的查詢操作并返回。 ***** 在面向對象的語言中,我們學習過通過`new`關鍵字來由`類`來實例化一個供我們使用的對象。`Spring boot`是面向接口開發的框架,它為我們管理了大多數的對象,所以`new`操作發生在了`Spring boot`框架的底層,而我們在使用該框架的過程中,只需要通過`@Autowired`來告知它我們需要一個什么功能的對象即可。就也就是所謂的`ioc 控制反轉` ---- 以前我們在編寫代碼的過程中來管理對象,現在這個管理對象的任務卻**反轉為**框架來完成了。 ***** ### 刪除冗余的配置項 由于`spring data jpa`已經包含了`JDBC`,所以我們此時可以在`pom.xml`刪除原來對`jdbc`依賴了。 pom.xml ``` <dependencies> <dependency> ? <groupId>org.springframework.boot</groupId> ? <artifactId>spring-boot-starter-data-jdbc</artifactId> ? </dependency> ? ``` 原則上,如果你不刪除該依賴也不應該出現問題。但實際的情況是,如果你不刪除該依賴則在應用啟動時會出現以下錯誤: **以下內容選讀** ``` org.springframework.beans.factory.support.BeanDefinitionOverrideException: Invalid bean definition with name 'klassRepository' defined in null: Cannot register bean definition [Root bean: class [org.springframework.data.jpa.repository.support.JpaRepositoryFactoryBean]; scope=; abstract=false; lazyInit=false; autowireMode=0; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodName=null; destroyMethodName=null] for bean 'klassRepository': There is already [Root bean: class [org.springframework.data.jdbc.repository.support.JdbcRepositoryFactoryBean]; scope=; abstract=false; lazyInit=false; autowireMode=0; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodName=null; destroyMethodName=null] bound. ``` 它的意思是說:在進行對象管理的時候進行新的對象注冊的時候,發現了重名的對象klassRepository。這個原因我猜測是由于:由`JPA`管理的`JpaRepositoryFactoryBean`以與由`JDBC`管理的`JdbcRepositoryFactoryBean`分別掃描到了`KlassRepository`。他們兩個都想把它注冊到`spring`統一管理的對象中,但該對象只允許存在一個,所以就報錯了。解決該問題也可以在配置文件中增加一行:`spring.main.allow-bean-definition-overriding=true`,意思是說如果發現有重名的了,就用后面的覆蓋前面的。此做法并不推薦。 ## 測試 我們重新啟動應用,然后在數據表中添加2條測試數據,并重新運行測試: 教師表: ![](https://img.kancloud.cn/91/7e/917e4a003140ac08bdb72a9baf878ee5_685x120.png) 班級表: ![](https://img.kancloud.cn/7e/41/7e41f42453d04f1fadd11d972a2489a3_478x163.png) 當name為hello,返回0條數據: ``` GET http://localhost:8080/Klass?name=hello HTTP/1.1 200 Content-Type: application/json;charset=UTF-8 Transfer-Encoding: chunked Date: Mon, 04 Nov 2019 07:08:15 GMT [] Response code: 200; Time: 260ms; Content length: 2 bytes ``` 當name為空時,返回3條數據: ``` GET http://localhost:8080/Klass?name= HTTP/1.1 200 Content-Type: application/json;charset=UTF-8 Transfer-Encoding: chunked Date: Mon, 04 Nov 2019 07:09:47 GMT [ { "id": 1, "name": "測試1" }, { "id": 2, "name": "測試2" }, { "id": 3, "name": "其它" } ] Response code: 200; Time: 59ms; Content length: 66 bytes ``` 當name為`測試`時,返回2條數據 ``` GET http://localhost:8080/Klass?name=%E6%B5%8B%E8%AF%95 HTTP/1.1 200 Content-Type: application/json;charset=UTF-8 Transfer-Encoding: chunked Date: Mon, 04 Nov 2019 07:10:17 GMT [ { "id": 1, "name": "測試1" }, { "id": 2, "name": "測試2" } ] Response code: 200; Time: 23ms; Content length: 45 bytes ``` 當name為`其它`時返回1條數據 ``` GET http://localhost:8080/Klass?name=%E5%85%B6%E5%AE%83 HTTP/1.1 200 Content-Type: application/json;charset=UTF-8 Transfer-Encoding: chunked Date: Mon, 04 Nov 2019 07:10:49 GMT [ { "id": 3, "name": "其它" } ] Response code: 200; Time: 25ms; Content length: 22 bytes ``` 當name為 `試`時,返回2條數據: ``` GET http://localhost:8080/Klass?name=%E8%AF%95 HTTP/1.1 200 Content-Type: application/json;charset=UTF-8 Transfer-Encoding: chunked Date: Mon, 04 Nov 2019 07:11:20 GMT [ { "id": 1, "name": "測試1" }, { "id": 2, "name": "測試2" } ] Response code: 200; Time: 21ms; Content length: 45 bytes ``` ### SETER/GETER 對照我們自己定義的接口,剛剛的測試貌似完全的滿足了我們的要求。但問題是我們在前面想顯示的為如下數據: ![](https://img.kancloud.cn/a1/45/a14529f39b75ae4cfd7cf058026f5ada_644x448.png) 而返回的數據當中,我們并沒有看到`教師`的信息,這樣的數據返回給前臺必然是無法滿足實際需求的。這一問題的出現,暴露了以下問題: **在接口的定義過程中,返回數據的值定義的過于寬泛,在細節上沒有實際的指導意義。這為以后的BUG埋下的伏筆!** 這個問題產生的原因在這: entity/Klass.java ``` package com.mengyunzhi.springBootStudy.entity; import javax.persistence.*; @Entity public class Klass { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; @ManyToOne private Teacher teacher; private String name; public Klass() { } public Long getId() { return id; } public void setId(Long id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } } ``` 通過觀察此文件我們發現,`teacher`屬性是沒有`setter`及`getter`方法的。為了更好的說明`setter`及`getter`在整個程序執行過程中發揮的作用,我們依次添加`getter`及`setter`函數: #### GETTER與SETTER entity/Klass.java ``` public Teacher getTeacher() { return teacher; } public void setTeacher(Teacher teacher) { this.teacher = teacher; } ``` 然后重新運行后臺、重新添加測試數據后重新測試: ``` GET http://localhost:8080/Klass?name=%E6%B5%8B%E8%AF%95 HTTP/1.1 200 Content-Type: application/json;charset=UTF-8 Transfer-Encoding: chunked Date: Mon, 04 Nov 2019 08:22:42 GMT [ { "id": 1, "teacher": { "id": 1, "name": "張三更新", "sex": false, "username": "newzhangsan", "email": "newzhangsan@yunzhiclub.com", "createTime": null, "updateTime": null }, "name": "測試1" }, { "id": 2, "teacher": { "id": 1, "name": "張三更新", "sex": false, "username": "newzhangsan", "email": "newzhangsan@yunzhiclub.com", "createTime": null, "updateTime": null }, "name": "測試2" } ] Response code: 200; Time: 164ms; Content length: 331 bytes ``` 測試結果中返回了教師數據,依此我們可以得出結論: ** 如果沒有setter與getter方法,查詢到的數據將無法返回給前臺。** ## 請測試 那么到底是getter還是setter在真正的起做用呢?先猜猜,然后自己測試一下來驗證自己的猜測結果。 # 參考文檔 | 名稱 | 鏈接 | 預計學習時長(分) | | --- | --- | --- | | 源碼地址 | [https://github.com/mengyunzhi/spring-boot-and-angular-guild/releases/tag/step3.2.9](https://github.com/mengyunzhi/spring-boot-and-angular-guild/releases/tag/step3.2.9) | - | | Accessing data with MySQL | [https://spring.io/guides/gs/accessing-data-mysql/](https://spring.io/guides/gs/accessing-data-mysql/)| 15 |
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看