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 會將一些預設 bean 新增到 ApplicationContext。您可以覆寫其方法來自訂 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 註釋。

如果您想要執行 update 或 delete 語句,您可以向方法新增 @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 上提問。如果您發現錯誤或想要請求功能,請建立 issue

取得 Spring 電子報

隨時關注 Spring 電子報

訂閱

領先一步

VMware 提供培訓和認證,以加速您的進展。

瞭解更多

取得支援

Tanzu Spring 在一個簡單的訂閱中提供 OpenJDK™、Spring 和 Apache Tomcat® 的支援和二進位檔案。

瞭解更多

即將到來的活動

查看 Spring 社群中所有即將到來的活動。

檢視全部