JPA 和 Spring Data JPA 之間的區別
一、概述
我們有多種使用 Java 應用程序連接到數據庫的選項。通常,我們指的是不同的層,從 JDBC 開始。然後,我們轉向 JPA,使用像 Hibernate 這樣的實現。 JPA 最終將使用 JDBC,但使用對象-實體管理方法使其對用戶更加透明。
最後,我們可以有一個類似框架的集成,例如 Spring Data JPA,它具有用於訪問實體的預定義接口,但仍然使用 JPA 和引擎蓋下的實體管理器。
在本教程中,我們將討論 Spring Data JPA 和 JPA 之間的區別。我們還將通過一些高級概述和代碼片段來解釋它們如何工作。讓我們首先解釋 JDBC 的一些歷史以及 JPA 是如何產生的。
2.從JDBC到JPA
自 1997 年 JDK(Java 開發工具包)1.1 版以來,我們已經可以使用JDBC訪問關係數據庫。
關於 JDBC 的要點對於理解 JPA 也是必不可少的,包括:
-
[DriverManager](https://docs.oracle.com/javase/8/docs/api/java/sql/DriverManager.html)
和用於連接和執行查詢的接口:這使得通常使用特定驅動程序(例如 MySQL Java 連接器)可以連接到任何 ODBC 可訪問的數據源。我們可以連接到數據庫並在其上打開/關閉事務。最重要的是,我們只需更改數據庫驅動程序就可以使用任何數據庫,如 MySQL、Oracle 或 PostgreSQL 。 - 數據源:對於 Java Enterprise 和像 Spring 這樣的框架,了解我們如何在工作上下文中定義和獲取數據庫連接很重要。
- 連接池,其作用類似於數據庫連接對象的緩存:我們可以重用處於主動/被動狀態的打開的連接,並減少它們的創建次數。
- 分佈式事務:它們由一個或多個語句組成,這些語句在同一事務中更新多個數據庫或資源上的數據。
在 JDBC 創建之後,像Hibernate這樣的持久性框架(或 ORM 工具)開始出現,它將數據庫資源映射為普通的舊 Java 對象。我們將 ORM 稱為定義模式生成或數據庫方言等的層。
此外,Entity Java Bean ( EJB ) 創建標準來管理封裝應用程序業務邏輯的服務器端組件。事務處理、JNDI 和持久性服務等功能現在都是 Java beans 。此外,註釋和依賴注入現在簡化了不同系統的配置和集成。
隨著 EJB 3.0 的發布,持久性框架被合併到 Java Persistence API (JPA) 中,Hibernate 或EclipseLink等項目已成為 JPA 規範的實現。
3.聯合行動計劃
使用 JPA,我們可以獨立於所使用的數據庫,以面向對象的語法編寫構建塊。
為了進行演示,讓我們看一個員工表定義的示例。我們最終可以使用@Entity
註解將表定義為 POJO:
@Entity
@Table(name = "employee")
public class Employee implements Serializable {
@Id
@Generated
private Long id;
@Column(nullable = false)
private String firstName;
// other fields, setter and getters
}
JPA 類可以管理數據庫表功能,例如主鍵策略和多對多關係。例如,在使用外鍵時,這是相關的。 JPA 可以延遲初始化集合併僅在我們需要時訪問數據。
我們可以使用EntityManager
對實體執行所有 CRUD 操作(創建、檢索、更新、刪除)。 JPA 正在隱式處理事務。這可以通過像Spring 事務管理這樣的容器來完成,或者簡單地通過使用EntityManager
的 Hibernate 這樣的 ORM 工具來完成。
一旦我們訪問了EntityManager
,我們就可以,例如,持久化一個Employee
:
Employee employee = new Employee();
// set properties
entityManager.persist(employee);
3.1.條件查詢和 JPQL
例如,我們可以通過 id 找到一個Employee
:
Employee response = entityManger.find(Employee.class, id);
更有趣的是,我們可以以類型安全的方式使用 Criteria Queries 與@Entity
進行交互。比如還是通過id查找,我們可以使用[CriteriaQuery](https://jakarta.ee/specifications/persistence/2.2/apidocs/javax/persistence/criteria/criteriaquery)
接口:
CriteriaBuilder cb = entityManager.getCriteriaBuilder();
CriteriaQuery<Employee> cr = cb.createQuery(Employee.class);
Root<Employee> root = cr.from(Employee.class);
cr.select(root);
criteriaQuery.where(criteriaBuilder.equal(root.get(Employee_.ID), employee.getId()));
Employee employee = entityManager.createQuery(criteriaQuery).getSingleResult();
此外,我們還可以應用排序和分頁:
criteriaQuery.orderBy(criteriaBuilder.asc(root.get(Employee_.FIRST_NAME)));
TypedQuery<Employee> query = entityManager.createQuery(criteriaQuery);
query.setFirstResult(0);
query.setMaxResults(3);
List<Employee> employeeList = query.getResultList();
我們可以使用條件查詢來實現持久化。例如,我們可以使用CriteriaUpdate
接口進行更新。假設我們要更新員工的電子郵件地址:
CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder();
CriteriaUpdate<Employee> criteriaQuery = criteriaBuilder.createCriteriaUpdate(Employee.class);
Root<Employee> root = criteriaQuery.from(Employee.class);
criteriaQuery.set(Employee_.EMAIL, email);
criteriaQuery.where(criteriaBuilder.equal(root.get(Employee_.ID), employee));
entityManager.createQuery(criteriaQuery).executeUpdate();
最後,JPA 還提供了 JPQL(如果我們本機使用 Hibernate,則為 HQL),它允許我們以類似 SQL 的語法創建查詢,但仍然引用@Entity
bean:
public Employee getEmployeeById(Long id) {
Query jpqlQuery = getEntityManager().createQuery("SELECT e from Employee e WHERE e.id=:id");
jpqlQuery.setParameter("id", id);
return jpqlQuery.getSingleResult();
}
3.2. JDBC
JPA 可以適應許多具有通用接口的不同數據庫。然而,在實際應用程序中,我們很可能需要 JDBC 支持。這是為了使用特定的數據庫查詢語法或出於性能原因,例如,在批處理中。
即使我們使用 JPA,我們仍然可以使用createNativeQuery
方法以數據庫的本機語言編寫。例如,我們可能想使用rownum
Oracle 關鍵字:
Query query = entityManager
.createNativeQuery("select * from employee where rownum < :limit", Employee.class);
query.setParameter("limit", limit);
List<Employee> employeeList = query.getResultList();
此外,這適用於仍然與特定於數據庫的語言相關的各種函數和過程。例如,我們可以創建並執行一個存儲過程:
StoredProcedureQuery storedProcedure = em.createStoredProcedureQuery("calculate_something");
// set parameters
storedProcedure.execute();
Double result = (Double) storedProcedure.getOutputParameterValue("output");
3.3.註釋
JPA 帶有一組註釋。我們已經看到了@Table、@ @Entity
、 @Id
@Column
@Table
如果我們經常重用一個查詢,我們可以在類級別使用@Entity
將其註釋為@NamedQuery
,仍然使用 JPQL:
@NamedQuery(name="Employee.findById", query="SELECT e FROM Employee e WHERE e.id = :id")
然後,我們可以從模板創建一個Query
:
Query query = em.createNamedQuery("Employee.findById", Employee.class);
query.setParameter("id", id);
Employee result = query.getResultList();
與@NamedQuery
類似,我們可以使用@NamedNativeQuery
進行數據庫原生查詢:
@NamedNativeQuery(name="Employee.findAllWithLimit", query="SELECT * FROM employee WHERE rownum < :limit")
3.4.元模型
我們可能想要生成一個元模型,允許我們以類型安全的方式靜態訪問表字段。例如,讓我們看看從Employee
生成的Employee_
類:
@Generated(value = "org.hibernate.jpamodelgen.JPAMetaModelEntityProcessor")
@StaticMetamodel(Employee.class)
public abstract class Employee_ {
public static volatile SingularAttribute<Employee, String> firstName;
public static volatile SingularAttribute<Employee, String> lastName;
public static volatile SingularAttribute<Employee, Long> id;
public static volatile SingularAttribute<Employee, String> email;
public static final String FIRST_NAME = "firstName";
public static final String LAST_NAME = "lastName";
public static final String ID = "id";
public static final String EMAIL = "email";
}
我們可以靜態訪問這些字段。如果我們更改數據模型,該類將重新生成該類。
4. 春季數據JPA
作為大型 Spring Data 系列的一部分,Spring Data JPA 是作為 JPA 之上的抽象層構建的。因此,我們擁有 JPA 的所有功能以及易於開發的 Spring。
多年來,開發人員編寫了樣板代碼來為基本功能創建 JPA DAO。 Spring 通過提供最少的接口和實際實現來幫助顯著減少代碼量。
4.1.資料庫
例如,假設我們要為Employee
表創建一個 CRUD 存儲庫。我們可以使用JpaRepository
:
public interface EmployeeRepository extends JpaRepository<Employee, Long> {
}
這就是我們開始所需要的。所以,如果我們想要持久化或更新,我們可以獲取存儲庫的一個實例並保存一個員工:
employeeRepository.save(employee);
我們也非常支持編寫查詢。有趣的是,我們可以通過簡單地聲明它們的方法簽名來定義查詢方法:
public interface EmployeeRepository extends JpaRepository<Employee, Long> {
List<Employee> findByFirstName(String firstName);
}
Spring 將在運行時從存儲庫接口自動創建存儲庫實現。
因此,我們可以使用這些方法而無需實現它們:
List<Employee> employees = employeeRepository.findByFirstName("John");
我們還支持對存儲庫進行排序和分頁:
public interface EmployeeRepository extends PagingAndSortingRepository<Employee, Long> {
}
然後我們可以創建一個具有頁面大小、數量和排序標準的[Pageable](https://docs.spring.io/spring-data/data-commons/docs/current/api/org/springframework/data/domain/Pageable.html)
對象:
Pageable pageable = PageRequest.of(5, 10, Sort.by("firstName"));
Page<Employee> employees = employeeRepositorySortAndPaging.findAll(pageable);
4.2.查詢
另一個很棒的特性是對@Query
註釋的廣泛支持。與 JPA 類似,這有助於定義類似 JPQL 或本機查詢。讓我們看一個示例,說明如何在存儲庫界面中使用它通過應用排序來獲取員工列表:
@Query(value = "SELECT e FROM Employee e")
List<Employee> findAllEmployee(Sort sort);
同樣,我們將使用存儲庫並獲取列表:
List<Employee> employees = employeeRepository.findAllEmployee(Sort.by("firstName"));
4.3.查詢Dsl
與 JPA 類似,我們有類似條件的支持,稱為 QueryDsl,它也有一個元模型生成。例如,假設我們想要一個員工列表,過濾名稱:
QEmployee employee = QEmployee.employee;
List<Employee> employees = queryFactory.selectFrom(employee)
.where(
employee.firstName.eq("John"),
employee.lastName.eq("Doe"))
.fetch();
5.JPA 測試
讓我們創建並測試一個簡單的 JPA 應用程序。我們可以讓 Hibernate 管理事務性。
5.1.依賴關係
讓我們看一下依賴關係。我們需要在pom.xml
中導入JPA、 Hibernate 核心和H2數據庫。
<dependency>
<groupId>javax.persistence</groupId>
<artifactId>javax.persistence-api</artifactId>
<version>2.2</version>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-core</artifactId>
<version>5.6.11-Final</version>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<version>2.1.214</version>
</dependency>
此外,我們需要一個用於生成元模型的插件:
<plugin>
<groupId>org.bsc.maven</groupId>
<artifactId>maven-processor-plugin</artifactId>
<version>3.3.3</version>
<executions>
<execution>
<id>process</id>
<goals>
<goal>process</goal>
</goals>
<phase>generate-sources</phase>
<configuration>
<outputDirectory>${project.build.directory}/generated-sources</outputDirectory>
<processors>
<processor>org.hibernate.jpamodelgen.JPAMetaModelEntityProcessor</processor>
</processors>
</configuration>
</execution>
</executions>
<dependencies>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-jpamodelgen</artifactId>
<version>5.6.11.Final</version>
</dependency>
</dependencies>
</plugin>
5.2.配置
為了保持簡單的 JPA,我們使用一個persistence.xml
文件:
<?xml version="1.0" encoding="UTF-8"?>
<persistence xmlns="http://xmlns.jcp.org/xml/ns/persistence"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistence
http://xmlns.jcp.org/xml/ns/persistence/persistence_2_1.xsd"
version="2.1">
<persistence-unit name="pu-test">
<provider>org.hibernate.jpa.HibernatePersistenceProvider</provider>
<class>com.baeldung.spring.data.persistence.springdata_jpa_difference.model.Employee</class>
<properties>
<property name="javax.persistence.jdbc.driver" value="org.h2.Driver"/>
<property name="javax.persistence.jdbc.url" value="jdbc:h2:mem:test;DB_CLOSE_DELAY=-1"/>
<property name="javax.persistence.jdbc.user" value="sa"/>
<property name="javax.persistence.jdbc.password" value=""/>
<property name="hibernate.dialect" value="org.hibernate.dialect.H2Dialect"/>
<property name="hibernate.hbm2ddl.auto" value="create-drop"/>
</properties>
</persistence-unit>
</persistence>
我們不需要任何基於 Bean 的配置。
5.3.測試類定義
為了演示,讓我們創建一個測試類。我們將使用createEntityManagerFactory
方法獲取EntityManager
並手動管理事務:
public class JpaDaoIntegrationTest {
private final EntityManagerFactory emf = Persistence.createEntityManagerFactory("pu-test");
private final EntityManager entityManager = emf.createEntityManager();
@Before
public void setup() {
deleteAllEmployees();
}
// tests
private void deleteAllEmployees() {
entityManager.getTransaction()
.begin();
entityManager.createNativeQuery("DELETE from Employee")
.executeUpdate();
entityManager.getTransaction()
.commit();
}
public void save(Employee entity) {
entityManager.getTransaction()
.begin();
entityManager.persist(entity);
entityManager.getTransaction()
.commit();
}
public void update(Employee entity) {
entityManager.getTransaction()
.begin();
entityManager.merge(entity);
entityManager.getTransaction()
.commit();
}
public void delete(Long employee) {
entityManager.getTransaction()
.begin();
entityManager.remove(entityManager.find(Employee.class, employee));
entityManager.getTransaction()
.commit();
}
public int update(CriteriaUpdate<Employee> criteriaUpdate) {
entityManager.getTransaction()
.begin();
int result = entityManager.createQuery(criteriaUpdate)
.executeUpdate();
entityManager.getTransaction()
.commit();
entityManager.clear();
return result;
}
}
5.4.測試 JPA
首先,我們要測試是否可以通過 id 找到員工:
@Test
public void givenPersistedEmployee_whenFindById_thenEmployeeIsFound() {
// save employee
assertEquals(employee, entityManager.find(Employee.class, employee.getId()));
}
讓我們看看我們可以找到Employee
的其他方法。例如,我們可以使用CriteriaQuey
:
@Test
public void givenPersistedEmployee_whenFindByIdCriteriaQuery_thenEmployeeIsFound() {
// save employee
CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder();
CriteriaQuery<Employee> criteriaQuery = criteriaBuilder.createQuery(Employee.class);
Root<Employee> root = criteriaQuery.from(Employee.class);
criteriaQuery.select(root);
criteriaQuery.where(criteriaBuilder.equal(root.get(Employee_.ID), employee.getId()));
assertEquals(employee, entityManager.createQuery(criteriaQuery)
.getSingleResult());
}
另外,我們可以使用 JPQL:
@Test
public void givenPersistedEmployee_whenFindByIdJpql_thenEmployeeIsFound() {
// save employee
Query jpqlQuery = entityManager.createQuery("SELECT e from Employee e WHERE e.id=:id");
jpqlQuery.setParameter("id", employee.getId());
assertEquals(employee, jpqlQuery.getSingleResult());
}
讓我們看看如何從@NamedQuery
創建一個Query
:
@Test
public void givenPersistedEmployee_whenFindByIdNamedQuery_thenEmployeeIsFound() {
// save employee
Query query = entityManager.createNamedQuery("Employee.findById");
query.setParameter(Employee_.ID, employee.getId());
assertEquals(employee, query.getSingleResult());
}
我們還可以看一個如何應用排序和分頁的示例:
@Test
public void givenPersistedEmployee_whenFindWithPaginationAndSort_thenEmployeesAreFound() {
// save John, Frank, Bob, James
CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder();
CriteriaQuery<Employee> criteriaQuery = criteriaBuilder.createQuery(Employee.class);
Root<Employee> root = criteriaQuery.from(Employee.class);
criteriaQuery.select(root);
criteriaQuery.orderBy(criteriaBuilder.asc(root.get(Employee_.FIRST_NAME)));
TypedQuery<Employee> query = entityManager.createQuery(criteriaQuery);
query.setFirstResult(0);
query.setMaxResults(3);
List<Employee> employeeList = query.getResultList();
assertEquals(Arrays.asList(bob, frank, james), employeeList);
}
最後,讓我們看看如何使用CriteriaUpdate
更新員工電子郵件:
@Test
public void givenPersistedEmployee_whenUpdateEmployeeEmailWithCriteria_thenEmployeeHasUpdatedEmail() {
// save employee
String updatedEmail = "[email protected]";
CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder();
CriteriaUpdate<Employee> criteriaUpdate = criteriaBuilder.createCriteriaUpdate(Employee.class);
Root<Employee> root = criteriaUpdate.from(Employee.class);
criteriaUpdate.set(Employee_.EMAIL, updatedEmail);
criteriaUpdate.where(criteriaBuilder.equal(root.get(Employee_.ID), employee.getId()));
assertEquals(1, update(criteriaUpdate));
assertEquals(updatedEmail, entityManager.find(Employee.class, employee.getId())
.getEmail());
}
6. Spring Data JPA 測試
讓我們看看如何通過添加 Spring 存儲庫和內置查詢支持來改進。
6.1.依賴關係
在這種情況下,我們需要添加Spring Data依賴項。我們還需要 Fluent 查詢 API 的QueryDsl依賴項。
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-jpa</artifactId>
<version>2.7.5</version>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<version>2.2.214</version>
</dependency>
<dependency>
<groupId>com.querydsl</groupId>
<artifactId>querydsl-apt</artifactId>
<version>5.0.0</version>
</dependency>
<dependency>
<groupId>com.querydsl</groupId>
<artifactId>querydsl-jpa</artifactId>
<version>5.0.0</version>
</dependency>
6.2.配置
首先,讓我們創建我們的配置:
@Configuration
@EnableTransactionManagement
@EnableJpaRepositories(basePackageClasses = EmployeeRepository.class)
public class SpringDataJpaConfig {
@Bean
public LocalContainerEntityManagerFactoryBean entityManagerFactory(DataSource dataSource) {
LocalContainerEntityManagerFactoryBean em = new LocalContainerEntityManagerFactoryBean();
em.setDataSource(dataSource);
em.setPackagesToScan("com.baeldung.spring.data.persistence.springdata_jpa_difference.model");
JpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
em.setJpaVendorAdapter(vendorAdapter);
Properties properties = new Properties();
properties.setProperty("hibernate.hbm2ddl.auto", "create-drop");
properties.setProperty("hibernate.dialect", "org.hibernate.dialect.H2Dialect");
em.setJpaProperties(properties);
return em;
}
@Bean
public PlatformTransactionManager transactionManager(LocalContainerEntityManagerFactoryBean entityManagerFactoryBean) {
JpaTransactionManager transactionManager = new JpaTransactionManager();
transactionManager.setEntityManagerFactory(entityManagerFactoryBean.getObject());
return transactionManager;
}
@Bean
public DataSource dataSource() {
return DataSourceBuilder.create()
.url("jdbc:h2:mem:db;DB_CLOSE_DELAY=-1")
.driverClassName("org.h2.Driver")
.username("sa")
.password("sa")
.build();
}
@Bean
public JPAQueryFactory jpaQueryFactory(EntityManager entityManager) {
return new JPAQueryFactory((entityManager));
}
}
最後,讓我們看看我們的JpaRepository
:
@Repository
public interface EmployeeRepository extends JpaRepository<Employee, Long> {
List<Employee> findByFirstName(String firstName);
@Query(value = "SELECT e FROM Employee e")
List<Employee> findAllEmployee(Sort sort);
}
另外,我們想使用PagingAndSortingRepository
:
@Repository
public interface EmployeeRepositoryPagingAndSort extends PagingAndSortingRepository<Employee, Long> {
}
6.3.測試類定義
讓我們看看我們用於 Spring Data 測試的測試類。我們將回滾以保持每個測試的原子性:
@ContextConfiguration(classes = SpringDataJpaConfig.class)
@RunWith(SpringJUnit4ClassRunner.class)
@Transactional
@Rollback
public class SpringDataJpaIntegrationTest {
@Autowired
private EmployeeRepository employeeRepository;
@Autowired
private EmployeeRepositoryPagingAndSort employeeRepositoryPagingAndSort;
@Autowired
private JPAQueryFactory jpaQueryFactory;
// tests
}
6.4.測試 Spring Data JPA
讓我們從通過 id 查找員工開始:
@Test
public void givenPersistedEmployee_whenFindById_thenEmployeeIsFound() {
Employee employee = employee("John", "Doe");
employeeRepository.save(employee);
assertEquals(Optional.of(employee), employeeRepository.findById(employee.getId()));
}
讓我們看看如何通過名字查找員工:
@Test
public void givenPersistedEmployee_whenFindByFirstName_thenEmployeeIsFound() {
Employee employee = employee("John", "Doe");
employeeRepository.save(employee);
assertEquals(employee, employeeRepository.findByFirstName(employee.getFirstName())
.get(0));
}
我們可以應用排序,例如,在查詢所有員工時:
@Test
public void givenPersistedEmployees_whenFindSortedByFirstName_thenEmployeeAreFoundInOrder() {
Employee john = employee("John", "Doe");
Employee bob = employee("Bob", "Smith");
Employee frank = employee("Frank", "Brown");
employeeRepository.saveAll(Arrays.asList(john, bob, frank));
List<Employee> employees = employeeRepository.findAllEmployee(Sort.by("firstName"));
assertEquals(3, employees.size());
assertEquals(bob, employees.get(0));
assertEquals(frank, employees.get(1));
assertEquals(john, employees.get(2));
}
讓我們看看如何使用 QueryDsl 構建查詢:
@Test
public void givenPersistedEmployee_whenFindByQueryDsl_thenEmployeeIsFound() {
Employee john = employee("John", "Doe");
Employee frank = employee("Frank", "Doe");
employeeRepository.saveAll(Arrays.asList(john, frank));
QEmployee employeePath = QEmployee.employee;
List<Employee> employees = jpaQueryFactory.selectFrom(employeePath)
.where(employeePath.firstName.eq("John"), employeePath.lastName.eq("Doe"))
.fetch();
assertEquals(1, employees.size());
assertEquals(john, employees.get(0));
}
最後,我們可以檢查如何使用PagingAndSortingRepository
:
@Test
public void givenPersistedEmployee_whenFindBySortAndPagingRepository_thenEmployeeAreFound() {
Employee john = employee("John", "Doe");
Employee bob = employee("Bob", "Smith");
Employee frank = employee("Frank", "Brown");
Employee jimmy = employee("Jimmy", "Armstrong");
employeeRepositoryPagingAndSort.saveAll(Arrays.asList(john, bob, frank, jimmy));
Pageable pageable = PageRequest.of(0, 2, Sort.by("firstName"));
Page<Employee> employees = employeeRepositoryPagingAndSort.findAll(pageable);
assertEquals(Arrays.asList(bob, frank), employees.get()
.collect(Collectors.toList()));
}
7. JPA 和 Spring Data JPA 有何不同
JPA 定義了對象關係映射 (ORM) 的標準方法。
它提供了一個抽象層,使其獨立於我們正在使用的數據庫。 JPA 還可以處理事務性並且構建在 JDBC 之上,因此我們仍然可以使用本機數據庫語言。
Spring Data JPA 是 JPA 之上的另一層抽象。但是,它比 JPA 更靈活,並為所有 CRUD 操作提供簡單的存儲庫和語法。我們可以從 JPA 應用程序中刪除所有樣板代碼,並使用更簡單的接口和註釋。此外,我們將擁有 Spring 的開發便利性,例如,透明地處理事務性。
此外,沒有 JPA 就沒有 Spring Data JPA,所以無論如何,如果我們想了解更多有關 Java 數據庫訪問層的知識,JPA 是一個很好的起點。
八、結論
在本教程中,我們簡要了解了 JDBC 的歷史以及 JPA 為何成為關係數據庫 API 的標準。我們還看到了用於持久化實體和創建動態查詢的 JPA 和 Spring Data JPA 示例。最後,我們提供了一些測試用例來展示普通 JPA 應用程序和 Spring Data JPA 應用程序之間的區別。
一如既往,所有源代碼都可以在 GitHub 上獲得。