1. 程式人生 > >SpringBoot第二講 利用Spring Data JPA實現資料庫的訪問(一)

SpringBoot第二講 利用Spring Data JPA實現資料庫的訪問(一)

在基本瞭解了springboot的執行流程之後,我們需要逐個來突破springboot的幾個關鍵性問題,我們首先解決的是springboot訪問資料庫的問題。Java訪問資料庫經歷了幾個階段,第一個階段是直接通過JDBC訪問,這種方式工作量極大,而且會做大量的重複勞動,之後出現了一些現成的ORM框架,如hibernate、Mybatis等,這些框架封裝了大量的資料庫的訪問操作,但是我們依然要對這些框架進行二次封裝。如今spring Data幫助我們解決了資料庫的操作的問題,Spring Data還提供了一套JPA介面幫助我們可以非常簡單實現基於關係資料庫的訪問操作。如下圖所示:

利用spring DATA JPA實現資料庫訪問 
Spring Data JPA等於在ORM之上又進行了一次封裝,但具體的對資料庫的訪問依然要依賴於底層的ORM框架,Spring Data JPA預設是通過Hibernate實現的,接下來我們就來看看Spring Data JPA如何訪問我們的資料庫和如何簡化我們的操作的。

第一步建立一個Springboot的專案,並且新增Spring Data JPA的支援

這個操作可以直接在start.spring.io網站中建立,並且新增JPA的支援。這個專案我們可以考慮不使用Web。

利用spring DATA JPA實現資料庫訪問

之後建立一個專案,拷貝maven的依賴。

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation
="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion> <groupId>org.konghao</groupId> <artifactId>hello-jpa</artifactId> <version>1.0-SNAPSHOT</version> <parent> <groupId
>
org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>1.4.2.RELEASE</version> <relativePath/> <!-- lookup parent from repository --> </parent> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> <java.version>1.8</java.version> </properties> <dependencies> <!-- spring data jpa的依賴--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-jpa</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> </dependencies> </project>
  • 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
  • 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

pom.xml設定完成之後,我們會發現依賴包中有了hibernate的jar檔案,這就說明spring data jpa預設就是使用hibernate框架來作為底層的ORM。

為了可以相對快速的上手spring Data,我們這裡就建立一個Student的Model物件。

//Student
*/
/*
* 以下兩個程式碼其實就是Hiberate宣告實體的annotation
* */
@Entity
@Table(name="t_stu")
public class Student {

    @Id()
    @GeneratedValue(strategy = GenerationType.AUTO)
    private int id;
    private String name;
    private String address;
    private int age;
    ....
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17

以上程式碼我省略其中的getter和settter方法,建立完實體類之後,這個實體類上的annotation都是原來hibernate中常用的,就不一一講解了。之後在resources資料夾中配置appication.properties檔案,這是springboot的主配置檔案,此時我們配置和資料庫訪問相關的內容,我們使用的是hibernate,所以就配置和hibernate相關的內容


#開啟包的自動掃描
entitymanager.packagesToScan= org.konghao.model
# 資料庫連線
spring.datasource.url=jdbc:mysql://localhost:3306/springboot
# 使用者名稱
spring.datasource.username=root
# 密碼
spring.datasource.password=123
# 資料庫驅動
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
# 自動更新表
spring.jpa.properties.hibernate.hbm2ddl.auto=update
# 使用MYSQL5作為資料庫訪問方言
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL5Dialect
#顯示sql語句
spring.jpa.properties.hibernate.show_sql=true
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17

注意原來和hibernate的配置都改成了以spring.jpa.properties.hiberate.xx,此時由於使用了MySQL,所以還得匯入mysql的connector

<dependency>
   <groupId>mysql</groupId>
   <artifactId>mysql-connector-java</artifactId>
</dependency>
  • 1
  • 2
  • 3
  • 4
  • 1
  • 2
  • 3
  • 4

有沒有發現我們不用設定版本,由於繼承了>org.springframework.boot,它會自動幫助我們匹配一個合適的connector來專案中的。到此和資料庫配置相關的所有任務就結束了。

接下來就讓我們開始訪問資料庫吧,在原來的方式中,我們需要為每一個物件建立自己的DAO介面,然後寫一個實現類基礎我們自己封裝好的BaseDao,然後完成資料物件的CRUD等操作,如今Spring Data JPA幫我們完成了這個工作,我們首先看一下Spring Data JPA中的幾個介面

利用spring DATA JPA實現資料庫訪問

最高層的Repository<T,ID>是一個空介面,我們定義的資料訪問類只要實現這個介面,這個資料訪問類就可以被spring data所管理,就此可以使用spring為我們提供操作方法(在原來的spring data中我們需要配置很多和Spring Data Repository相關的設定,但是現在有了spring boot,全部都已經自動配置好了)。這個介面要實現有兩個泛型引數,第一個T表示實體類,第二個表示主鍵的型別,我們寫一個數據庫訪問介面。

public interface StudentRepository extends Repository<Student,Integer> {

