1. 程式人生 > >Spring Data JPA學習

Spring Data JPA學習

Spring Data JPA是在Spring JPA的基礎上,對持久層做了簡化。使用者只需宣告持久層的介面,不需要實現該介面。Spring Data JPA內部會根據不同的策略、通過不同的方法建立Query操作資料庫。

Spring 將 EntityManager 的建立與銷燬、事務管理等程式碼抽取出來,並由其統一管理,開發者不需要關心這些,業務方法中只剩下操作領域物件的程式碼,事務管理和 EntityManager建立、銷燬的程式碼都不再需要開發者關心了。

Spring Data JPA使用方法

Spring Data JPA 簡化持久層開發大致需要如下幾個步驟。

(1) 引入依賴的jar檔案

以Maven方式為例,引入jar包:

<dependency>
	<groupId>org.springframework.data</groupId>
	<artifactId>spring-data-jpa</artifactId>
	<version>1.7.0.RELEASE</version>
</dependency>
(2) 在Spring的配置檔案中新增配置

在配置檔案中設定實體類所在的包,定義entityManagerFactory、transactionManager等資訊。
Spring會在base-package中定義的package和其子package中搜尋繼承了Repository的介面。

<beans 
    ...
	xmlns:jpa="http://www.springframework.org/schema/data/jpa"
	xsi:schemaLocation=" 
                ...
                http://www.springframework.org/schema/data/jpa 
                http://www.springframework.org/schema/data/jpa/spring-jpa.xsd ">
	<!-- 其他... -->
	<!-- JPA實體管理工廠的配置 -->
	<bean id="entityManagerFactory"
		class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
		<property name="dataSource" ref="dataSource" />
		<property name="jpaVendorAdapter" ref="hibernateJpaVendorAdapter" />
		<property name="packagesToScan" value="com.mj.dsl.jpa" /><!--待掃描的實體類包,不再需要persistence.xml了 -->
		<property name="jpaProperties">
			<props>
				<prop key="hibernate.ejb.naming_strategy">org.hibernate.cfg.ImprovedNamingStrategy</prop>
				<prop key="hibernate.show_sql">false</prop>
				<prop key="hibernate.hbm2ddl.auto">update</prop>
			</props>
		</property>
	</bean>

	<!-- Spring Data JPA配置 -->
	<jpa:repositories base-package="com.eric.test.jpa" />

	<!--指定實現JPA的介面卡 -->
	<bean id="hibernateJpaVendorAdapter"
		class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
		<property name="databasePlatform" value="org.hibernate.dialect.MySQLDialect" />
		<!-- <property name="databasePlatform" value="org.hibernate.dialect.DerbyDialect" /> -->
	</bean>

	<!-- JPA事務配置 -->
	<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
		<property name="entityManagerFactory" ref="entityManagerFactory" />
	</bean>
	
	<bean id="transactionTemplate" class="org.springframework.transaction.support.TransactionTemplate" scope="prototype">
		<property name="transactionManager" ref="transactionManager" />
	</bean>

	<!-- 使用annotation定義事務 -->
	<tx:annotation-driven transaction-manager="transactionManager"
		proxy-target-class="true" />
	<!-- 其他... -->			
</beans>

(3) 宣告持久層介面

該介面繼承Repository <T,ID>或其子介面,T是領域實體,ID是領域實體的主鍵型別。例:

public interface UserRepository extends Repository<User, Long> {……}

(4) 在持久層的介面中宣告需要的業務方法

Spring Data JPA將會根據指定的策略為該方法生成實現程式碼。使用者不需要實現該介面。例:

List<User> findByLastname(String lastname);

Repository 介面說明

Repository是SpringData的核心介面,它並不提供任何方法,使用者需要自己定義需要的方法。
 
(1) 繼承Repository介面的兩種方法
 ①直接繼承
public interface UserDao extends Repository<User, Long> { …… }
 ②使用@RepositoryDefinition註解
@RepositoryDefinition(domainClass = User.class, idClass = Long.class)
public interface UserDao { …… }
(2) 其他Repository介面
CrudRepository(Spring Data提供) 繼承Repository,提供增刪改查方法,可以直接呼叫。
PagingAndSortingRepository(Spring Data提供) 繼承CrudRepository,增加了分頁查詢和排序兩個方法
JpaRepository(Spring Data JPA提供) 繼承PagingAndSortingRepository,是針對JPA技術的介面,提供flush(),saveAndFlush(),deleteInBatch()等方法

建立Query

Spring Data JPA會通過解析使用者在持久層介面中定義的方法名來生成相應的query語句。解析時能被識別的keyword和包含這些keyword的方法會被解析成什麼樣的Query,如下所示:
And --- 等價於 SQL 中的 and 關鍵字,比如 findByUsernameAndPassword(String user, Striang pwd);
Or --- 等價於 SQL 中的 or 關鍵字,比如 findByUsernameOrAddress(String user, String addr);
Between --- 等價於 SQL 中的 between 關鍵字,比如 findBySalaryBetween(int max, int min);
LessThan --- 等價於 SQL 中的 "<",比如 findBySalaryLessThan(int max);
GreaterThan --- 等價於 SQL 中的">",比如 findBySalaryGreaterThan(int min);
IsNull --- 等價於 SQL 中的 "is null",比如 findByUsernameIsNull();
IsNotNull --- 等價於 SQL 中的 "is not null",比如 findByUsernameIsNotNull();
NotNull --- 與 IsNotNull 等價;
Like --- 等價於 SQL 中的 "like",比如 findByUsernameLike(String user);
NotLike --- 等價於 SQL 中的 "not like",比如 findByUsernameNotLike(String user);
OrderBy --- 等價於 SQL 中的 "order by",比如 findByUsernameOrderBySalaryAsc(String user);
Not --- 等價於 SQL 中的 "! =",比如 findByUsernameNot(String user);
In --- 等價於 SQL 中的 "in",比如 findByUsernameIn(Collection<String> userList) ,方法的引數可以是 Collection 型別,也可以是陣列或者不定長引數;
NotIn --- 等價於 SQL 中的 "not in",比如 findByUsernameNotIn(Collection<String> userList) ,方法的引數可以是 Collection 型別,也可以是陣列或者不定長引數;

LocalContainerEntityManagerFactoryBean與LocalEntityManagerFactoryBean的區別

LocalEntityManagerFactoryBean
程式管理型:實體管理器是在程式直接向實體管理器工廠請求一個實體管理器時建立的。在這種情況下,程式負責開啟或關閉實體管理器,並且在事務中控制管理器。這種型別最適合不運行於Java EE容器的獨立程式。 

LocalContainerEntityManagerFactoryBean
容器管理型:實體管理器由Java EE容器建立和管理。這種情況下,程式根本不與實體管理器工廠進行互動,實體管理器是通過注入或利用JNDI直接獲得的,容器負責配置實體管理器工廠。這種型別最適合希望不考慮persistence.xml中的特殊性而在JPA配置之上維持某種控制的Java EE容器。