JPA

Spring JPA(在 org.springframework.orm.jpa 套件下提供)以類似於與 Hibernate 整合的方式,為 Java Persistence API 提供全面的支援,同時也了解底層實作,以便提供額外功能。

在 Spring 環境中設定 JPA 的三個選項

Spring JPA 支援提供三種設定 JPA EntityManagerFactory 的方式,應用程式使用該工廠來取得實體管理器。

使用 LocalEntityManagerFactoryBean

您只能在簡單的部署環境中使用此選項,例如獨立應用程式和整合測試。

LocalEntityManagerFactoryBean 建立適用於簡單部署環境的 EntityManagerFactory,在這些環境中,應用程式僅使用 JPA 進行資料存取。 工廠 Bean 使用 JPA PersistenceProvider 自動偵測機制(根據 JPA 的 Java SE 引導),並且在大多數情況下,僅要求您指定持久化單元名稱。 以下 XML 範例組態了這樣的 Bean

<beans>
	<bean id="myEmf" class="org.springframework.orm.jpa.LocalEntityManagerFactoryBean">
		<property name="persistenceUnitName" value="myPersistenceUnit"/>
	</bean>
</beans>

此形式的 JPA 部署是最簡單且最受限制的。 您無法參考現有的 JDBC DataSource Bean 定義,並且不存在對全域交易的支援。 此外,持久化類別的織入(位元組碼轉換)是供應商特定的,通常需要在啟動時指定特定的 JVM 代理程式。 此選項僅適用於獨立應用程式和測試環境,JPA 規範就是為此設計的。

從 JNDI 取得 EntityManagerFactory

當部署到 Jakarta EE 伺服器時,您可以使用此選項。 請查看伺服器的文件,以了解如何在伺服器中部署自訂 JPA 供應商,允許使用與伺服器預設供應商不同的供應商。

從 JNDI 取得 EntityManagerFactory(例如在 Jakarta EE 環境中),只需變更 XML 組態即可,如下列範例所示

<beans>
	<jee:jndi-lookup id="myEmf" jndi-name="persistence/myPersistenceUnit"/>
</beans>

此動作假設標準 Jakarta EE 引導。 Jakarta EE 伺服器自動偵測持久化單元(實際上是應用程式 jar 中的 META-INF/persistence.xml 檔案)和 Jakarta EE 部署描述符(例如,web.xml)中的 persistence-unit-ref 項目,並為這些持久化單元定義環境命名 Context 位置。

在這種情況下,整個持久化單元部署,包括持久化類別的織入(位元組碼轉換),都由 Jakarta EE 伺服器負責。 JDBC DataSource 是透過 META-INF/persistence.xml 檔案中的 JNDI 位置定義的。 EntityManager 交易與伺服器的 JTA 子系統整合。 Spring 僅使用取得的 EntityManagerFactory,透過相依性注入將其傳遞給應用程式物件,並管理持久化單元的交易(通常透過 JtaTransactionManager)。

如果您在同一個應用程式中使用多個持久化單元,則此類 JNDI 擷取的持久化單元的 Bean 名稱應與應用程式用來參考它們的持久化單元名稱相符(例如,在 @PersistenceUnit@PersistenceContext 註解中)。

使用 LocalContainerEntityManagerFactoryBean

您可以在基於 Spring 的應用程式環境中使用此選項來獲得完整的 JPA 功能。 這包括 Web 容器(例如 Tomcat)、獨立應用程式以及具有複雜持久化需求的整合測試。

LocalContainerEntityManagerFactoryBean 提供對 EntityManagerFactory 組態的完全控制,並且適用於需要細緻自訂的環境。 LocalContainerEntityManagerFactoryBean 根據 persistence.xml 檔案、提供的 dataSourceLookup 策略和指定的 loadTimeWeaver 建立 PersistenceUnitInfo 實例。 因此,可以在 JNDI 之外使用自訂資料來源並控制織入過程。 以下範例顯示了 LocalContainerEntityManagerFactoryBean 的典型 Bean 定義

<beans>
	<bean id="myEmf" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
		<property name="dataSource" ref="someDataSource"/>
		<property name="loadTimeWeaver">
			<bean class="org.springframework.instrument.classloading.InstrumentationLoadTimeWeaver"/>
		</property>
	</bean>
