詳細介紹springData

1.什麼是SpringData?
Spring Data 項目的目的是爲了簡化構建基於 Spring 框架應用的數據訪問計數,包括非關係數據庫、Map-Reduce 框架、雲數據服務等等;另外也包含對關係數據庫的訪問支持。java


Spring Data 包含多個子項目:spring


Commons - 提供共享的基礎框架,適合各個子項目使用,支持跨數據庫持久化
Hadoop - 基於 Spring 的 Hadoop 做業配置和一個 POJO 編程模型的 MapReduce 做業
Key-Value  - 集成了 Redis 和 Riak ,提供多個經常使用場景下的簡單封裝
Document - 集成文檔數據庫:CouchDB 和 MongoDB 並提供基本的配置映射和資料庫支持
Graph - 集成 Neo4j 提供強大的基於 POJO 的編程模型
Graph Roo AddOn - Roo support for Neo4j
JDBC Extensions - 支持 Oracle RAD、高級隊列和高級數據類型
JPA - 簡化建立 JPA 數據訪問層和跨存儲的持久層功能
Mapping - 基於 Grails 的提供對象映射框架,支持不一樣的數據庫
Examples - 示例程序、文檔和圖數據庫
Guidance - 高級文檔


 看了這麼多專業的介紹,其實Spring Data項目旨在爲你們提供一種通用的編碼模式,統一咱們的API。

 2.HelloWorld展現
 學習任何東西,從一個簡單易懂的DEMO學起,會很是重要,下面先來看一個簡單的HelloWorlddemo
 直接看一下Dao層吧!sql

<span style="font-family:Comic Sans MS;font-size:18px;">/**       
 * @FileName: PersonRepotory.java     
 * @Package:com.tgb.springdata.Entity     
 * @Description: TODO    
 * @author: LUCKY      
 * @date:2015年11月8日 下午6:38:58     
 * @version V1.0       
 */    
package com.tgb.springdata.Entity;    
    
import java.util.Date;    
import java.util.List;    
    
import org.hibernate.type.TrueFalseType;    
import org.springframework.data.jpa.repository.JpaRepository;    
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;    
import org.springframework.data.jpa.repository.Modifying;    
import org.springframework.data.jpa.repository.Query;    
import org.springframework.data.jpa.repository.support.JpaRepositoryFactory;    
import org.springframework.data.repository.CrudRepository;    
import org.springframework.data.repository.PagingAndSortingRepository;    
import org.springframework.data.repository.Repository;    
import org.springframework.data.repository.query.Param;    
    
/**    
 * @ClassName: PersonRepotory     
 * @Description: TODO    
 * @author: LUCKY    
 * @date:2015年11月8日 下午6:38:58       
 */    
    
/*  
 * 1.Repository是一個空接口,便是一個標記接口  
 * 2.若咱們定義的接口繼承了Repository,則該接口會被IOC容器識別爲一個Repository Bean  
 * 注入到IOC容器中,進而能夠在該接口中定義知足必定規則的接口  
 * 3.實際上也能夠經過一個註解@RepositoryDefination 註解來替代Repository接口  
 */    
/*  
 * 在Repository子接口中聲明方法  
 * 1.不是隨便聲明的,而須要符合必定的規範  
 * 2.查詢方法以find|read|get開發  
 * 3.涉及條件查詢,條件的屬性須要定義關鍵字鏈接  
 * 4.要注意的額是,條件的屬性以字母大寫  
 * 5.支持屬性的級聯查詢,若當前類有符合條件的屬性,則優先使用,則不使用級聯屬性  
 * 若須要使用級聯屬性,則屬性之間使用——進行鏈接  
 */    
//@RepositoryDefinition(domainClass=Person.class,idClass=Integer.class)    
public interface PersonRepotory  extends JpaRepository<Person,Integer>,JpaSpecificationExecutor<Person>,PersonDao  {    
    
        
    //根據lastname,來獲取對應的Person    
    Person getByLastName(String lastName);    
        
    //Where lastName like ?% and id<?    
    List<Person> getByLastNameStartingWithAndIdLessThan(String lastName,Integer id);    
        
        
    //Where lastName like ?% and id<?    
    List<Person> getByLastNameEndingWithAndIdLessThan(String lastName,Integer id);    
        
    //where email In(?,?,?) Or birth < ?    
    List<Person> getByEmailInOrBirthLessThan(List<String> emails,Date birth);    
        
