最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

JpaRepository如何實(shí)現(xiàn)增刪改查并進(jìn)行單元測(cè)試

 更新時(shí)間:2021年11月25日 09:58:47   作者:yeungsinsin  
這篇文章主要介紹了JpaRepository如何實(shí)現(xiàn)增刪改查并進(jìn)行單元測(cè)試,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教

JpaRepository增刪改查進(jìn)行單元測(cè)試

項(xiàng)目結(jié)構(gòu)

在這里插入圖片描述

創(chuàng)建UserInfoDaoI.java文件,繼承JpaRepository。(不需要實(shí)現(xiàn)類)

在這里插入圖片描述

根據(jù)條件查詢/刪除

在這里插入圖片描述

更新

在這里插入圖片描述

參考此文章進(jìn)行開發(fā)

單元測(cè)試

在這里插入圖片描述

SpringDataJPA的Repository理解

repository抽取擴(kuò)展理解

在SpringDataJPA中使用repository來(lái)進(jìn)行數(shù)據(jù)層操作(作用相當(dāng)于dao層),直接使用repository對(duì)象調(diào)用已經(jīng)實(shí)現(xiàn)好的數(shù)據(jù)層操作方法進(jìn)行CRUD、分頁(yè)、排序等操作,還可以在自定義repository接口中依據(jù)一定規(guī)則擴(kuò)展功能。在一個(gè)項(xiàng)目中,我們平常需要為每一個(gè)實(shí)體類都創(chuàng)建一個(gè)repository接口,我們自定義的repository接口都需要去繼承JpaRepository接口,以具有所有的數(shù)據(jù)層操作功能,但也僅僅限于簡(jiǎn)單查詢等操作。通常我們?yōu)榱四軐?shí)現(xiàn)復(fù)雜查詢操作,會(huì)繼續(xù)繼承JpaSpecificationExecutor接口,簡(jiǎn)單說(shuō)就是建立一個(gè)規(guī)則來(lái)進(jìn)行查詢。

這樣雖然在很大程度上簡(jiǎn)化了開發(fā)代碼難度,但在為每一實(shí)體類創(chuàng)建對(duì)應(yīng)repository接口時(shí),發(fā)現(xiàn)存在大量的重復(fù)代碼,這時(shí)很容易的我們會(huì)想到抽取父類來(lái)簡(jiǎn)化一些公共代碼并順帶可以對(duì)子類進(jìn)行一些規(guī)范。雖然SpringDataJPA提供的功能已經(jīng)足夠強(qiáng)大了,但是依然還是不能滿足實(shí)際開發(fā)中的所有需求,所以我們想在抽取父類的同時(shí)實(shí)現(xiàn)對(duì)其功能的擴(kuò)展。在進(jìn)行這個(gè)操作之前我們需要了解一下整個(gè)repository的結(jié)構(gòu)。

應(yīng)該免不了有疑問,我們僅僅是定義了一個(gè)接口去實(shí)現(xiàn)了JpaRepository接口,怎么就能創(chuàng)建對(duì)象了,而且還能給我們實(shí)現(xiàn)一系列的數(shù)據(jù)層操作?這就要從為什么自定義repository接口要去繼承JpaRepository接口說(shuō)起了:

在這里插入圖片描述

通過它的結(jié)構(gòu)圖可以看出,JpaRepository的父類分別是PagingAndSortingRepository、CrudRepository和Repository,前兩個(gè)接口中前者定義了分頁(yè)和排序功能,后者看名字就可以知道里面全是CRUD操作,值得注意的是,它這保存和修改方法都是save。Repository接口呢沒有定義任何功能,它的作用就是標(biāo)識(shí)。這么說(shuō)吧我們自定義的接口繼承JpaRepository接口就相當(dāng)于繼承了Repository接口,那么SpringDataJPA在掃描時(shí)只要掃描到我們某個(gè)接口實(shí)現(xiàn)了Repository接口,就為自動(dòng)的為其創(chuàng)建代理實(shí)現(xiàn)子類(通過AOP實(shí)現(xiàn))。但是為什么就只為我們自定義的repository接口創(chuàng)建了實(shí)現(xiàn)子類而沒有為PagingAndSortingRepository、CrudRepository、JpaRepository創(chuàng)建呢?這個(gè)同樣能從結(jié)構(gòu)圖中看出答案:它們都是打上了NoRepositoryBean注解的,凡是打上了這個(gè)注解的接口SPringDataJPA都不會(huì)為其創(chuàng)建實(shí)現(xiàn)子類。