</beans>

以下範例顯示了典型的 persistence.xml 檔案

<persistence xmlns="http://java.sun.com/xml/ns/persistence" version="1.0">
	<persistence-unit name="myUnit" transaction-type="RESOURCE_LOCAL">
		<mapping-file>META-INF/orm.xml</mapping-file>
		<exclude-unlisted-classes/>
	</persistence-unit>
</persistence>
<exclude-unlisted-classes/> 快捷方式表示不應發生掃描已註解的實體類別。 明確的 'true' 值 (<exclude-unlisted-classes>true</exclude-unlisted-classes/>) 也表示不掃描。 <exclude-unlisted-classes>false</exclude-unlisted-classes/> 會觸發掃描。 但是,如果您希望發生實體類別掃描,我們建議省略 exclude-unlisted-classes 元素。

使用 LocalContainerEntityManagerFactoryBean 是最強大的 JPA 設定選項,允許在應用程式內進行彈性的本機組態。 它支援連結到現有的 JDBC DataSource,同時支援本機和全域交易等等。 但是,它也對執行階段環境施加了要求,例如,如果持久化供應商要求位元組碼轉換,則需要具有織入功能的類別載入器。

此選項可能會與 Jakarta EE 伺服器的內建 JPA 功能衝突。 在完整的 Jakarta EE 環境中,請考慮從 JNDI 取得您的 EntityManagerFactory。 或者,在您的 LocalContainerEntityManagerFactoryBean 定義上指定自訂 persistenceXmlLocation(例如,META-INF/my-persistence.xml),並且僅在您的應用程式 jar 檔案中包含具有該名稱的描述符。 由於 Jakarta EE 伺服器僅尋找預設的 META-INF/persistence.xml 檔案,因此它會忽略此類自訂持久化單元,因此,可以預先避免與 Spring 驅動的 JPA 設定發生衝突。

何時需要載入時織入?

並非所有 JPA 供應商都需要 JVM 代理程式。 Hibernate 就是一個不需要的範例。 如果您的供應商不需要代理程式,或者您有其他替代方案,例如透過自訂編譯器或 Ant 工作在建置時套用增強功能,則您不應使用載入時織入器。

LoadTimeWeaver 介面是 Spring 提供的類別,可讓 JPA ClassTransformer 實例以特定方式插入,具體取決於環境是 Web 容器還是應用程式伺服器。 透過 代理程式 掛鉤 ClassTransformer 通常效率不高。 代理程式針對整個虛擬機器工作,並檢查載入的每個類別,這在生產伺服器環境中通常是不理想的。

Spring 為各種環境提供了許多 LoadTimeWeaver 實作,讓 ClassTransformer 實例僅適用於每個類別載入器,而不適用於每個 VM。

請參閱 AOP 章節中的 Spring 組態,以更深入了解 LoadTimeWeaver 實作及其設定,無論是通用的還是針對各種平台(例如 Tomcat、JBoss 和 WebSphere)自訂的。

Spring 組態 中所述,您可以使用 @EnableLoadTimeWeaving 註解或 context:load-time-weaver XML 元素來組態 Context 範圍的 LoadTimeWeaver。 此類全域織入器會自動被所有 JPA LocalContainerEntityManagerFactoryBean 實例選取。 以下範例顯示了設定載入時織入器的慣用方式,可自動偵測平台(例如,Tomcat 的織入功能類別載入器或 Spring 的 JVM 代理程式)並將織入器自動傳播到所有可感知織入器的 Bean

<context:load-time-weaver/>

<bean id="emf" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
	...
</bean>

但是,如果需要,您可以透過 loadTimeWeaver 屬性手動指定專用的織入器,如下列範例所示

<bean id="emf" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
	<property name="loadTimeWeaver">
		<bean class="org.springframework.instrument.classloading.ReflectiveLoadTimeWeaver"/>
	</property>
</bean>

無論 LTW 如何組態,透過使用此技術,依賴檢測的 JPA 應用程式都可以在目標平台(例如,Tomcat)中執行,而無需代理程式。 當託管應用程式依賴不同的 JPA 實作時,這尤其重要,因為 JPA 轉換器僅在類別載入器層級套用,因此彼此隔離。

處理多個持久化單元

