spring data 入門

轉載:https://blog.csdn.net/Cs_hnu_scw/article/details/80786161

(一)讓我們來搭建Spring Data的開發環境(還是和上面一樣哦!)

步驟:

1:在pom,xml文件中添加Spring Data的相關依賴

 <!-- spring-data-jpa -->
    <dependency>
      <groupId>org.springframework.data</groupId>
      <artifactId>spring-data-jpa</artifactId>
      <version>1.8.0.RELEASE</version>
    </dependency>
    <!-- 配置hibernate的實體管理依賴-->
    <dependency>
      <groupId>org.hibernate</groupId>
      <artifactId>hibernate-entitymanager</artifactId>
      <version>4.3.6.Final</version>
    </dependency>
2:編寫JavaBean實體。(我這裏就不用上面的student,而用一個新的teacher來演示,便於大家進行查看,而且我們不需要提前在數據庫中創建表哦,當我們沒有的時候,這個是會自動創建表的呢!方便不?)

package com.hnu.scw.model;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
/**
 * @ Author     :scw
 * @ Date       :Created in 下午 8:37 2018/6/22 0022
 * @ Description:編寫一個老師實體類
 * @ Modified By:
 * @Version: $version$
 */
@Entity
public class Teacher {
    //配置表的id,並且是使用自增
    @Id
    @GeneratedValue
    private Integer id;
    //設置列的長度爲15,並且不能爲空
    @Column(length = 15 ,nullable = false)
    private String name ;
    private String classNumber ;
 
    public Integer getId() {
        return id;
    }
 
    public void setId(Integer id) {
        this.id = id;
    }
 
    public String getName() {
        return name;
    }
 
    public void setName(String name) {
        this.name = name;
    }
 
    public String getClassNumber() {
        return classNumber;
    }
 
    public void setClassNumber(String classNumber) {
        this.classNumber = classNumber;
    }
 
    @Override
    public String toString() {
        return "Teacher{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", classNumber='" + classNumber + '\'' +
                '}';
    }
}
表結構如下:

3:編寫Spring 和Spring Data的相關配置文件(我命名爲springdatacontext.xml),放在resource文件目錄下。

<?xml version="1.0" encoding="UTF-8" ?>
<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" xmlns:tx="http://www.springframework.org/schema/tx"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/data/jpa
        http://www.springframework.org/schema/data/jpa/spring-jpa.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
    <!--配置數據源-->
    <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
        <property name="url" value="jdbc:mysql:///springdata" />
        <property name="username" value="root" />
        <property name="password" value="123456" />
        <property name="driverClassName" value="com.mysql.jdbc.Driver" />
    </bean>
    <!--配置entityManagerFactory 用於管理實體的一些配置-->
    <bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
        <property name="dataSource" ref="dataSource" />
        <property name="jpaVendorAdapter">
            <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter"/>
        </property>
        <property name="packagesToScan" value="com.hnu.scw"/>
        <property name="jpaProperties">
            <props>
                <prop key="hibernate.ejb.naming_strategy" >org.hibernate.cfg.ImprovedNamingStrategy</prop>
                <prop key="hibernate.dialect" >org.hibernate.dialect.MySQL5InnoDBDialect</prop>
                <prop key="hibernate.show_sql" >true</prop>
                <prop key="hibernate.format_sql" >true</prop>
                <!--配置是否實體自動生成數據表-->
                <prop key="hibernate.hbm2ddl.auto" >update</prop>
            </props>
        </property>
    </bean>
    <!--配置事務管理器-->
    <bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
        <property name="entityManagerFactory" ref="entityManagerFactory"/>
    </bean>
    <!--配置支持事務註解-->
    <tx:annotation-driven transaction-manager="transactionManager"/>
    <!--配置spring data-->
    <jpa:repositories base-package="com.hnu.scw" entity-manager-factory-ref="entityManagerFactory"/>
    <!--配置spring的掃描包-->
    <context:component-scan base-package="com.hnu.scw"/>
</beans>
進入我們真正的使用了哦!!!!!!重點來了~~~~~

4:編寫我們需要進行操作實體的Dao層接口-------------------重點,,好好看這接口的內容!