    //where a.id>?    
    List<Person> getByAddressIdGreaterThan(Integer id);    
        
    //查詢id值最大的那個person    
    //使用@Query註解能夠自定義JPQL語句,語句能夠實現更靈活的查詢    
    @Query("SELECT p FROM Person p WHERE p.id=(SELECT max(p2.id) FROM Person p2)")    
    Person getMaxIdPerson();    
        
    //爲@Query註解傳遞參數的方式1:使用佔位符    
    @Query("SELECT P FROM Person P where P.lastName=?1 AND P.email=?2")    
    List<Person> testQueryAnnotationParams1(String lastName,String email);    
        
        
        
    //爲@Query註解傳遞參數的方式2:使用命名參數方式    
        @Query("SELECT P FROM Person P where P.lastName=:lastName AND P.email=:email")    
        List<Person> testQueryAnnotationParams2(@Param("email")String email,@Param("lastName")String lastName);    
            
            
        //Spring Data 運行在佔位符上添加%%    
        @Query("select p from Person p where p.lastName like %?1% or p.email like %?2%")    
        List<Person> testQueryAnnotationLikeParam(String lastName,String email);    
            
        //設置nativeQuery=true 可使用原生的sql查詢    
        @Query(value="SELECT count(id) FROM jpa_persons",nativeQuery=true)    
        public long getTotalCount();    
            
            
        //能夠經過自定義的JPQL 完成update和delete操做,注意:JPQL不支持Insert操做    
        //在@Query註解中編寫JPQL語句,但必須使用@Modify進行修飾,以通知SpringData,這是一個Update或者Delete    
        //Update或者delete操做,須要使用事務,此時須要定義Service層,在service層的方法上添加事務操做    
        //默認狀況下,SpringData的每一個方法上有事務,但都是一個只讀事務,他們不能完成修改操做    
        @Modifying    
        @Query("update Person p set p.email=:email where id=:id")    
        void updatePersonEmail(@Param("id")Integer id,@Param("email")String email);    
            
            
}    
</span>

 在Spring Data JPA中經過繼承接口就能夠了,下面來看一下是如何來調用的
數據庫


<span style="font-family:Comic Sans MS;font-size:18px;">/**       
 * @FileName: SpringDataTest.java     
 * @Package:com.tgb.test     
 * @Description: TODO    
 * @author: LUCKY      
 * @date:2015年11月8日 下午5:35:37     
 * @version V1.0       
 */    
package com.tgb.test;    
    
import static org.junit.Assert.*;    
    
import java.sql.SQLException;    
import java.util.ArrayList;    
import java.util.Arrays;    
import java.util.Date;    
import java.util.List;    
    
import javax.persistence.criteria.CriteriaBuilder;    
import javax.persistence.criteria.CriteriaQuery;    
import javax.persistence.criteria.Path;    
import javax.persistence.criteria.Predicate;    
import javax.persistence.criteria.Root;    
import javax.sql.DataSource;    
    
import org.junit.Test;    
import org.springframework.context.ApplicationContext;    
import org.springframework.context.support.ClassPathXmlApplicationContext;    
import org.springframework.data.domain.Page;    
import org.springframework.data.domain.PageRequest;    
import org.springframework.data.domain.Pageable;    
import org.springframework.data.domain.Sort;    
import org.springframework.data.domain.Sort.Direction;    
import org.springframework.data.domain.Sort.Order;    
import org.springframework.data.jpa.domain.Specification;    
    
import com.tgb.springdata.Entity.Person;    
import com.tgb.springdata.Entity.PersonRepotory;    
import com.tgb.springdata.Service.PersonService;    
    
/**    
 * @ClassName: SpringDataTest     
 * @Description: TODO    
 * @author: LUCKY    
 * @date:2015年11月8日 下午5:35:37       
 */    
public class SpringDataTest {    
    