對於依賴多個持久化單元位置(例如,儲存在類別路徑中的各種 JAR 中)的應用程式,Spring 提供了 PersistenceUnitManager 作為中央儲存庫,並避免了持久化單元探索過程,這可能會很耗費資源。 預設實作允許指定多個位置。 這些位置會被剖析,然後透過持久化單元名稱擷取。(預設情況下,會在類別路徑中搜尋 META-INF/persistence.xml 檔案。)以下範例組態了多個位置

<bean id="pum" class="org.springframework.orm.jpa.persistenceunit.DefaultPersistenceUnitManager">
	<property name="persistenceXmlLocations">
		<list>
			<value>org/springframework/orm/jpa/domain/persistence-multi.xml</value>
			<value>classpath:/my/package/**/custom-persistence.xml</value>
			<value>classpath*:META-INF/persistence.xml</value>
		</list>
	</property>
	<property name="dataSources">
		<map>
			<entry key="localDataSource" value-ref="local-db"/>
			<entry key="remoteDataSource" value-ref="remote-db"/>
		</map>
	</property>
	<!-- if no datasource is specified, use this one -->
	<property name="defaultDataSource" ref="remoteDataSource"/>
</bean>

<bean id="emf" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
	<property name="persistenceUnitManager" ref="pum"/>
	<property name="persistenceUnitName" value="myCustomUnit"/>
</bean>

預設實作允許自訂 PersistenceUnitInfo 實例(在將它們饋送到 JPA 供應商之前),可以宣告式地(透過其屬性,這會影響所有託管單元)或以程式化方式(透過 PersistenceUnitPostProcessor,這允許持久化單元選取)。 如果未指定 PersistenceUnitManager,則會建立一個並由 LocalContainerEntityManagerFactoryBean 在內部使用。

背景引導

LocalContainerEntityManagerFactoryBean 透過 bootstrapExecutor 屬性支援背景引導,如下列範例所示

<bean id="emf" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
	<property name="bootstrapExecutor">
		<bean class="org.springframework.core.task.SimpleAsyncTaskExecutor"/>
	</property>
</bean>

實際的 JPA 供應商引導會移交給指定的執行器,然後與應用程式引導執行緒平行執行。 公開的 EntityManagerFactory Proxy 可以注入到其他應用程式組件中,甚至能夠回應 EntityManagerFactoryInfo 組態檢查。 但是,一旦其他組件存取實際的 JPA 供應商(例如,呼叫 createEntityManager),這些呼叫就會封鎖,直到背景引導完成。 特別是,當您使用 Spring Data JPA 時,請務必也為其儲存庫設定延遲引導。

從 6.2 開始,JPA 初始化會在 Context 重新整理完成之前強制執行,並等待非同步引導在此時完成。 這使得完全初始化的資料庫基礎架構的可用性可預測,並允許在 ContextRefreshedEvent Listener 等中進行自訂的後初始化邏輯。 不建議將此類應用程式層級資料庫初始化放入 @PostConstruct 方法或類似方法中; 最好將其放在 Lifecycle.start(如果適用)或 ContextRefreshedEvent Listener 中。

基於 JPA 實作 DAO:EntityManagerFactoryEntityManager

雖然 EntityManagerFactory 實例是執行緒安全的,但 EntityManager 實例不是。 注入的 JPA EntityManager 的行為類似於從應用程式伺服器的 JNDI 環境中擷取的 EntityManager,如 JPA 規範所定義。 如果存在目前的交易 EntityManager,它會將所有呼叫委派給它。 否則,它會回退到每個操作新建立的 EntityManager,實際上使其使用成為執行緒安全的。

可以使用注入的 EntityManagerFactoryEntityManager,針對純 JPA 撰寫程式碼,而無需任何 Spring 相依性。 如果啟用了 PersistenceAnnotationBeanPostProcessor,Spring 可以理解欄位和方法層級的 @PersistenceUnit@PersistenceContext 註解。 以下範例顯示了使用 @PersistenceUnit 註解的純 JPA DAO 實作

  • Java

  • Kotlin

public class ProductDaoImpl implements ProductDao {

	private EntityManagerFactory emf;

	@PersistenceUnit
	public void setEntityManagerFactory(EntityManagerFactory emf) {
		this.emf = emf;
	}

