Spring Data JPA 簡單介紹

背景 

考慮到公司應用中數據庫訪問的多樣性和複雜性,目前正在開發UDSL(統一數據訪問層),開發到一半的時候,偶遇SpringData 工程。發現兩者的思路驚人的一致。
於是就花了點時間瞭解SpringData,可能UDSL II期會基於SpringData做擴展

SpringData相關資料 
介紹:針對關係型數據庫,KV數據庫,Document數據庫,Graph數據庫,Map-Reduce等一些主流數據庫,採用統一技術進行訪問,並且儘可能簡化訪問手段。
目前已支持的數據庫有(主要):MongoDB,Neo4j,Redis,Hadoop,JPA等

SpringData官方資料(強烈推薦,文檔非常詳細)
SpringData主頁:http://www.springsource.org/spring-data 
SpringDataJPA 指南文檔:http://static.springsource.org/spring-data/data-jpa/docs/current/reference/html/  (非常詳細)
SpringDataJPA Examples: https://github.com/SpringSource/spring-data-jpa-examples (非常詳細的例子)

Spring-Data-Jpa簡介 
Spring Data Jpa 極大簡化了數據庫訪問層代碼,只要3步,就能搞定一切
1. 編寫Entity類,依照JPA規範,定義實體
2. 編寫Repository接口,依靠SpringData規範,定義數據訪問接口(注意,只要接口,不需要任何實現)
3. 寫一小陀配置文件 (Spring Scheme配置方式極大地簡化了配置方式)

