Spring Data JDBC 簡介

工程 | Jens Schauder | 2018 年 9 月 17 日 | ...

隨著即將釋出的 Lovelace GA 版本,我們將推出一個新的 Spring Data 模組:Spring Data JDBC

Spring Data JDBC 的理念是提供對關係資料庫的訪問,同時避免 JPA 的複雜性。JPA 提供延遲載入、快取和髒資料跟蹤等功能。雖然這些功能在您需要時非常有用,但它們實際上會使考慮 JPA 及其行為變得比實際更難。

延遲載入可能會在您意想不到的時候觸發昂貴的語句,或者可能因異常而失敗。當您想要比較同一實體的兩個版本時,快取可能會妨礙您,而髒資料跟蹤使得很難找到所有持久化操作都透過的單一入口點。

Spring Data JDBC 旨在提供一個更簡單的模型。它不會有快取、髒資料跟蹤或延遲載入。相反,SQL 語句只會在您呼叫儲存庫方法時才發出。作為該方法結果返回的物件在方法返回之前會完全載入。沒有“會話”,也沒有實體的代理。所有這些都應該讓 Spring Data JDBC 更容易理解。

當然,這種更簡單的方法會導致一些限制,我們將在未來的文章中介紹。此外,這是第一個版本,因此有許多我們想要並計劃實現的功能,但為了儘早將產品提供給您,我們不得不推遲這些功能。

讓我們來看一個簡單的例子。

首先,我們需要一個實體

class Customer {
    @Id
    Long id;
    String firstName;
    LocalDate dob;
}

請注意,您不需要 getter 或 setter。如果您更喜歡使用它們,那也完全沒問題。實際上,唯一的要求是實體有一個帶有 Id 註解的屬性(即 @org.springframework.data.annotation.Id,而不是 javax.persistence 中的那個)。

接下來,我們需要宣告一個儲存庫。最簡單的方法是擴充套件 CrudRepository

interface CustomerRepository extends CrudRepository<Customer, Long> {}

最後,我們需要配置 ApplicationContext 以啟用儲存庫的建立

@Configuration
@EnableJdbcRepositories (1)
public class CustomerConfig extends JdbcConfiguration { (2)

    @Bean
    NamedParameterJdbcOperations operations() { (3)
        return new NamedParameterJdbcTemplate(dataSource());
    }

    @Bean
    PlatformTransactionManager transactionManager() { (4)
        return new DataSourceTransactionManager(dataSource());
	}

    @Bean
    DataSource dataSource(){ (5)
        return new EmbeddedDatabaseBuilder()
                .generateUniqueName(true)
                .setType(EmbeddedDatabaseType.HSQL)
                .addScript("create-customer-schema.sql")
                .build();
    }
}

讓我們逐步瞭解配置。

  1. EnableJdbcRepositories 啟用儲存庫的建立。由於它需要一些 bean 的存在,因此我們需要其餘的配置。

  2. 擴充套件 JdbcConfiguration 會向 ApplicationContext 新增一些預設 bean。您可以重寫其方法以自定義 Spring Data JDBC 的某些行為。目前,我們使用預設實現。

  3. 真正重要的部分是 NamedParameterJdbcOperations,它在內部用於向資料庫提交 SQL 語句。

  4. 嚴格來說,事務管理器不是必需的。但是您將無法獲得跨越單個語句的事務支援,而沒有人希望這樣,對嗎?

  5. Spring Data JDBC 不直接使用 DataSource,但由於 TransactionManagerNamedParameterJdbcOperations 需要它,因此將其註冊為 bean 是一種確保兩者使用相同例項的簡單方法。

這就是您開始使用它所需的一切。現在讓我們在一個測試中玩轉它

@RunWith(SpringRunner.class)
@Transactional
@ContextConfiguration(classes = CustomerConfig.class)
public class CustomerRepositoryTest {

    @Autowired CustomerRepository customerRepo;

    @Test
    public void createSimpleCustomer() {

        Customer customer = new Customer();
        customer.dob = LocalDate.of(1904, 5, 14);
        customer.firstName = "Albert";

        Customer saved = customerRepo.save(customer);

        assertThat(saved.id).isNotNull();

        saved.firstName = "Hans Albert";

        customerRepo.save(saved);

        Optional<Customer> reloaded = customerRepo.findById(saved.id);

        assertThat(reloaded).isNotEmpty();

        assertThat(reloaded.get().firstName).isEqualTo("Hans Albert");
    }
}

@Query 註解

您可能無法僅使用 CrudRepository 中的基本 CRUD 方法走得很遠。我們決定將查詢派生(Spring Data 從方法名派生查詢的流行功能)推遲到以後的版本。在此之前,您可以使用簡單的 @Query 註解來指定儲存庫方法上的查詢

@Query("select id, first_name, dob from customer where upper(first_name) like '%' || upper(:name) || '%' ")
List<Customer> findByName(@Param("name") String name);

請注意,如果使用 -parameters 標誌進行編譯,則不需要 @Param 註解。

如果要執行更新或刪除語句,可以在方法中新增 @Modifying 註解。

讓我們建立另一個測試來嘗試新方法。

@Test
public void findByName() {

    Customer customer = new Customer();
    customer.dob = LocalDate.of(1904, 5, 14);
    customer.firstName = "Albert";

    Customer saved = customerRepo.save(customer);

    assertThat(saved.id).isNotNull();

    customer.id= null; (1)
    customer.firstName = "Bertram";

    customerRepo.save(customer);

    customer.id= null;
    customer.firstName = "Beth";

    customerRepo.save(customer);

    assertThat(customerRepo.findByName("bert")).hasSize(2); (2)
}
  1. 由於 Java 物件及其對應的行之間的連線只是它的 Id 加上它的型別,因此將 Id 設定為 null 並再次儲存會在資料庫中建立另一行。

  2. 我們正在進行不區分大小寫(like)的搜尋,因此我們找到了“Albert”和“Bertram”,但沒有找到“Beth”。

結束語

關於 Spring Data JDBC 還有更多內容需要學習。繼續閱讀 Spring Data JDBC 引用和聚合

或者您可以檢視示例文件,當然還有原始碼。如果您有問題,請在 StackOverflow 上提問。如果您發現錯誤或想請求功能,請建立問題

獲取 Spring 新聞通訊

透過 Spring 新聞通訊保持聯絡

訂閱

領先一步

VMware 提供培訓和認證,助您加速進步。

瞭解更多

獲得支援

Tanzu Spring 提供 OpenJDK™、Spring 和 Apache Tomcat® 的支援和二進位制檔案,只需一份簡單的訂閱。

瞭解更多

即將舉行的活動

檢視 Spring 社群所有即將舉行的活動。

檢視所有