	public Collection loadProductsByCategory(String category) {
		EntityManager em = this.emf.createEntityManager();
		try {
			Query query = em.createQuery("from Product as p where p.category = ?1");
			query.setParameter(1, category);
			return query.getResultList();
		}
		finally {
			if (em != null) {
				em.close();
			}
		}
	}
}
class ProductDaoImpl : ProductDao {

	private lateinit var emf: EntityManagerFactory

	@PersistenceUnit
	fun setEntityManagerFactory(emf: EntityManagerFactory) {
		this.emf = emf
	}

	fun loadProductsByCategory(category: String): Collection<*> {
		val em = this.emf.createEntityManager()
		val query = em.createQuery("from Product as p where p.category = ?1");
		query.setParameter(1, category);
		return query.resultList;
	}
}

先前的 DAO 不相依於 Spring,並且仍然非常適合 Spring 應用程式 Context。 此外,DAO 利用註解來要求注入預設的 EntityManagerFactory,如下列 Bean 定義範例所示

<beans>

	<!-- bean post-processor for JPA annotations -->
	<bean class="org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor"/>

	<bean id="myProductDao" class="product.ProductDaoImpl"/>

</beans>

作為明確定義 PersistenceAnnotationBeanPostProcessor 的替代方案,請考慮在您的應用程式 Context 組態中使用 Spring context:annotation-config XML 元素。 這樣做會自動註冊所有 Spring 標準後處理器,用於基於註解的組態,包括 CommonAnnotationBeanPostProcessor 等等。

請考慮以下範例

<beans>

	<!-- post-processors for all standard config annotations -->
	<context:annotation-config/>

	<bean id="myProductDao" class="product.ProductDaoImpl"/>

</beans>

此類 DAO 的主要問題在於,它總是透過 factory 建立新的 EntityManager。您可以請求注入事務性的 EntityManager (也稱為「共享 EntityManager」,因為它是實際事務性 EntityManager 的共享、執行緒安全的代理),而不是 factory,來避免這種情況。以下範例示範如何做到這一點

  • Java

  • Kotlin

public class ProductDaoImpl implements ProductDao {

	@PersistenceContext
	private EntityManager em;

	public Collection loadProductsByCategory(String category) {
		Query query = em.createQuery("from Product as p where p.category = :category");
		query.setParameter("category", category);
		return query.getResultList();
	}
}
class ProductDaoImpl : ProductDao {

	@PersistenceContext
	private lateinit var em: EntityManager

	fun loadProductsByCategory(category: String): Collection<*> {
		val query = em.createQuery("from Product as p where p.category = :category")
		query.setParameter("category", category)
		return query.resultList
	}
}

@PersistenceContext 註解有一個選用屬性,稱為 type,預設值為 PersistenceContextType.TRANSACTION。您可以使用此預設值來接收共享的 EntityManager 代理。另一種選擇 PersistenceContextType.EXTENDED 則完全不同。這會產生所謂的擴展 EntityManager,它不是執行緒安全的,因此不得在並行存取的組件中使用,例如 Spring 管理的 singleton bean。擴展 EntityManager 實例僅適用於有狀態的組件,例如駐留在 session 中的組件,EntityManager 的生命週期不與目前的交易綁定,而是完全取決於應用程式。

方法和欄位層級的注入

您可以將指示依賴注入的註解 (例如 @PersistenceUnit@PersistenceContext) 應用於類別內部的欄位或方法 — 因此有了「方法層級注入」和「欄位層級注入」的說法。欄位層級註解簡潔且易於使用,而方法層級註解允許進一步處理注入的依賴項。在這兩種情況下,成員的可見性 (public、protected 或 private) 都無關緊要。

類別層級註解呢?

在 Jakarta EE 平台上,它們用於依賴聲明,而不是資源注入。

注入的 EntityManager 由 Spring 管理 (感知到正在進行的交易)。即使新的 DAO 實作使用方法層級的 EntityManager 注入,而不是 EntityManagerFactory,由於註解的使用,bean 定義中也不需要任何變更。

這種 DAO 風格的主要優點是它僅依賴 Java Persistence API。不需要導入任何 Spring 類別。此外,由於 JPA 註解是可以理解的,因此注入會由 Spring 容器自動應用。從非侵入性的角度來看,這很有吸引力,並且對於 JPA 開發人員來說可能感覺更自然。