    @Query("select s from Student s where s.id=?1")
    public Student loadById(int id);

    //根據地址和年齡進行查詢
    public List<Student> findByAddressAndAge(String address, int age);
    //根據id獲取物件,即可返回物件,也可以返回列表
    public Student readById(int id);
    //根據id獲取列表,這裡如果確定只有一個物件,也可以返回物件
    public List<Student> getById(int id);
    //根據id獲取一個物件,同樣也可以返回列表
    public Student findById(int id);
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

這個介面實現了Repository介面,我們定義了兩個方法,這兩個方法代表Repository使用的一種基本方法,第一個方法增加了一個Query的annotation,通過這個宣告,Spring Data JPA就知道該使用什麼HQL去查詢資料,?1表示用方法中的第一個引數。第二個函式我們並沒有定義任何的Annotation,但是它也可以查詢得出來,在Spring Data JPA中提供了一種衍生查詢,只要函式的宣告有findBy,getBy,readBy,他就會去讀取,findByAddressAnAge表示根據address和age進行查詢,方法的第一個引數就是address,第二個引數就是age,readByXX,getByXX都是一樣的道理,這些方法的返回值可以是一個列表,也可以是一個物件,spring Data JPA會自動根據返回型別來進行處理。我們不用寫實現類,Spring Data JPA會自動幫助我們實現查詢。很多時候在專案中會用到這些簡單的查詢,但是不得不寫個方法來實現,但是現在使用了Spring Data JPA之後,這個操作被完全簡化了。接著看一下測試類的實現。

@RunWith(SpringRunner.class)
@SpringBootTest
public class DemoApplicationTests {
    //注入剛才定義的介面
    @Autowired
    private StudentRepository studentRepository;

    @Test
    public void testStudent() {
        Assert.assertEquals("foo",studentRepository.findById(1).getName());
        Assert.assertEquals("foo",studentRepository.readById(1).getName());
        Assert.assertEquals(1,studentRepository.getById(1).size());
        Assert.assertEquals("foo",studentRepository.loadById(1).getName());
        Assert.assertEquals(2,studentRepository.findByAddressAndAge("zt",22).size());
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16

現在應該對Spring Data JPA有了基本瞭解了吧,我們再看看剛才那張圖,CRUDRepository實現了CRUD的方法,PagingAndSortingRepository在CRUD的基礎上擴充套件了分頁和排序的功能,而JpaRepository同樣擴充套件了一些方法方便我們查詢。

我們先看看CRUDRepository這個介面,這個接口裡面提供了CRUD的基本操作,使用非常的簡單。

public interface StudentCrudRepository extends CrudRepository<Student,Integer>{
    //增加了一個countByXX的方法
    public long countByAge(int age);
}
  • 1
  • 2
  • 3
  • 4
  • 1
  • 2
  • 3
  • 4

測試程式碼

@Test
    public void testAddStudent() {
        //新增操作
        Student stu = new Student("foo1","km",22);
        studentCrudRepository.save(stu);
    }

    @Test
    public void testUpdateStudent() {
        /*修改的操作*/
        Student stu = studentCrudRepository.findOne(1);
        stu.setName("bar1");
        studentCrudRepository.save(stu);
    }

    @Test
    public void testDelete() {
        //刪除操作
        studentCrudRepository.delete(1);
    }

    @Test
    public void testCount() {
        //取數量操作
        Assert.assertEquals(3,studentCrudRepository.count());
        Assert.assertEquals(2,studentCrudRepository.countByAge(22));
    }
  • 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
  • 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

通過這個例子我們應該已經感受了Spring Data JPA如何簡化了我們的資料庫訪問操作了吧!這一部分先講到這裡,下一講我們實現分頁,排序和更多的JPA查詢功能。