package com.hnu.scw.repository;
import com.hnu.scw.model.Teacher;
import org.springframework.data.jpa.repository.Modifying;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.Repository;
import org.springframework.data.repository.RepositoryDefinition;
import org.springframework.data.repository.query.Param;
import java.util.List;
 
/**
 * @ Author     :scw
 * @ Date       :Created in 下午 9:17 2018/6/22 0022
 * @ Description:基於Spring Data接口的dao層開發接口
 * @ Modified By:
 * @Version: $version$
 */
//有兩種方式,要麼用註解要麼用繼承
//@RepositoryDefinition(domainClass = Teacher.class ,idClass = Integer.class)
public interface TeacherRepository extends Repository<Teacher , Integer> {
    //===============使用springdata默認方式=============================
    /**
     * 根據名字查詢老師
     * @param name
     * @return
     */
    Teacher findByName(String name);
 
    /**
     * 根據班級名稱進行查詢老師(這裏用到模糊匹配like)
     * @param classNumber
     * @return
     */
    List<Teacher> findByclassNumberLike(String classNumber);
}
重點分析一波:

(1)首先,我們這個接口是需要繼承Repository這個接口

(2)泛型參數:第一個是我們制定這個接口所需要進行操作的實體JavaBean

                         第二個是我們實體JavaBean中主鍵的類型。(因爲我這主鍵是id,用的Integer類型)

(3)繼承的Repository這個接口有什麼用?讓我們看看源碼分析一下

什麼?????這個接口啥都沒有呀。。。對的,這個接口是什麼都沒有,就類似Serializable接口一樣,就是一個空接口,專業點說就是標記接口。。那麼,這個到底有什麼用呢?

大家,,認真看認真看!!!!!!!!!()

     第一點:Repository是一個空接口,即是一個標記接口。
     第二點:若我們定義的接口繼承了Repository,則該接口會被IOC容器識別爲一個Repository Bean,納入到IOC容器中,進而可以在該接口中定義滿足一定規範的方法。IOC容器中實際存放了繼承了Repository的接口的實現類,而這個實現類由spring幫助完成 。在applicationContext.xml中我們配置了springdata:這裏的base-package指定了Repository Bean所在的位置,在這個包下的所有的繼承了Repository的接口都會被IOC容器識別並納入到容器中,如果沒有繼承Repository則IOC容器無法識別。
     第三點:我們也可以通過註解的方式替代繼承Repository接口@RepositoryDefinition(domainClass=需要處理的實體類的類型,IdClass=主鍵的類型)。
     第四點:看看它有哪些子類:

那這些子類都有什麼用呢?別急,這在我後面都會提到哦!!!!

5:好了,我們來進行單元測試吧!

注意:阿,爲什麼不需要寫接口的實現類嗎?是不是博文你忘記說了呀。。。。。不不不不,咱們就是不寫,你先按照我上面的接口定義兩個方法就可以了。(不過,你要保證你的實體和我的是一樣的teacher哦!要不然肯定不行的)

package com.hnu.scw;
import com.hnu.scw.model.Teacher;
import com.hnu.scw.repository.TeacherRepository;
import org.junit.Before;
import org.junit.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import java.util.List;
/**
 * @ Author     :scw
 * @ Date       :Created in 下午 8:41 2018/6/22 0022
 * @ Description:${description}
 * @ Modified By:
 * @Version: $version$
 */
public class SpringDataTest {
    //用於加載spring配置文件
    private ApplicationContext context = null;
 
    //用於操作老師實體的接口
    @Autowired
    private TeacherRepository teacherRepository = null;
    @Before
    public void getContext(){
        context = new ClassPathXmlApplicationContext("springdatacontext.xml");
        //通過類名進行注入
        teacherRepository = context.getBean(TeacherRepository.class);
    }
 
    /**
     * 直接執行這個測試方法,然後就再去看一下數據庫就會發生對應實體中的內容到數據庫中了
     */
    @Test
    public void testCreateTableAuto(){
 
    }
 
    /**
     * 測試springdata中的findByName方法(沒有任何的實現,這就是springdata的強大)
     */
    @Test
    public void testSpringDataFindName(){
        Teacher teacher = teacherRepository.findByName("哈哈");
        System.out.println(teacher);
    }
 