    private PersonRepotory personRepotory=null;    
    private PersonService personService;    
    private ApplicationContext ctx=null;    
    {    
        ctx=new ClassPathXmlApplicationContext("applicationContext.xml");    
        personRepotory=ctx.getBean(PersonRepotory.class);    
        personService=ctx.getBean(PersonService.class);    
    }    
        
        
    @Test    
    public void testKeyWorlds(){    
        List<Person> persons=personRepotory.getByLastNameStartingWithAndIdLessThan("BB", 10);    
        System.out.println(persons);    
            
        List<Person> persons1=personRepotory.getByLastNameEndingWithAndIdLessThan("BB", 10);    
        System.out.println(persons);    
        System.out.println(persons1);    
            
        persons=personRepotory.getByEmailInOrBirthLessThan(Arrays.asList("aa@qq.com","bb@qq.com"),new Date());    
        System.out.println(persons.size());    
    }    
        
        
        
        
        
    @Test    
    public void testDataSource() throws SQLException{    
        DataSource dataSource=ctx.getBean(DataSource.class);    
        System.out.println(dataSource.getConnection());    
    }    
        
    @Test    
    public void TestJpa(){    
            
    }    
        
    @Test    
    public void testKeyWorlds2(){    
        List<Person> persons=personRepotory.getByAddressIdGreaterThan(1);    
        System.out.println(persons);    
    }    
        
    @Test    
    public void testQueryAnnotation(){    
        Person person=personRepotory.getMaxIdPerson();    
//      System.out.println(person);    
            
        List<Person> persons=personRepotory.testQueryAnnotationParams1("AA", "bb");    
        System.out.println(persons);    
            
        List<Person> persons1=personRepotory.testQueryAnnotationParams2("bb", "AA");    
        System.out.println(persons1);    
    }    
        
        
    @Test    
    public void testModifing(){    
//      personRepotory.updatePersonEmail(1, "@@qq.com");    
        personService.updatePersonEmail("aa@aa", 1);    
    }    
        
    @Test    
    public void testQueryLikeAnnotationParam(){    
        List<Person> persons=personRepotory.testQueryAnnotationLikeParam("%AA%", "%b%");    
        System.out.println(persons);    
            
        long count=personRepotory.getTotalCount();    
        System.out.println(count);    
    }    
        
        
        
        
    @Test    
    public void HelloWorldSpringData(){    
        PersonRepotory personRepotory=ctx.getBean(PersonRepotory.class);    
        System.out.println(personRepotory.getClass().getName());    
        Person person=personRepotory.getByLastName("AA");    
        System.out.println(person);    
            
        }    
        
        
    @Test    
    public void testCrudRepository()    
    {    
        List<Person> persons=new ArrayList<Person>();    
        for (int i = 1; i < 10000; i++) {    
            Person person=new Person();    
            person.setBirth(new Date());    
            person.setEmail("@2"+i+" com");    
            persons.add(person);    
        }    
            
        long startTime=System.currentTimeMillis();    
        personService.savePersons(persons);    
        long endTime=System.currentTimeMillis();    
        System.out.println((endTime-startTime)/1000);    
    }    
        
        
    @Test    
    public void testPagingAndSortingRespository(){    
        //pageNumber是從0開始的    
        int pageNumber=4;    
        int pageSize=5;    
        //PageAble 接口一般用的是PageRequest實現類,其中封裝了須要分頁的信息    
        //排序相關的,sor封裝了排序的信息    
        Order order1=new Order(Direction.DESC, "id");    
            
        Order order2=new Order(Direction.DESC, "email");    
        Sort sort=new Sort(order1,order2);    
            
            
        Pageable pageable=new PageRequest(pageNumber, pageSize,sort);    
        Page<Person> page=personRepotory.findAll(pageable);    
        System.out.println("總記錄數"+page.getTotalElements());    
        System.out.println("當前第幾頁"+page.getNumber());    
        System.out.println("總頁數"+page.getTotalPages());    
        System.out.println("當前頁面的List"+page.getContent());    
        System.out.println("當前頁面的記錄數"+page.getNumberOfElements());    
    }    
        
        
    @Test    
    public void testJpaRepository(){    
        Person person=new Person();    
        person.setBirth(new Date());    
        person.setEmail("aa");    
        person.setLastName("xyz");    
        personRepotory.saveAndFlush(person);    
            
            
    }    
        
        
    /*  
     * 實現帶查詢條件的分頁效果 id>5  
     * 調用JpaSpecificationExecutor的page<T> findAll(Speciation<T>,PageAble pageable)  
     * specification:封裝了JPA Criteria 查詢的條件  
     * pageable:封裝了請求分頁的消息,例如pageno,pagesize,sort  
     */    
    @Test    
    public void testJpaSpeciationExecutor(){    
        int pageNo=0;    
        int pageSize=5;    
        PageRequest pageRequest=new PageRequest(pageNo, pageSize);    
        //一般使用Specification 的匿名內部類,    
        Specification<Person> specification=new Specification<Person>() {    
    
        /*  
         * @param root:表明的查詢的實體類  
         * @param query:能夠從中獲得Root對象,即告知JPA Criteria查詢要查詢哪個實體類,  
         * 還能夠來添加查詢條件,還能夠結合EntityManager對象獲得最終查詢的TypedQuery 對象  
         * @Param cb:criteriabuildre對象,用於建立Criteria相關的對象工程,固然能夠從中獲取到predicate類型  
         * @return:表明一個查詢條件  
         */    
            @Override    
            public Predicate toPredicate(Root<Person> root,    
                    CriteriaQuery<?> query, CriteriaBuilder cb) {    
//              Path path=root.get("id");    
//              Predicate predicate=cb.gt(path, 5);    
                    
                Predicate p1=cb.like(root.get("id").as(String.class), "%"+"1"+"%");    
                Predicate p2=cb.equal(root.get("lastName").as(String.class), "sd");    
                Predicate p3=cb.like(root.get("email").as(String.class), "%s%");    
//              構建組合的Predicate示例:    
                Predicate p = cb.and(p3,cb.or(p1,p2));    
                    
                return p;    
            }    
                
        };    
            
        Page<Person> page=personRepotory.findAll(specification,pageRequest);    
        
        System.out.println("總記錄數"+page.getTotalElements());    
        System.out.println("當前第幾頁"+page.getNumber());    
        System.out.println("總頁數"+page.getTotalPages());    
        System.out.println("當前頁面的List"+page.getContent());    
        System.out.println("當前頁面的記錄數"+page.getNumberOfElements());    
    }    
        
        
    @Test    
    public void testCustomRepositoryMethod(){    
        personRepotory.test();    
    }    
        
        
}  
</span>

