广告
返回顶部
首页 > 资讯 > 后端开发 > Python >JpaRepository如何实现增删改查并进行单元测试
  • 917
分享到

JpaRepository如何实现增删改查并进行单元测试

2024-04-02 19:04:59 917人浏览 独家记忆

Python 官方文档:入门教程 => 点击学习

摘要

目录JpaRepository增删改查进行单元测试项目结构单元测试springDataJPA的Repository理解repository抽取扩展理解接下来贴一贴代码JpaRepos

JpaRepository增删改查进行单元测试

项目结构

在这里插入图片描述

创建UserInfoDaoI.java文件,继承JpaRepository。(不需要实现类)

在这里插入图片描述

根据条件查询/删除

在这里插入图片描述

更新

在这里插入图片描述

参考此文章进行开发

单元测试

在这里插入图片描述

SpringDataJPA的Repository理解

repository抽取扩展理解

在SpringDataJPA中使用repository来进行数据层操作(作用相当于dao层),直接使用repository对象调用已经实现好的数据层操作方法进行CRUD、分页、排序等操作,还可以在自定义repository接口中依据一定规则扩展功能。在一个项目中,我们平常需要为每一个实体类都创建一个repository接口,我们自定义的repository接口都需要去继承JpaRepository接口,以具有所有的数据层操作功能,但也仅仅限于简单查询等操作。通常我们为了能实现复杂查询操作,会继续继承JpaSpecificationExecutor接口,简单说就是建立一个规则来进行查询。

这样虽然在很大程度上简化了开发代码难度,但在为每一实体类创建对应repository接口时,发现存在大量的重复代码,这时很容易的我们会想到抽取父类来简化一些公共代码并顺带可以对子类进行一些规范。虽然SpringDataJPA提供的功能已经足够强大了,但是依然还是不能满足实际开发中的所有需求,所以我们想在抽取父类的同时实现对其功能的扩展。在进行这个操作之前我们需要了解一下整个repository的结构。

应该免不了有疑问,我们仅仅是定义了一个接口去实现了JpaRepository接口,怎么就能创建对象了,而且还能给我们实现一系列的数据层操作?这就要从为什么自定义repository接口要去继承JpaRepository接口说起了:

在这里插入图片描述

通过它的结构图可以看出,JpaRepository的父类分别是PagingAndSortingRepository、CrudRepository和Repository,前两个接口中前者定义了分页和排序功能,后者看名字就可以知道里面全是CRUD操作,值得注意的是,它这保存和修改方法都是save。Repository接口呢没有定义任何功能,它的作用就是标识。这么说吧我们自定义的接口继承JpaRepository接口就相当于继承了Repository接口,那么SpringDataJPA在扫描时只要扫描到我们某个接口实现了Repository接口,就为自动的为其创建代理实现子类(通过aop实现)。但是为什么就只为我们自定义的repository接口创建了实现子类而没有为PagingAndSortingRepository、CrudRepository、JpaRepository创建呢?这个同样能从结构图中看出答案:它们都是打上了NoRepositoryBean注解的,凡是打上了这个注解的接口SPringDataJPA都不会为其创建实现子类。

这样一来,我们自定义的接口继承了以上三个接口后就相当于“集百家之长”了,拥有了它们所有功能,但是问题又来了,它们再牛终归还是接口啊,又不能创建对象,是怎么操作的呢?

在这里插入图片描述

原来,SpringDataJPA自动的为自动创建的repository实现子类继承了SimpleJpaRepository类,而SimpleJpaRepository又是SpringDataJPA的Repository默认实现两大方式之一,自然而然的自动创建的repository代理子类也就具有了所有的功能。至此,SpringDataJPA中repository实现数据层操作的原理也大概讲清楚了,接下来就说说扩展了:虽然SPringDataJPA提供的功能已经足够强大了,但是依然还是不能满足实际开发中的所有需求。所以说了这么久终于要说到重点了:抽取父类、扩展功能。

在这里插入图片描述

通过上图,大概也能看出结构了,大概思想:在原本应该继承JpaRepository的实体类repository接口与JpaRepository之间增加了一层而已,让BaseRepository继承JpaSpecificationExecutor、JpaRepository,实体类repository接口继承BaseRepository接口;这样便能实现在拥有原有SpringDataJPA的Repository功能的情况下在BaseRepository扩展其他功能,但在这需要注意:在SpringDataJPA中默认会使自动创建的repository代理实现子类(例:图中的EmployeeRepositoryImpl)去继承SimpleJpaRepository,很明显我们并不能使用默认的,因为这样会使得我们的BaseRepository接口定义的一无是处,所以我们需要再创建一个自定义的BaseRepository实现BaseRepositoryImpl继承SimpleJpaRepository,再修改配置使得SpringDataJPA自动创建出的所有实体类repository的实现代理子类都去继承我们的BaseRepositoryImpl,这样我们便能彻底实现扩展了。

前面说过SpringDataJPA会默认的将自动创建出的实现代理子类继承SimpleJpaRepository类,所以我们需要修改SimpleJpaRepository为我们自定义的BaseRepositoryImpl类,SpringDataJPA是通过JpaRepositoryFactoryBean来实现创建并继承过程的。我们只用自定义一个BaseRepositoryFactoryBean来继承JpaRepositoryFactoryBean,接下来只用修改最终返回功能对象,和确定功能对象的类型即可。最后记得要在spring的配置文件中在SpringDataJPA的配置中添加修改创建对象的factoryBean为我们自定义的BaseRepositoryFactoryBean。

最后,记得修改各实体repository接口继承我们定义的BaseRepository接口

接下来贴一贴代码

接下来贴一贴代码

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;