這樣一來(lái),我們自定義的接口繼承了以上三個(gè)接口后就相當(dāng)于“集百家之長(zhǎng)”了,擁有了它們所有功能,但是問題又來(lái)了,它們?cè)倥=K歸還是接口啊,又不能創(chuàng)建對(duì)象,是怎么操作的呢?

在這里插入圖片描述

原來(lái),SpringDataJPA自動(dòng)的為自動(dòng)創(chuàng)建的repository實(shí)現(xiàn)子類繼承了SimpleJpaRepository類,而SimpleJpaRepository又是SpringDataJPA的Repository默認(rèn)實(shí)現(xiàn)兩大方式之一,自然而然的自動(dòng)創(chuàng)建的repository代理子類也就具有了所有的功能。至此,SpringDataJPA中repository實(shí)現(xiàn)數(shù)據(jù)層操作的原理也大概講清楚了,接下來(lái)就說(shuō)說(shuō)擴(kuò)展了:雖然SPringDataJPA提供的功能已經(jīng)足夠強(qiáng)大了,但是依然還是不能滿足實(shí)際開發(fā)中的所有需求。所以說(shuō)了這么久終于要說(shuō)到重點(diǎn)了:抽取父類、擴(kuò)展功能。

在這里插入圖片描述

通過上圖,大概也能看出結(jié)構(gòu)了,大概思想:在原本應(yīng)該繼承JpaRepository的實(shí)體類repository接口與JpaRepository之間增加了一層而已,讓BaseRepository繼承JpaSpecificationExecutor、JpaRepository,實(shí)體類repository接口繼承BaseRepository接口;這樣便能實(shí)現(xiàn)在擁有原有SpringDataJPA的Repository功能的情況下在BaseRepository擴(kuò)展其他功能,但在這需要注意:在SpringDataJPA中默認(rèn)會(huì)使自動(dòng)創(chuàng)建的repository代理實(shí)現(xiàn)子類(例:圖中的EmployeeRepositoryImpl)去繼承SimpleJpaRepository,很明顯我們并不能使用默認(rèn)的,因?yàn)檫@樣會(huì)使得我們的BaseRepository接口定義的一無(wú)是處,所以我們需要再創(chuàng)建一個(gè)自定義的BaseRepository實(shí)現(xiàn)BaseRepositoryImpl繼承SimpleJpaRepository,再修改配置使得SpringDataJPA自動(dòng)創(chuàng)建出的所有實(shí)體類repository的實(shí)現(xiàn)代理子類都去繼承我們的BaseRepositoryImpl,這樣我們便能徹底實(shí)現(xiàn)擴(kuò)展了。

前面說(shuō)過SpringDataJPA會(huì)默認(rèn)的將自動(dòng)創(chuàng)建出的實(shí)現(xiàn)代理子類繼承SimpleJpaRepository類,所以我們需要修改SimpleJpaRepository為我們自定義的BaseRepositoryImpl類,SpringDataJPA是通過JpaRepositoryFactoryBean來(lái)實(shí)現(xiàn)創(chuàng)建并繼承過程的。我們只用自定義一個(gè)BaseRepositoryFactoryBean來(lái)繼承JpaRepositoryFactoryBean,接下來(lái)只用修改最終返回功能對(duì)象,和確定功能對(duì)象的類型即可。最后記得要在spring的配置文件中在SpringDataJPA的配置中添加修改創(chuàng)建對(duì)象的factoryBean為我們自定義的BaseRepositoryFactoryBean。