下面,我依賴Example中的例子,簡單地介紹下以上幾個步驟
User.java


 1  /** 
 2   * User Entity Sample
 3   * 
 4   *  @author  <a href="mailto:[email protected]">Stone.J</a> Aug 25, 2011
 5    */ 
 6  @Entity
 7  public   class  User  extends  AbstractPersistable < Long >  {
 8  
 9       private   static   final   long  serialVersionUID  =   - 2952735933715107252L ;
10  
11      @Column(unique  =   true )
12       private  String            username;
13       private  String            firstname;
14       private  String            lastname;
15  
16       public  String getUsername() {
17           return  username;
18      }
19  
20       public   void  setUsername(String username) {
21           this .username  =  username;
22      }
23  
24       public  String getFirstname() {
25           return  firstname;
26      }
27  
28       public   void  setFirstname(String firstname) {
29           this .firstname  =  firstname;
30      }
31  
32       public  String getLastname() {
33           return  lastname;
34      }
35  
36       public   void  setLastname(String lastname) {
37           this .lastname  =  lastname;
38      }
39  

沒什麼技術,JPA規範要求怎麼寫,它就怎麼寫

Repository.java


 1  /** 
 2   * User Repository Interface.
 3   * 
 4   *  @author  <a href="mailto:[email protected]">Stone.J</a> Aug 25, 2011
 5    */ 
 6  public   interface  SimpleUserRepository  extends  CrudRepository < User, Long > , JpaSpecificationExecutor <User >  {
 7  
 8       public  User findByTheUsersName(String username);
 9  
10       public  List < User >  findByLastname(String lastname);
11  
12      @Query( " select u from User u where u.firstname = ? " )
13       public  List < User >  findByFirstname(String firstname);
14  
15      @Query( " select u from User u where u.firstname = :name or u.lastname = :name " )
16       public  List < User >  findByFirstnameOrLastname(@Param( " name " ) String name);
17      
18  

需要關注它繼承的接口,我簡單介紹幾個核心接口

Repository: 僅僅是一個標識,表明任何繼承它的均爲倉庫接口類,方便Spring自動掃描識別
CrudRepository: 繼承Repository,實現了一組CRUD相關的方法
PagingAndSortingRepository: 繼承CrudRepository,實現了一組分頁排序相關的方法
JpaRepository: 繼承PagingAndSortingRepository,實現一組JPA規範相關的方法
JpaSpecificationExecutor: 比較特殊,不屬於Repository體系,實現一組JPA Criteria查詢相關的方法

不需要寫任何實現類,Spring Data Jpa框架幫你搞定這一切。

Spring Configuration

 1  < beans > 
 2       < bean id = " entityManagerFactory "   class = "org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean " > 
 3           < property name = " dataSource "  ref = " dataSource "   /> 
 4           < property name = " jpaVendorAdapter " > 
 5               < bean  class = " org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter " > 
 6                   < property name = " generateDdl "  value = " true "   /> 
 7                   < property name = " database "  value = " HSQL "   /> 
 8               </ bean > 
 9           </ property > 
10           < property name = " persistenceUnitName "  value = " jpa.sample "   /> 
11       </ bean > 
12  
13       < bean id = " transactionManager "   class = " org.springframework.orm.jpa.JpaTransactionManager " > 
14           < property name = " entityManagerFactory "  ref = " entityManagerFactory "   /> 
15       </ bean > 
16  
17       < jdbc:embedded - database id = " dataSource "  type = " HSQL "   /> 
18  
19  
20       < jpa:repositories base - package = " org.springframework.data.jpa.example.repository.simple "   /> 
21  </ beans>

核心代碼只要配置一行:<jpa:repositories base-package="org.springframework.data.jpa.example.repository.simple" />即可。上面的僅僅是數據源,事務的配置而已。

至此,大功告成,即可運行

 1  /** 
 2   * Intergration test showing the basic usage of { @link  SimpleUserRepository}.
 3   * 
 4   *  @author  <a href="mailto:[email protected]">Stone.J</a> Aug 25, 2011
 5    */ 
 6  @RunWith(SpringJUnit4ClassRunner. class )
 7  @ContextConfiguration(locations  =   " classpath:simple-repository-context.xml " )
 8  @Transactional
 9  public   class  SimpleUserRepositorySample {
10  
11      @Autowired
12      SimpleUserRepository repository;
13      User                 user;
14  
15      @Before
16       public   void  setUp() {
17          user  =   new  User();
18          user.setUsername( " foobar " );
19          user.setFirstname( " firstname " );
20          user.setLastname( " lastname " );
21      }
22  
23       //  crud方法測試 
24      @Test
25       public   void  testCrud() {
26          user  =  repository.save(user);
27          assertEquals(user, repository.findOne(user.getId()));
28      }
29  
30       //  method query測試 
31      @Test
32       public   void  testMethodQuery()  throws  Exception {
33          user  =  repository.save(user);
34          List < User >  users  =  repository.findByLastname( " lastname " );
35          assertNotNull(users);
36          assertTrue(users.contains(user));
37      }
38  
39       //  named query測試 
40      @Test
41       public   void  testNamedQuery()  throws  Exception {
42          user  =  repository.save(user);
43          List < User >  users  =  repository.findByFirstnameOrLastname( " lastname " );
44          assertTrue(users.contains(user));
45      }
46  
47       //  criteria query測試 
48      @Test
49       public   void  testCriteriaQuery()  throws  Exception {
50          user  =  repository.save(user);
51          List < User >  users  =  repository.findAll( new  Specification < User > () {
52  
53              @Override
54               public  Predicate toPredicate(Root < User >  root, CriteriaQuery <?>  query, CriteriaBuilder cb) {
55                   return  cb.equal(root.get( " lastname " ),  " lastname " );
56              }
57          });
58          assertTrue(users.contains(user));
59      }
60  

其中,寫操作相對比較簡單,我不做詳細介紹,針對讀操作,我稍微描述下:
Method Query: 方法級別的查詢,針對 findBy , find , readBy , readgetBy等前綴的方法,解析方法字符串,生成查詢語句,其中支持的關鍵詞有:


Named Query: 針對一些複雜的SQL,支持原生SQL方式,進行查詢,保證性能
Criteria Query: 支持JPA標準中的Criteria Query
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章