@NoRepositoryBean
public interface BaseRepository<T,ID extends Serializable> extends JpaRepository<T,ID>,JpaSpecificationExecutor<T>{
    //根据Query拿到分页对象(分页)
    Page findPageByQuery(BaseQuery baseQuery);
    //根据Query拿到对应的所有数据(不分页)
    List<T> findByQuery(BaseQuery baseQuery);
    //根据jpql与对应的参数拿到数据
    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
    
    public Page findPageByQuery(BaseQuery baseQuery) {
        //拿到条件
        Specification spec = baseQuery.createSpec();
        //创建排序
        Sort sort = baseQuery.getSort();
        //分页
        Pageable page = new PageRequest(baseQuery.getJPACurrentPage(), baseQuery.getPageSize(), sort);
        return super.findAll(spec,page);
    }
    
    @Override
    public List findByQuery(BaseQuery baseQuery) {
        //获取到条件
        Specification spec = baseQuery.createSpec();
        //排序
        Sort sort = baseQuery.getSort();
        return super.findAll(spec,sort);
    }
    
    @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;

public interface EmployeeRepository extends BaseRepository<Employee,Long> {
    
    List<Employee> findByUsernameLike(String username);
    
    @Query("select o from Employee o where username like ?1")
    List<Employee> findByUsername(String username);
    
    @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); //注:这里创建是我们的自定义类
    }
    //继承JpaRepositoryFactory后,把返回的对象修改成我们自己的实现
    private static  class MyRepositoryFactory<T,ID extends Serializable>   extends JpaRepositoryFactory {
        private final EntityManager entityManager;
        
        public MyRepositoryFactory(EntityManager entityManager) {
            super(entityManager);
            this.entityManager = entityManager;
        }
        //这里返回最后的功能对象
        @Override
        protected Object getTargetRepository(RepositoryInformation information) {
            return new BaseRepositoryImpl<T,ID>((Class<T>)information.getDomainType(),entityManager);
        }
        //确定功能对象的类型
        @Override
        protected Class<?> getRepositoryBaseClass(RepositoryMetadata metadata) {
            return BaseRepositoryImpl.class;
        }
    }
}

spring配置文件中关于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"/>

以上为个人经验,希望能给大家一个参考,也希望大家多多支持编程网。

--结束END--

本文标题: JpaRepository如何实现增删改查并进行单元测试

本文链接: https://www.lsjlt.com/news/158337.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • JpaRepository如何实现增删改查并进行单元测试
    目录JpaRepository增删改查进行单元测试项目结构单元测试SpringDataJPA的Repository理解repository抽取扩展理解接下来贴一贴代码JpaRepos...
    99+
    2022-11-12
  • Java如何实现单链表的增删改查
    一、新建学生节点类 Stu_Node节点包含: 学号:int num; 姓名:String name; 性别:String gender; 下一个节点:Stu_Node next;...
    99+
    2022-11-12
  • Nodejs如何连接mysql并实现增、删、改、查操作
    这篇文章主要介绍了Nodejs如何连接mysql并实现增、删、改、查操作,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。一、准备nodejs的...
    99+
    2022-10-19
  • 使用Hibernate如何实现对数据库进行增删改查操作
    使用Hibernate如何实现对数据库进行增删改查操作?针对这个问题,这篇文章详细介绍了相对应的分析和解答,希望可以帮助更多想解决这个问题的小伙伴找到更简单易行的方法。Hibernate对数据删除操作删除User表中个一条数据,是需要更具U...
    99+
    2023-05-31
    hibernate 数据库 增删改查
  • 使用Mybatis如何实现对数据库进行增删改查操作
    本篇文章为大家展示了使用Mybatis如何实现对数据库进行增删改查操作,内容简明扼要并且容易理解,绝对能使你眼前一亮,通过这篇文章的详细介绍希望你能有所收获。什么是 MyBatis?MyBatis 是支持普通 SQL 查询,存储过程和高级映...
    99+
    2023-05-31
    mybatis 增删改查 数据库
  • 如何搭建MyBatis-Plus框架并进行数据库增删改查功能
    本篇内容主要讲解“如何搭建MyBatis-Plus框架并进行数据库增删改查功能”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“如何搭建MyBatis-Plus框架并进行数据库增删改查功能”吧!搭建...
    99+
    2023-06-09
  • 如何实现Vue中数据的增删改查并结合对话框
    近年来,随着前端技术的不断发展,Vue已经成为了越来越多开发者选择的前端框架。其中,前端数据的增删改查是Web应用程序中最基础的功能之一。在Vue中,如何实现增删改查的同时跳出一个对话框呢?接下来,本文将为您介绍如何实现Vue中数据的增删改...
    99+
    2023-05-14
  • C语言中如何实现单向链表的增删查改操作
    这篇文章主要介绍了C语言中如何实现单向链表的增删查改操作,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。前言链表是线性表的链式存储结构,它可以以O(1)的时间复杂度进行插入或者...
    99+
    2023-06-25
  • 如何进行单元测试利器JUnit的实践与分析
    今天就跟大家聊聊有关如何进行单元测试利器JUnit的实践与分析,可能很多人都不太了解,为了让大家更加了解,小编给大家总结了以下内容,希望大家根据这篇文章可以有所收获。单元测试工具Junit是一个开源项目,昨天学习了一下这个东西,总结下心得。...
    99+
    2023-06-17
  • bootstrap如何实现table单元格新增行并编辑功能
    这篇文章主要介绍bootstrap如何实现table单元格新增行并编辑功能,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!table单元格新增行并编辑,具体内容如下需要bootstra...
    99+
    2022-10-19
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作