基於 @Autowired 實作 DAO (通常使用建構子基礎的注入)

@PersistenceUnit@PersistenceContext 只能在方法和欄位上宣告。那麼透過建構子和其他 @Autowired 注入點提供 JPA 資源呢?

只要目標被定義為 bean,例如透過 LocalContainerEntityManagerFactoryBeanEntityManagerFactory 就可以輕鬆地透過建構子和 @Autowired 欄位/方法注入。注入點依類型完全符合原始的 EntityManagerFactory 定義。

然而,@PersistenceContext 風格的共享 EntityManager 參考無法直接用於常規的依賴注入。為了使其可用於 @Autowired 所需的基於類型的匹配,請考慮定義一個 SharedEntityManagerBean 作為 EntityManagerFactory 定義的配套。

<bean id="emf" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
	...
</bean>

<bean id="em" class="org.springframework.orm.jpa.support.SharedEntityManagerBean">
	<property name="entityManagerFactory" ref="emf"/>
</bean>

或者,您可以根據 SharedEntityManagerCreator 定義一個 @Bean 方法

@Bean("em")
public static EntityManager sharedEntityManager(EntityManagerFactory emf) {
	return SharedEntityManagerCreator.createSharedEntityManager(emf);
}

在多個持久化單元的情況下,每個 EntityManagerFactory 定義都需要伴隨一個對應的 EntityManager bean 定義,理想情況下使用限定詞,以便與不同的 EntityManagerFactory 定義匹配,從而透過 @Autowired @Qualifier("…​") 區分持久化單元。

Spring 驅動的 JPA 交易

如果您尚未閱讀 宣告式交易管理,我們強烈建議您閱讀,以更詳細地了解 Spring 的宣告式交易支持。

JPA 的建議策略是透過 JPA 的原生交易支持進行本地交易。Spring 的 JpaTransactionManager 針對任何常規 JDBC 連接池,提供了許多從本地 JDBC 交易中已知的功能 (例如交易特定的隔離級別和資源級別的唯讀最佳化),而無需 JTA 交易協調器和支援 XA 的資源。

Spring JPA 也允許配置的 JpaTransactionManager 將 JPA 交易公開給存取相同 DataSource 的 JDBC 存取程式碼,前提是已註冊的 JpaDialect 支持檢索底層的 JDBC Connection。Spring 為 EclipseLink 和 Hibernate JPA 實作提供了方言。有關 JpaDialect 的詳細資訊,請參閱下一節

對於 JTA 風格的實際資源連線的延遲檢索,Spring 為目標連線池提供了對應的 DataSource 代理類別:請參閱 LazyConnectionDataSourceProxy。這對於 JPA 唯讀交易尤其有用,這些交易通常可以從本地快取中處理,而不是存取資料庫。

理解 JpaDialectJpaVendorAdapter

作為一項進階功能,JpaTransactionManagerAbstractEntityManagerFactoryBean 的子類別允許將自訂的 JpaDialect 傳遞到 jpaDialect bean 屬性中。JpaDialect 實作可以啟用 Spring 支持的以下進階功能,通常以供應商特定的方式進行

  • 應用特定的交易語義 (例如自訂隔離級別或交易逾時)

  • 檢索事務性的 JDBC Connection (用於公開給基於 JDBC 的 DAO)

  • PersistenceException 進階轉換為 Spring 的 DataAccessException

這對於特殊的交易語義和異常的進階轉換尤其有價值。預設實作 (DefaultJpaDialect) 不提供任何特殊能力,如果需要先前列出的功能,則必須指定適當的方言。

作為更廣泛的供應商適配設施,主要用於 Spring 功能完善的 LocalContainerEntityManagerFactoryBean 設定,JpaVendorAdapterJpaDialect 的功能與其他供應商特定的預設值結合在一起。指定 HibernateJpaVendorAdapterEclipseLinkJpaVendorAdapter 是為 Hibernate 或 EclipseLink 自動配置 EntityManagerFactory 設定最方便的方法。請注意,這些供應商適配器主要設計用於 Spring 驅動的交易管理 (也就是說,用於 JpaTransactionManager)。