    /**
     * 測試使用springdata進行模糊匹配
     */
    @Test
    public void testSpringDataLike(){
        List<Teacher> teachers = teacherRepository.findByclassNumberLike("%班班%");
        for (Teacher teacher:teachers) {
            System.out.println(teacher);
        }
    }
}
溫馨提示:當我們直接上面的代碼後,就會發現,竟然竟然能夠進行數據操作耶,但是我並沒有寫實現類,這是爲什麼爲什麼爲什麼呢?

好的,咱們的重點來了,好好看看~~~~

知識點1:爲什麼只需要在接口中寫方法名稱,而不需要寫實現類就可以進行數據庫的操作?

解析:是否還記得我們的接口是繼承的Respository這個接口呢?是的,這個就是它的強大的地方。一切的一切都是歸根於它。這個原因我在上面已經說過了哦。

知識點2:在接口中方法名稱是隨便寫的嗎?有沒有什麼規範呢?

解析:這個當然不能隨便寫了,而且我們要實現我們想要的操作,我們必須滿足Spring Data定義的規範。

我來分析一下我寫的示例的方法,爲什麼這樣命名就可以實現我們想要的操作了。

第一:

首先:findBy就表示我們要進行查詢操作,所以,如果你需要進行查詢操作,那你就就需要前綴是findBy

其次:Name :這個也不是隨便的哦。如果我們想根據實體類中的名字屬性進行查詢,那麼就是Name,如果是想根據班級,那麼我們就要寫classNumber。當然,裏面的參數的命名就是隨便的啦,參數名字就沒什麼影響了

最後:Teacher返回類型:這個沒什麼特別,我們查詢的就是這個實體的數據,當然就是返回這個類型的對象啦。

第二:

首先:findBy這個和上面解釋一樣,我就不多說。

其次:classNumber這個也不多說,因爲,我是要進行這個屬性的模糊查詢呀!

最後:Like:這個可是很重要的哦。這後綴就代表是進行模糊匹配啦。所以,如果你要進行模糊匹配就要Like結束方法名。

OK,如果這樣,那我數據庫操作麻煩起來的話,那麼方法名不是特別長,特別難記了,而且好多規範都不知道,怎麼辦呢?彆着急呀,下面我就來給你介紹一下,有哪些命令的規範。。(其實嘛,後面當然有解決辦法啦~哈哈)

關鍵字    方法命名    sql where字句
And    findByNameAndPwd    where name= ? and pwd =?
Or    findByNameOrSex    where name= ? or sex=?
Is,Equals    findById,findByIdEquals    where id= ?
Between    findByIdBetween    where id between ? and ?
LessThan    findByIdLessThan    where id < ?
LessThanEquals    findByIdLessThanEquals    where id <= ?
GreaterThan    findByIdGreaterThan    where id > ?
GreaterThanEquals    findByIdGreaterThanEquals    where id > = ?
After    findByIdAfter    where id > ?
Before    findByIdBefore    where id < ?
IsNull    findByNameIsNull    where name is null
isNotNull,NotNull    findByNameNotNull    where name is not null
Like    findByNameLike    where name like ?
NotLike    findByNameNotLike    where name not like ?
StartingWith
findByNameStartingWith    where name like '?%'
EndingWith    findByNameEndingWith    where name like '%?'
Containing    findByNameContaining    where name like '%?%'
OrderBy    findByIdOrderByXDesc    where id=? order by x desc
Not    findByNameNot    where name <> ?
In    findByIdIn(Collection<?> c)    where id in (?)
NotIn    findByIdNotIn(Collection<?> c)    where id not  in (?)
True    
findByAaaTue
where aaa = true
False    findByAaaFalse    where aaa = false
IgnoreCase    findByNameIgnoreCase    where UPPER(name)=UPPER(?)
咳咳咳咳,這麼多,記不住,怎麼辦?那麼,我就教你進一步的優化~畢竟先苦後甜嘛~~~~

(二)通過@Query註解來優化Spring Data接口中的方法

我們在上面已經看到了,一般接口定義方法的名字是比較麻煩的,當然,如果Spring Data只能做到這樣的程度,那就也太low了,所以如果解決上面的方法呢?很簡單,通過註解就可以解決了。

