1. 程式人生 > >SpringBoot-SpringData-JPA整合

SpringBoot-SpringData-JPA整合

資料庫訪問這一層 常用的方式有:JdbcTemplate ,SpringData-JPA, MyBatis
今天我們說一下SpringData-JPA, 使用上一篇SpringBoot-JUnit作為基礎程式碼

注:本文使用的例子來自DD程式設計師,旨在學習,為了防止爭議,本文改為轉載

Spring-data-jpa的優勢

開發中對資料庫的操作大多為增刪改查,開發者重複大量且枯燥的程式碼來實現這部分邏輯
Spring-data-jpa使資料訪問層變成只是一層介面的編寫方式

Spring-data-jpa 只需要一個繼承了JpaRepository的介面就能實現資料的訪問

public
interface UserRepository extends JpaRepository<User, Long> { User findByName(String name); @Query("from User u where u.name=:name") User findUser(@Param("name") String name); }

專案結構

專案結構

SpringBoot整合SpringData-JPA依賴

在pom.xml中新增依賴(以MySql資料庫為例):

<!-- SpringData-Jpa依賴-->
<dependency <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-jpa</artifactId> </dependency> <!-- mysql驅動:com.mysql.jdbc.Driver --> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId
>
<version>5.1.29</version> </dependency>

資料庫連線配置

application.xml中配置資料庫連線資訊,自動建立表結構設定

spring.datasource.url=jdbc:mysql://localhost:3306/test
spring.datasource.username=root
spring.datasource.password=123
spring.datasource.driver-class-name=com.mysql.jdbc.Driver

spring.jpa.properties.hibernate.hbm2ddl.auto=create-drop

Spring-data-jpa依賴於Hibernate
spring.jpa.properties.hibernate.hbm2ddl.auto是hibernate的配置屬性
主要作用是:自動建立、更新、驗證資料庫表結構

引數配置介紹:

create:
    每次載入hibernate時都會刪除上一次的生成的表,
    然後根據model類重新生成表,哪怕沒有改變,
    這是導致資料庫表資料丟失的一個重要原因。

create-drop:
    每次載入hibernate時根據model類生成表,但sessionFactory關閉時,表自動刪除。

update:最常用
    首次載入hibernate時根據model類自動建立起表結構(要先建立資料庫)
    以後載入hibernate時根據model類自動更新表結構,即使表結構變了,老資料不刪除。
    注意:當部署到伺服器後,表結構不會立即建立起來,應用首次執行後才會建立表結構。

validate:
    每次載入hibernate時,驗證建立資料庫表結構,和資料庫表比較,不建立新表,會插入新值。

建立domain

建立User實體,會被對映到資料庫
根據配置項 hibernate.hbm2ddl.auto,應用啟動時自動建立表

import javax.persistence.*;
@Entity
public class User {

    // 沒有預設構造會報錯
    public User(){

    }

    public User(String name, Integer age) {
        this.name = name;
        this.age = age;
    }

    @Id
    @GeneratedValue
    private Long id;

    @Column(nullable = false)
    private String name;

    @Column(nullable = false)
    private Integer age;

    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;
    }

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }

}

建立資料訪問介面(原DAO層)

一般的,對於資料訪問層,需要建立一個介面來規定對資料操作的一系列方法,再建立DAO來實現此介面,從而實現對資料庫的訪問

而Spring-data-jpa,對資料訪問,只需繼承Spring-data-jpa提供的介面(這裡以JpaRepository為例)即可完成對資料的訪問

public interface UserRepository extends JpaRepository<User, Long> {

    User findByName(String name);

    User findByNameAndAge(String name, Integer age);

    @Query("from User u where u.name=:name")
    User findUser(@Param("name") String name);

}

以上即可實現資料庫的訪問,無需再寫實現類

先發一個截圖說明一下SpringData-JPA介面(後續會詳細說明)

SpringData-JPA介面

這裡的JpaRepository介面實現的資料庫操作方法

@NoRepositoryBean
public interface JpaRepository<T, ID extends Serializable> extends PagingAndSortingRepository<T, ID> {
    List<T> findAll();

    List<T> findAll(Sort var1);

    List<T> findAll(Iterable<ID> var1);

    <S extends T> List<S> save(Iterable<S> var1);

    void flush();

    <S extends T> S saveAndFlush(S var1);

    void deleteInBatch(Iterable<T> var1);

    void deleteAllInBatch();

    T getOne(ID var1);
}

SpringData特性-通過解析方法名建立查詢

public interface UserRepository extends JpaRepository<User, Long> {

    User findByName(String name);

    User findByNameAndAge(String name, Integer age);

}

以上查詢使用者的兩個方法,沒有寫任何Sql,僅在介面層就完成了資料庫查詢動作
這是SpringData-JPA的一個特性-通過解析方法名建立查詢

除了解析方法名建立查詢,還提供註解建立查詢(@Query)
只需寫JPQL語句,通過類似“:name”對映@Param指定的引數即可

public interface UserRepository extends JpaRepository<User, Long> {

    User findByName(String name);

    @Query("from User u where u.name=:name")
    User findUser(@Param("name") String name);// 引數name 對映到資料庫欄位name

}

當然,SpringData-JPA給開發者帶來的便利遠不止以上這寫,這裡暫時只介紹SpringData-JPA的整合

單元測試

@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(Application.class)
public class ApplicationTests {

    @Autowired
    private UserRepository userRepository;

    @Test
    public void test() throws Exception {

        // 建立測試資料
        userRepository.save(new User(“Test1", 10));
        userRepository.save(new User("Test2", 20));
        userRepository.save(new User("Test3", 30));
        userRepository.save(new User("Test4", 40));
        userRepository.save(new User("Test5", 50));

        // 測試findAll, 查詢所有記錄
        Assert.assertEquals(5, userRepository.findAll().size());

        // 測試findByName, 查詢姓名為Test2的User.Age=20
        Assert.assertEquals(20, userRepository.findByName("Test2").getAge().longValue());

        // 測試findUser, 查詢姓名為Test3的User.Age=30
        Assert.assertEquals(30, userRepository.findUser("Test3").getAge().longValue());

        // 測試findByNameAndAge, 查詢姓名為Test4並且年齡為40的User
        Assert.assertEquals("Test4", userRepository.findByNameAndAge("Test4", 40).getName());

        // 測試刪除姓名為Test5的User
        userRepository.delete(userRepository.findByName("Test5"));

        // 測試findAll, 刪除後為4條記錄
        Assert.assertEquals(4, userRepository.findAll().size());

    }

}

測試結果:

測試結果

SpringBoot後續連載展望

至此SpringData的整合已經完成,後續計劃陸續更新SpringData相關文章,如:

建立表,一對多和多對一對映以及懶載入等問題
SpringData介面繼承關係和作用
各種註解的作用,如:更新操作,事務等
操作資料庫方法的規範,自己寫SQL的方式
SpringData多資料來源的實現

目前只想到這些相關的,也是專案中必知必會的
後面先繼續更新SpringBoot,上面的相關知識隨著用到進行連載

程式碼下載

維護記錄:
20170427:
修改描述錯誤: 遍歷->便利
修改@Query註解建立查詢-程式碼段錯誤