最后,記得修改各實(shí)體repository接口繼承我們定義的BaseRepository接口

接下來(lái)貼一貼代碼

接下來(lái)貼一貼代碼

BaseRepository

import com.xer.aisell.query.BaseQuery;
import org.springframework.data.domain.Page;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
import org.springframework.data.repository.NoRepositoryBean;
import java.io.Serializable;
import java.util.List;
/**
 * 雖然jpadata提供的功能已經(jīng)足夠強(qiáng)大了,但是依然還是不能滿足實(shí)際開發(fā)中的所有需求
 * 所以希望在具有它功能的前提下再拓展一些功能
 * 之前是通過每個(gè)實(shí)體類的repository接口來(lái)直接繼承JpaRepository接口,現(xiàn)在我們可以在中間添加一個(gè)父類接口BaseRepository
 * BaseRepository繼承JpaRepository,再由實(shí)體類repository來(lái)繼承BaseRepository
 * 這樣就能夠?qū)崿F(xiàn)既實(shí)現(xiàn)了功能,又能隨時(shí)擴(kuò)展功能
 * @param <T>
 * @param <ID>
 */
@NoRepositoryBean
public interface BaseRepository<T,ID extends Serializable> extends JpaRepository<T,ID>,JpaSpecificationExecutor<T>{
    //根據(jù)Query拿到分頁(yè)對(duì)象(分頁(yè))
    Page findPageByQuery(BaseQuery baseQuery);
    //根據(jù)Query拿到對(duì)應(yīng)的所有數(shù)據(jù)(不分頁(yè))
    List<T> findByQuery(BaseQuery baseQuery);
    //根據(jù)jpql與對(duì)應(yīng)的參數(shù)拿到數(shù)據(jù)
    List findByJpql(String jpql,Object... values);
}

BaseRepositoryImpl

import com.xer.aisell.query.BaseQuery;
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.jpa.domain.Specification;
import org.springframework.data.jpa.repository.support.SimpleJpaRepository;
import javax.persistence.EntityManager;
import javax.persistence.Query;
import java.io.Serializable;
import java.util.List;
public class BaseRepositoryImpl<T,ID extends Serializable> extends SimpleJpaRepository<T,ID> implements BaseRepository<T,ID> {
    private final EntityManager entityManager;
    public BaseRepositoryImpl(Class<T> domainClass, EntityManager em) {
        super(domainClass, em);
        this.entityManager = em;
    }
    @Override
    /**
     * 分頁(yè)
     */
    public Page findPageByQuery(BaseQuery baseQuery) {
        //拿到條件
        Specification spec = baseQuery.createSpec();
        //創(chuàng)建排序
        Sort sort = baseQuery.getSort();
        //分頁(yè)
        Pageable page = new PageRequest(baseQuery.getJPACurrentPage(), baseQuery.getPageSize(), sort);
        return super.findAll(spec,page);
    }
    /**
     * 不分頁(yè)查詢
     * @param baseQuery
     * @return
     */
    @Override
    public List findByQuery(BaseQuery baseQuery) {
        //獲取到條件
        Specification spec = baseQuery.createSpec();
        //排序
        Sort sort = baseQuery.getSort();
        return super.findAll(spec,sort);
    }
    /**
     *
     * 根據(jù)傳入JPQL查詢
     * @param jpql
     * @param values
     * @return
     */
    @Override
    public List findByJpql(String jpql, Object... values) {
        Query query = entityManager.createQuery(jpql);
        //為傳入JPQL填充條件值
        if (values != null) {
            for (int i = 0;i < values.length;i++) {
                query.setParameter(i+1,values[i]);
            }
        }
        return query.getResultList();
    }
}