1:示例代碼:(這個還是寫在上面接口中即可,請注意我代碼裏面的註釋)

 //==============使用query註解開發==============================================
    /**
     * 通過query註解進行開發模糊匹配(利用索引參數的方法)
     * @param classNumber
     * @return
     */
    @Query("select t from Teacher t where t.classNumber like %?1%")
    List<Teacher> queryTeacher(String classNumber);
 
    /**
     * 通過老師的名字來進行查詢數據
     * @param name
     * @return
     */
    @Query("select t from Teacher t where t.name = ?1")
    Teacher queryTeacherByName(String name );
    /**
     * 通過老師的名字來進行查詢數據(利用命名參數的方法,注意query註解的寫法不一樣的)
     * @param name
     * @return
     */
    @Query("select t from Teacher t where t.name = :name")
    Teacher queryTeacherByName2(@Param("name") String name );
 
    /**
     * 使用原生的SQL語句進行操作(注意from這時候用的就是數據庫的表名,而不是實體類名)
     * 必須添加nativeQuery = true,因爲默認是false的
     * @return
     */
    @Query(nativeQuery = true , value = "select count(1) from teacher")
    long countTeacherNumber();
2:編寫單元測試;

    /**
     * 測試使用springdata中的query註解進行開發模糊查詢
     */
    @Test
    public void testQueryTeacher(){
        List<Teacher> teachers = teacherRepository.queryTeacher("班班");
        for (Teacher teacher:teachers) {
            System.out.println(teacher);
        }
    }
 
    /**
     * 測試通過佔位符進行操作查詢
     */
    @Test
    public void testQueryTeacherByName(){
        Teacher teacher = teacherRepository.queryTeacherByName("哈哈");
        System.out.println(teacher);
    }
    /**
     * 測試通過別名進行操作查詢
     */
    @Test
    public void testQueryTeacherByName2(){
        Teacher teacher = teacherRepository.queryTeacherByName2("哈哈");
        System.out.println(teacher);
    }
 
    /**
     * 測試使用原生的SQL語句進行開發
     */
    @Test
    public void testCountTeacherNumber(){
        long number = teacherRepository.countTeacherNumber();
        System.out.println("數據總條數爲:" + number);
    }
(三)如何使用Spring Data進行刪除更新的數據庫操作

我們之前都是寫的查詢操作,那麼如果進行更新和刪除操作,是不是也是一樣的?

然而,請注意,並不是的,而且特別要注意下面兩點:

(1)對於更新和刪除操作,必須在接口的方法上面添加@Modifying註解,這樣就用於標識這是一個修改的操作

(2)必須在調用這個接口方法的地方(一般就是service層)使用事務,即用@Transactional註解進行標識。

示例代碼:

1:編寫接口方法:

 //================進行springdata的更新刪除的處理======================
 
    /**
     * 根據老師表的id進行修改對應數據的老師名字
     * 必須要添加@Modifying註解,並且要在調用的方法上添加事務註解@Transactional
     * @param name
     * @param id
     */
    @Modifying
    @Query("update Teacher  t set t.name = ?1 where t.id = ?2")
    void updateTeacherById(String name , Integer id);:
2:編寫service層代碼

package com.hnu.scw.service;
import com.hnu.scw.model.Teacher;
import com.hnu.scw.repository.TeacherCrudRespository;
import com.hnu.scw.repository.TeacherRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
 
import javax.transaction.Transactional;
import java.util.List;
 
/**
 * @ Author     :scw
 * @ Date       :Created in 下午 5:29 2018/6/23 0023
 * @ Description:編寫springdata相關的service層代碼
 * @ Modified By:
 * @Version: $version$
 */
@Service
public class SpringDataService {
    @Autowired
    private TeacherRepository teacherRepository;
 
    @Autowired
    private TeacherCrudRespository teacherCrudRespository;
    /**
     * 根據id進行修改老師的名字
     * @param name
     * @param id
     */
    @Transactional
    public void updateTeacher(String name , Integer id){
        teacherRepository.updateTeacherById(name , id);
    }
}
3:單元測試代碼:

package com.hnu.scw.service;
import com.hnu.scw.model.Teacher;
import com.hnu.scw.repository.TeacherRepository;
import org.junit.Before;
import org.junit.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
 
