如果你在開發的時候還爲如何,寫繁瑣的數據庫訪問的語句或複雜條件的多表查詢而頭痛時。
你可以不妨試一下spring-data-jpa 爲你提供的一整套全面的數據訪問模板, 也爲你的開發提高效率。其擴展性也會讓你大開眼見.廢話不多說了下面就來試試看吧......
引入:
Spring Data是SpringSource基金會下的一個用於簡化數據庫訪問,並支持雲服務的開源框架。其主要目標是使得數據庫的訪問變得方便快捷,並支持map-reduce框架和雲計算數據服務。對於擁有海量數據的項目,可以用Spring Data來簡化項目的開發。
然而針對不同的數據儲存訪問使用相對的類庫來操作訪問。Spring Data中已經爲我們提供了很多業務中常用的一些接口和實現類來幫我們快速構建項目,比如分頁、排序、DAO一些常用的操作。
今天主要是對Spring Data下的JPA模塊進行講解。
爲什麼說Spring Data能幫助我們快速構建項目呢,因爲Spring Data已經在數據庫訪問層上幫我們實現了公用功能了,而我們只需寫一個接口去繼承Spring Data提供給我們接口,便可實現對數據庫的訪問及操作,類似於spring-orm的TemplateDAO。
----------------------------------------------邪惡的分割線------------------------------------------------------------------------------
核心接口:
下面來看一下Repository的最頂層接口:
- public interface Repository<T, ID extends Serializable> {
- }
這個接口只是一個空的接口,目的是爲了統一所有Repository的類型,其接口類型使用了泛型,泛型參數中T代表實體類型,ID則是實體中id的類型。
再來看一下Repository的直接子接口CrudRepository中的方法:
- public interface CrudRepository<T, ID extends Serializable> extends Repository<T, ID> {
- <S extends T> S save(S entity);
- <S extends T> Iterable<S> save(Iterable<S> entities);
- T findOne(ID id);
- boolean exists(ID id);
- Iterable<T> findAll();
- Iterable<T> findAll(Iterable<ID> ids);
- long count();
- void delete(ID id);
- void delete(T entity);
- void delete(Iterable<? extends T> entities);
- void deleteAll();
- }
此接口中的方法大多是我們在訪問數據庫中常用的一些方法,如果我們要寫自己的DAO類的時候,只需定義個接口來集成它便可使用了。
再來看看Spring Data未我們提供分頁和排序的Repository的接口PagingAndSortingRepository:
- public interface PagingAndSortingRepository<T, ID extends Serializable> extends CrudRepository<T, ID> {
- Iterable<T> findAll(Sort sort);
- Page<T> findAll(Pageable pageable);
- }
這些Repository都是spring-data-commons提供給我們的核心接口,spring-data-commons是Spring Data的核心包。這個接口中爲我們提供了數據的分頁方法,以及排序方法。看吧,spring-data讓我們省了很多心了,一切都按照這個規範進行構造,就連業務系統中常用到的一些操作都爲我們考慮到了,而我們只需更用心的去關注業務邏輯層。spring-data將repository的顆粒度劃得很細,其實我覺得spring的框架中將每個類的顆粒度都劃得很細,這主要也是爲了責任分離。
----------------------------------------------邪惡的分割線------------------------------------------------------------------------------
JPA實現:
針對spring-data-jpa又提供了一系列repository接口,其中有JpaRepository和JpaSpecificationExecutor,這2個接口又有什麼區別呢,我們分別來看看這2個接口的源碼。
JpaRepository.class
- public interface JpaRepository<T, ID extends Serializable> extends PagingAndSortingRepository<T, ID> {
- List<T> findAll();
- List<T> findAll(Sort sort);
- <S extends T> List<S> save(Iterable<S> entities);
- void flush();
- T saveAndFlush(T entity);
- void deleteInBatch(Iterable<T> entities);
- void deleteAllInBatch();
這個類繼承自PagingAndSortingRepository,看其中的方法,可以看出裏面的方法都是一些簡單的操作,並未涉及到複雜的邏輯。當你在處理一些簡單的數據邏輯時,便可繼承此接口,看一個小例子吧。本文JPA供應者選擇的是Hibernate EntityManager,當然讀者們也可以選擇其他的JPA供應者,比如EclipseLink、OpenJPA,反正JPA是個標準,在無須修改的情況下便可移植。
先定義一用戶實體類User.class:
- @Entity
- @Table( name = "spring_data_user" )
- @PrimaryKeyJoinColumn( name = "id" )
- public class User extends IdGenerator{
- private static final long serialVersionUID = 1L;
- private String name;
- private String username;
- private String password;
- private String sex;
- private Date birth;
- private String address;
- private String zip;
- //省略getter和setter
- }
Id生成策略是採用的表生成策略,這裏就不貼代碼了,spring的配置文件我也就不貼出來了,反正就那些東西,網上一查,遍地都是。後續我會在將demo附上來。
實體類是有了,現在得寫一個持久層,這樣才能操作數據庫啊,現在我們來看一下持久層。IUserDao.class:
- @Repository("userDao")
- public interface IUserDao extends JpaRepository<User, Long>{}
再在spring的配置文件中加上以下代碼。
- <beans xmlns="http://www.springframework.org/schema/beans"
- xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xmlns:jpa="http://www.springframework.org/schema/data/jpa"
- xsi:schemaLocation="http://www.springframework.org/schema/beans
- http://www.springframework.org/schema/data/jpa
- http://www.springframework.org/schema/data/jpa/spring-jpa.xsd">
- <jpa:repositories base-package="org.tea.springdata.**.dao" />
- </beans>
加上這段後Spring就會將指定包中@Repository的類註冊爲bean,將bean託管給Spring。這樣定義完了就OK了!哦,就這樣就可以操作數據庫了?
是的,前面我就已經說了,Spring data已經幫我們寫好一個實現類了,而簡單的操作我們只須這樣繼承JpaRepository就可以做CRUD操作了。再寫個業務類來測試一把吧。由於我用的Cglib來動態代理,所以就不定義接口了,直接定義類UserService.class:
- @Service("userService")
- public class UserService {
- @Autowired
- private IUserDao dao;
- public void save(User user) {
- dao.save(user);
- }
- public void delete(Long id) {
- dao.delete(id);
- }
- public void update(User user) {
- dao.saveAndFlush(user);
- }
- public List<User> findAll() {
- return dao.findAll();
- }
- }
來寫一單元測試。
- public class UserServiceTest {
- private static ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
- private static UserService userService = (UserService) context.getBean("userService");
- public void saveUser() {
- StopWatch sw = new StopWatch(getClass().getSimpleName());
- sw.start("Add a user information.");
- User u = new User();
- u.setName("John");
- u.setSex("Man");
- u.setUsername("JohnZhang");
- u.setPassword("123456");
- u.setBirth(new Date());
- userService.save(u);
- sw.stop();
- System.err.println(sw.prettyPrint());
- }
- public static void main(String[] args) {
- UserServiceTest test = new UserServiceTest();
- test.saveUser();
- }
- }
綠了,高興了,測試通過!
額,都沒用Junit怎麼會綠呢,開個玩笑。
其餘繼承下來的操作方法,大家都可以自己測試一下,如沒意外,應該都會測試通過。
好吧,今天就暫時分享到這了,你千萬別以爲Spring-data就這麼點功能,這只是spring-data中最入門級的知識,後續還有很多東西值得學習,在下一篇文章中我會列出spring-data-jpa中精華的部分,對其進行講解,並附上Demo供下載。
寫一篇博客真不容易,好歹也要花上幾小時,文筆不行,如有不正之處,歡迎拍磚。如覺得還不錯,請頂一票。謝謝!