EmployeeRepository接口

import com.xer.aisell.domain.Employee;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
import org.springframework.data.jpa.repository.Query;
import java.util.List;
/***
 *用于數(shù)據(jù)庫(kù)操作
 */
public interface EmployeeRepository extends BaseRepository<Employee,Long> {
    /**
     * 可以自己擴(kuò)展
     */
    List<Employee> findByUsernameLike(String username);
    /**
     * 使用@Query
     *  實(shí)現(xiàn)自己寫JPQL查詢
     */
    @Query("select o from Employee o where username like ?1")
    List<Employee> findByUsername(String username);
    /**
     * 當(dāng)然也可以實(shí)現(xiàn)自己寫SQL
     */
    @Query(nativeQuery = true,value = "SELECT COUNT(*) FROM employee")
    Long getCount();
}

BaseRepositoryFactoryBean類(難)

import org.springframework.data.jpa.repository.support.JpaRepositoryFactory;
import org.springframework.data.jpa.repository.support.JpaRepositoryFactoryBean;
import org.springframework.data.repository.Repository;
import org.springframework.data.repository.core.RepositoryInformation;
import org.springframework.data.repository.core.RepositoryMetadata;
import org.springframework.data.repository.core.support.RepositoryFactorySupport;
import javax.persistence.EntityManager;
import java.io.Serializable;
public class BaseRepositoryFactoryBean<T extends Repository<S, ID>, S, ID extends Serializable> extends JpaRepositoryFactoryBean<T,S,ID> {
    @Override
    protected RepositoryFactorySupport createRepositoryFactory(EntityManager entityManager) {
        return new MyRepositoryFactory<T,ID>(entityManager); //注:這里創(chuàng)建是我們的自定義類
    }
    //繼承JpaRepositoryFactory后,把返回的對(duì)象修改成我們自己的實(shí)現(xiàn)
    private static  class MyRepositoryFactory<T,ID extends Serializable>   extends JpaRepositoryFactory {
        private final EntityManager entityManager;
        /**
         * Creates a new {@link JpaRepositoryFactory}.
         *
         * @param entityManager must not be {@literal null}
         */
        public MyRepositoryFactory(EntityManager entityManager) {
            super(entityManager);
            this.entityManager = entityManager;
        }
        //這里返回最后的功能對(duì)象
        @Override
        protected Object getTargetRepository(RepositoryInformation information) {
            return new BaseRepositoryImpl<T,ID>((Class<T>)information.getDomainType(),entityManager);
        }
        //確定功能對(duì)象的類型
        @Override
        protected Class<?> getRepositoryBaseClass(RepositoryMetadata metadata) {
            return BaseRepositoryImpl.class;
        }
    }
}

spring配置文件中關(guān)于SpringDataJPA的配置

 <jpa:repositories base-package="com.xer.aisell.dao" entity-manager-factory-ref="entityManagerFactory"
                      transaction-manager-ref="transactionManager"
                        factory-class="com.xer.aisell.dao.BaseRepositoryFactoryBean"/>

以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。