import java.util.ArrayList;
 
/**
 * @ Author     :scw
 * @ Date       :Created in 下午 5:27 2018/6/23 0023
 * @ Description:測試service層的方法
 * @ Modified By:
 * @Version: $version$
 */
public class SpringDataServiceTest {
    //用於加載spring配置文件
    private ApplicationContext context = null;
 
    @Autowired
    private SpringDataService springDataService = null ;
 
    @Before
    public void getContext(){
        context = new ClassPathXmlApplicationContext("springdatacontext.xml");
        //通過類名進行注入
        springDataService = context.getBean(SpringDataService.class);
    }
 
    /**
     * 測試springdata的更新操作的方法
     * 注意點:接口必須添加@Modifying註解
     * 調用層service必須有事務註解@Transactional
     */
    @Test
    public void testUpdateTeacher(){
        springDataService.updateTeacher("呵呵" , 1);
    }
}:
Spring Data的進階

    根據我們上面的內容,已經學會了基本的Spring Data的操作。那麼,它就這麼點技能麼?當然不是,請看下面的內容。

(一)接口繼承CrudRespository接口

說明: CrudRepository 接口繼承於 Repository 接口,並新增了簡單的增、刪、查等方法。

主要的方法如下:

示例代碼:

package com.hnu.scw.repository;
import com.hnu.scw.model.Teacher;
import org.springframework.data.repository.CrudRepository;
 
/**
 * @ Author     :scw
 * @ Date       :Created in 下午 5:38 2018/6/23 0023
 * @ Description:通過繼承CrudRespository接口(因爲可以快速進行crud相關的方法開發)
 * @ Modified By:
 * @Version: $version$
 */
public interface TeacherCrudRespository extends CrudRepository<Teacher , Integer>{
 
}
示例單元測試類:大家就可以根據我上面貼的方法進行隨便編寫就好了啦。就不多寫測試方法了~~~~~~

(二)接口繼承JpaRespository接口

說明:JpaRepository支持接口規範方法名查詢。意思是如果在接口中定義的查詢方法符合它的命名規則,就可以不用寫實現了。這個我在前面就說了有哪些命名規則的哦~

主要的接口如下:

示例代碼:

package com.hnu.scw.repository;
import com.hnu.scw.model.Teacher;
import org.springframework.data.jpa.repository.JpaRepository;
 
/**
 * @ Author     :scw
 * @ Date       :Created in 下午 5:59 2018/6/23 0023
 * @ Description:測試繼承JpaRepository接口的方法
 * @ Modified By:
 * @Version: $version$
 */
public interface TeacherJpaRepository extends JpaRepository<Teacher ,Integer>{
}
單元測試代碼:

package com.hnu.scw;
import com.hnu.scw.model.Teacher;
import com.hnu.scw.repository.TeacherJpaRepository;
import com.hnu.scw.repository.TeacherPagingAndSortRespository;
import org.junit.Before;
import org.junit.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
 
/**
 * @ Author     :scw
 * @ Date       :Created in 下午 6:00 2018/6/23 0023
 * @ Description:測試繼承Respositoty接口的相關的操作
 * @ Modified By:
 * @Version: $version$
 */
public class JpaRespositotyTest {
    //用於加載spring配置文件
    private ApplicationContext context = null;
 
    //用於操作老師實體的接口
    @Autowired
    private TeacherJpaRepository teacherJpaRepository = null;
    @Before
    public void getContext(){
        context = new ClassPathXmlApplicationContext("springdatacontext.xml");
        //通過類名進行注入
        teacherJpaRepository = context.getBean(TeacherJpaRepository.class);
    }
 
    /**
     * 測試JpaRepository接口中相關的查找數據的方法
     */
    @Test
    public void testJpaFind(){
        //查詢id=20的數據
        Teacher oneTeacher = teacherJpaRepository.findOne(20);
        System.out.println(oneTeacher);
 
        //判斷id=100的數據是否存在於數據庫中
        boolean exists = teacherJpaRepository.exists(100);
        System.out.println("數據存在嗎?" + exists);
    }
}
(三)接口繼承PagingAndSortRespository接口