或許會感到奇怪,爲什麼Dao只單純的是一個接口,沒有實現類呢?其實這就是Spring Data JPA爲咱們封裝了,只要按照Spring Data JPA的規範來定義,就會自動爲咱們生成一個默認的代理實現類。


編程

 3.Repository 接口app

基礎的 Repository提供了最基本的數據訪問功能,其幾個子接口則擴展了一些功能。它們的繼承關係以下: 
–Repository:僅僅是一個標識,代表任何繼承它的均爲倉庫接口類
–CrudRepository:繼承Repository,實現了一組CRUD相關的方法 
–PagingAndSortingRepository:繼承CrudRepository,實現了一組分頁排序相關的方法 
–JpaRepository:繼承PagingAndSortingRepository,實現一組JPA規範相關的方法 
–自定義的 XxxxRepository須要繼承 JpaRepository,這樣的XxxxRepository接口就具有了通用的數據訪問控制層的能力。
–JpaSpecificationExecutor:不屬於Repository體系,實現一組JPACriteria查詢相關的方法 


 4.@Query 註解
這種查詢能夠聲明在 Repository方法中,擺脫像命名查詢那樣的約束,將查詢直接在相應的接口方法中聲明,結構更爲清晰,這是Springdata 的特有實現。
//查詢id值最大的那個person
//使用@Query註解能夠自定義JPQL語句,語句能夠實現更靈活的查詢
@Query("SELECT p FROM Person p WHERE p.id=(SELECT max(p2.id) FROM Person p2)")
Person getMaxIdPerson();

 5.@Modifying 註解
框架

 @Query 與 @Modifying這兩個annotation一塊兒聲明,可定義個性化更新操做,例如只涉及某些字段更新時最爲經常使用,示例以下
//能夠經過自定義的JPQL 完成update和delete操做,注意:JPQL不支持Insert操做
//在@Query註解中編寫JPQL語句,但必須使用@Modify進行修飾,以通知SpringData,這是一個Update或者Delete
//Update或者delete操做,須要使用事務,此時須要定義Service層,在service層的方法上添加事務操做
//默認狀況下,SpringData的每一個方法上有事務,但都是一個只讀事務,他們不能完成修改操做
@Modifying
@Query("update Person p set p.email=:email where id=:id")
void updatePersonEmail(@Param("id")Integer id,@Param("email")String email);


dom

相關文章
相關標籤/搜索