有關其操作以及如何在 Spring 的 JPA 支持中使用的更多詳細資訊,請參閱 JpaDialectJpaVendorAdapter javadoc。

使用 JTA 交易管理設定 JPA

作為 JpaTransactionManager 的替代方案,Spring 也允許透過 JTA 進行多資源交易協調,無論是在 Jakarta EE 環境中,還是在獨立的交易協調器 (例如 Atomikos) 中。除了選擇 Spring 的 JtaTransactionManager 而不是 JpaTransactionManager 之外,您還需要採取一些其他步驟

  • 底層的 JDBC 連接池需要支援 XA,並且與您的交易協調器整合。這在 Jakarta EE 環境中通常很簡單,透過 JNDI 公開不同類型的 DataSource。有關詳細資訊,請參閱您的應用程式伺服器文件。同樣地,獨立的交易協調器通常配備特殊的 XA 整合 DataSource 變體。同樣,請查看其文件。

  • JPA EntityManagerFactory 設定需要針對 JTA 進行配置。這是供應商特定的,通常透過在 LocalContainerEntityManagerFactoryBean 上指定為 jpaProperties 的特殊屬性。在 Hibernate 的情況下,這些屬性甚至是版本特定的。有關詳細資訊,請參閱您的 Hibernate 文件。

  • Spring 的 HibernateJpaVendorAdapter 強制執行某些 Spring 導向的預設值,例如連線釋放模式 on-close,這與 Hibernate 5.0 中的 Hibernate 自身預設值相符,但在 Hibernate 5.1+ 中不再相符。對於 JTA 設定,請確保將您的持久化單元交易類型宣告為 "JTA"。或者,將 Hibernate 5.2 的 hibernate.connection.handling_mode 屬性設定為 DELAYED_ACQUISITION_AND_RELEASE_AFTER_STATEMENT 以恢復 Hibernate 自身的預設值。有關相關說明,請參閱 使用 Hibernate 時出現虛假的應用程式伺服器警告

  • 或者,考慮從您的應用程式伺服器本身取得 EntityManagerFactory (也就是說,透過 JNDI 查找而不是本地宣告的 LocalContainerEntityManagerFactoryBean)。伺服器提供的 EntityManagerFactory 可能需要在您的伺服器配置中進行特殊定義 (使部署的可移植性降低),但它是為伺服器的 JTA 環境設定的。

JPA 互動的原生 Hibernate 設定和原生 Hibernate 交易

原生 LocalSessionFactoryBean 設定與 HibernateTransactionManager 結合使用,允許與 @PersistenceContext 和其他 JPA 存取程式碼互動。Hibernate SessionFactory 現在原生實作了 JPA 的 EntityManagerFactory 介面,而 Hibernate Session 控制代碼原生就是 JPA EntityManager。Spring 的 JPA 支持設施會自動偵測原生 Hibernate session。

因此,在許多情況下,這種原生 Hibernate 設定可以作為標準 JPA LocalContainerEntityManagerFactoryBeanJpaTransactionManager 組合的替代方案,允許在同一個本地交易中與 SessionFactory.getCurrentSession() (以及 HibernateTemplate) 和 @PersistenceContext EntityManager 互動。這種設定還提供更強大的 Hibernate 整合和更靈活的配置,因為它不受 JPA bootstrap 合約的約束。

在這種情況下,您不需要 HibernateJpaVendorAdapter 配置,因為 Spring 的原生 Hibernate 設定提供了更多功能 (例如,自訂 Hibernate Integrator 設定、Hibernate 5.3 bean 容器整合以及更強大的唯讀交易最佳化)。最後但並非最不重要的一點是,您還可以透過 LocalSessionFactoryBuilder 表示原生 Hibernate 設定,與 @Bean 風格的配置無縫整合 (不涉及 FactoryBean)。

LocalSessionFactoryBeanLocalSessionFactoryBuilder 都支持背景 bootstrap,就像 JPA LocalContainerEntityManagerFactoryBean 一樣。有關介紹,請參閱 背景 Bootstrapping

LocalSessionFactoryBean 上,這可以透過 bootstrapExecutor 屬性獲得。在程式化的 LocalSessionFactoryBuilder 上,重載的 buildSessionFactory 方法接受 bootstrap executor 參數。