說明:這個接口主要就是實現了分頁和排序的方法。。。所以,分頁很重要哦~

方法接口如下:

接口示例代碼:

package com.hnu.scw.repository;
 
import com.hnu.scw.model.Teacher;
import org.springframework.data.repository.PagingAndSortingRepository;
 
/**
 * @ Author     :scw
 * @ Date       :Created in 下午 5:48 2018/6/23 0023
 * @ Description:通過繼承PagingAndSortRespository接口來快速進行分頁開發
 * @ Modified By:
 * @Version: $version$
 */
public interface TeacherPagingAndSortRespository extends PagingAndSortingRepository<Teacher ,Integer>{
}
單元測試代碼:
package com.hnu.scw;
import com.hnu.scw.model.Teacher;
import com.hnu.scw.repository.TeacherPagingAndSortRespository;
import com.hnu.scw.repository.TeacherRepository;
import org.junit.Before;
import org.junit.Test;
import org.springframework.beans.factory.annotation.Autowired;
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.Sort;
 
/**
 * @ Author     :scw
 * @ Date       :Created in 下午 5:49 2018/6/23 0023
 * @ Description:測試PagingAndSortRespository接口的分頁方法
 * @ Modified By:
 * @Version: $version$
 */
public class PagingAndSortRespositoryTest {
    //用於加載spring配置文件
    private ApplicationContext context = null;
 
    //用於操作老師實體的接口
    @Autowired
    private TeacherPagingAndSortRespository teacherPagingAndSortRespository = null;
    @Before
    public void getContext(){
        context = new ClassPathXmlApplicationContext("springdatacontext.xml");
        //通過類名進行注入
        teacherPagingAndSortRespository = context.getBean(TeacherPagingAndSortRespository.class);
    }
 
    /**
     * 測試通過繼承PagingAndSortRespository進行分頁的相關開發
     * 相當的方便
     */
    @Test
    public void testPagingTeacher(){
        PageRequest pageRequest = new PageRequest(0, 5);
        Page<Teacher> page = teacherPagingAndSortRespository.findAll(pageRequest);
        System.out.println("查詢的總頁數:" + page.getTotalPages());
        System.out.println("查詢的總數據條數:" + page.getTotalElements());
        System.out.println("查詢的當前頁數:" + (page.getNumber() + 1));
        System.out.println("查詢的數據的內容:" + page.getContent());
        System.out.println("查詢的當前頁的數據條數:" + page.getNumberOfElements());
    }
 
    /**
     * 測試分頁和排序的方法
     */
    @Test
    public void testPagingAndSortTeacher(){
        //按照id的降序進行排序
        Sort.Order sortOrder = new Sort.Order(Sort.Direction.DESC, "id");
        //構建排序對象
        Sort sort = new Sort(sortOrder);
        //把分頁和排序對象放入參數
        PageRequest pageRequest = new PageRequest(0, 5 , sort);
        Page<Teacher> page = teacherPagingAndSortRespository.findAll(pageRequest);
        System.out.println("查詢的總頁數:" + page.getTotalPages());
        System.out.println("查詢的總數據條數:" + page.getTotalElements());
        System.out.println("查詢的當前頁數:" + (page.getNumber() + 1));
        System.out.println("查詢的數據的內容:" + page.getContent());
        System.out.println("查詢的當前頁的數據條數:" + page.getNumberOfElements());
    }
}
(四)接口繼承JpaSpecificationExcutor接口

說明:不屬於Repository體系,實現一組 JPA Criteria 查詢相關的方法。Specification:封裝 JPA Criteria 查詢條件。通常使用匿名內部類的方式來創建該接口的對象。

主要接口方法如下:主要就是條件過濾,比如我們在分頁的時候需要一些條件,這樣就可以更好的進行分頁處理。

示例代碼如下:(用於實現分頁和過濾的作用)

package com.hnu.scw.repository;
import com.hnu.scw.model.Teacher;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
import org.springframework.data.repository.PagingAndSortingRepository;
 
/**
 * @ Author     :scw
 * @ Date       :Created in 下午 6:04 2018/6/23 0023
 * @ Description:繼承JpaSpecificationExecutorRepository接口
 * @ Modified By:
 * @Version: $version$
 */