相關(guān)文章

  • Spring BeanDefinition使用介紹

    Spring BeanDefinition使用介紹

    BeanDefinition是Spring框架中非常核心的概念,BeanDefinition是定義Bean的配置元信息接口,Spring根據(jù)BeanDefinition來(lái)定義Bean對(duì)象,簡(jiǎn)單說(shuō)就是對(duì)Bean信息的定義
    2023-01-01
  • SpringBoot 配合 SpringSecurity 實(shí)現(xiàn)自動(dòng)登錄功能的代碼

    SpringBoot 配合 SpringSecurity 實(shí)現(xiàn)自動(dòng)登錄功能的代碼

    這篇文章主要介紹了SpringBoot 配合 SpringSecurity 實(shí)現(xiàn)自動(dòng)登錄功能的代碼,代碼簡(jiǎn)單易懂,對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2020-09-09
  • SpringBoot+WebSocket向前端推送消息的實(shí)現(xiàn)示例

    SpringBoot+WebSocket向前端推送消息的實(shí)現(xiàn)示例

    WebSocket是一種在單個(gè)TCP連接上進(jìn)行全雙工通信的協(xié)議,允許服務(wù)器主動(dòng)向客戶端推送信息,同時(shí)也能從客戶端接收信息,本文主要介紹了SpringBoot+WebSocket向前端推送消息的實(shí)現(xiàn)示例,感興趣的可以了解一下
    2024-08-08
  • Maven構(gòu)建生命周期詳細(xì)介紹

    Maven構(gòu)建生命周期詳細(xì)介紹

    這篇文章主要介紹了Maven構(gòu)建生命周期詳細(xì)介紹,小編覺得還是挺不錯(cuò)的,這里分享給大家,需要的朋友可以參考下。
    2017-11-11
  • 詳解Java Selenium中的鍵盤控制操作

    詳解Java Selenium中的鍵盤控制操作

    這篇文章主要為大家介紹了如何使用java代碼利用Selenium 控制瀏覽器中需要用到的鍵盤操作。文中的示例代碼講解詳細(xì),感興趣的小伙伴可以了解一下
    2023-01-01
  • 詳細(xì)介紹Java中的各種鎖

    詳細(xì)介紹Java中的各種鎖

    不少同學(xué)開始慢慢接觸多線時(shí)候,對(duì)線程之間為了保障數(shù)據(jù)安全性,一致性有所了解,本文詳細(xì)解介紹java中的21種鎖 ,需要的朋友可以參考下
    2021-06-06
  • IDEA自動(dòng)清理類中未使用的import包的操作方法

    IDEA自動(dòng)清理類中未使用的import包的操作方法

    在項(xiàng)目開發(fā)中,經(jīng)常會(huì)引入很多未使用的import包,這不僅增加了編譯時(shí)間,還會(huì)使代碼可讀性變差,設(shè)置IDEA自動(dòng)清理未使用的import包,可以提高代碼的可讀性,本文給大家介紹IDEA自動(dòng)清理類中未使用的import包的方法,感興趣的朋友一起看看吧
    2024-09-09
  • spring緩存cache的使用詳解

    spring緩存cache的使用詳解

    這篇文章主要介紹了spring緩存cache的使用詳解,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-10-10
  • JDBC 程序的常見錯(cuò)誤及調(diào)試方法

    JDBC 程序的常見錯(cuò)誤及調(diào)試方法

    本文是《Java Web開發(fā)教程——入門與提高篇(JSP+Servlet)》一書《第9章 JDBC技術(shù)》的補(bǔ)充內(nèi)容。
    2009-06-06
  • Java線程中的Thread.yield()詳細(xì)解析

    Java線程中的Thread.yield()詳細(xì)解析

    這篇文章主要介紹了Java線程中的Thread.yield()詳細(xì)解析,yield()讓當(dāng)前線程從運(yùn)行狀態(tài)?轉(zhuǎn)為?就緒狀態(tài),以允許具有相同優(yōu)先級(jí)的其他線程獲得運(yùn)行機(jī)會(huì),需要的朋友可以參考下
    2023-11-11

最新評(píng)論

哈巴河县| 始兴县| 基隆市| 册亨县| 锡林郭勒盟| 芒康县| 泽州县| 石景山区| 克山县| 泰兴市| 滦平县| 庆元县| 漳平市| 望奎县| 和龙市| 阜阳市| 兴海县| 南郑县| 武平县| 旬阳县| 郯城县| 浦城县| 商洛市| 泉州市| 宁陕县| 灌云县| 化州市| 嫩江县| 乃东县| 密山市| 基隆市| 伊春市| 莒南县| 贡觉县| 五家渠市| 常州市| 星子县| 金秀| 敦化市| 汉川市| 武隆县|