public interface TeacherJpaSpecificationExecutorRepository extends PagingAndSortingRepository<Teacher , Integer> ,JpaSpecificationExecutor<Teacher >{
}
單元測試如下:

package com.hnu.scw;
import com.hnu.scw.model.Teacher;
import com.hnu.scw.repository.TeacherJpaSpecificationExecutorRepository;
import com.hnu.scw.repository.TeacherRepository;
import jdk.nashorn.internal.runtime.Specialization;
import org.junit.Before;
import org.junit.Test;
import org.springframework.beans.factory.annotation.Autowired;
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.Sort;
import org.springframework.data.jpa.domain.Specification;
import javax.persistence.criteria.*;
 
/**
 * @ Author     :scw
 * @ Date       :Created in 下午 6:11 2018/6/23 0023
 * @ Description:繼承JpaSpecificationExecutor接口的方法
 * @ Modified By:
 * @Version: $version$
 */
public class JpaSpecificationExecutorTest {
    //用於加載spring配置文件
    private ApplicationContext context = null;
 
    //用於操作老師實體的接口
    @Autowired
    private TeacherJpaSpecificationExecutorRepository teacherJpaSpecificationExecutorRepository = null;
    @Before
    public void getContext(){
        context = new ClassPathXmlApplicationContext("springdatacontext.xml");
        //通過類名進行注入
        teacherJpaSpecificationExecutorRepository = context.getBean(TeacherJpaSpecificationExecutorRepository.class);
    }
 
    /**
     * 進行測試JpaSpecificationExecutor這個接口的相關方法
     * 實現查詢第一頁的前五條數據根據id升序排序,並且id要大於20
     */
    @Test
    public void testJpaSpecificationExecutor(){
        //設置分頁要進行過濾的條件
        Specification specification = new Specification<Teacher>(){
            @Override
            public Predicate toPredicate(Root<Teacher> root,
                                         CriteriaQuery<?> criteriaQuery,
                                         CriteriaBuilder criteriaBuilder) {
                Path path = root.get("id");
                //設置過濾條件爲id大於20 ,其中的gt就是表示大於
                Predicate predicate = criteriaBuilder.gt(path , 20);
                return predicate;
            }
        };
        //按照id的降序進行排序
        Sort.Order sortOrder = new Sort.Order(Sort.Direction.ASC, "id");
        //構建排序對象
        Sort sort = new Sort(sortOrder);
        PageRequest pageRequest = new PageRequest(0, 5 , sort);
        //把分頁和排序對象以及過濾對象放入參數
        Page<Teacher> page = teacherJpaSpecificationExecutorRepository.findAll(specification ,pageRequest);
        System.out.println("查詢的總頁數:" + page.getTotalPages());
        System.out.println("查詢的總數據條數:" + page.getTotalElements());
        System.out.println("查詢的當前頁數:" + (page.getNumber() + 1));
        System.out.println("查詢的數據的內容:" + page.getContent());
        System.out.println("查詢的當前頁的數據條數:" + page.getNumberOfElements());
    }
}
讓我給你總結總結Spring Data

(1)上面就是關於Spring Data相關的一些處理操作,總體來說還是比較容易掌握的。

(2)我們在使用任何的框架或者插件的時候,我們都需要想個問題,我們爲什麼要用這個而不用其他的?那麼其他的又有什麼缺點,而我們用的又有什麼好處呢?這些都是該思考的東西,而不要只是進行學習,而不會其原理。

(3)Spring Data剛開始接觸可能還是需要個過程,畢竟它的接口比較多,操作數據庫的方法也比較靈活,所以,還是需要多進行練習的。

(4)Spring Data相比通用Mapper插件來說,其減少了xml文件的編寫,而是用更加靈活的註解和方法命名規範來進行處理,但是他們各自有好處,不能說哪個完全不好,完全看開發需求和場景來決定的。

(5)這裏講解的只是入門,當然是需要各位進行不斷擴展的哦~~~~~歡迎進行交流

(6)最後,我把項目的源碼放到百度雲網方便各位進行學習:

鏈接:https://pan.baidu.com/s/1Cc2MP6zM-NWDKQbNqpRfVA             密碼:5hur

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章