spring boot之使用spring data jpa的自定义sql方式

 更新时间:2021年12月08日 15:29:24   作者:冰霜秋月  
这篇文章主要介绍了spring boot之使用spring data jpa的自定义sql方式,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教

spring data jpa介绍

PA(Java Persistence API)是Sun官方提出的Java持久化规范。它为Java开发人员提供了一种对象/关联映射工具来管理Java应用中的关系数据。他的出现主要是为了简化现有的持久化开发工作和整合ORM技术,结束现在Hibernate,TopLink,JDO等ORM框架各自为营的局面。值得注意的是,JPA是在充分吸收了现有Hibernate,TopLink,JDO等ORM框架的基础上发展而来的,具有易于使用,伸缩性强等优点。

自定义SQL查询

Spring data 觉大部分的SQL都可以根据方法名定义的方式来实现,但是由于某些原因我们想使用自定义的SQL来查询,spring data也是完美支持的;在SQL的查询方法上面使用@Query注解,如涉及到删除和修改在需要加上@Modifying.

    public interface CustomerRepository extends JpaRepository<Customer, Integer>{
    @Modifying
    @Query("update Customer c set c.customerName=?1 where c.id=?2")
    Integer modifyByIdAndUserId(String customerName,Integer id);
    @Modifying
    @Query("delete from Customer where id = ?1")
    void deleteByCustomerId(Integer id);
}

注意当调用自定义更新和删除sql操作时,会出现下面的异常

org.springframework.dao.InvalidDataAccessApiUsageException: Executing an update/delete query; nested exception is javax.persistence.TransactionRequiredException: Executing an update/delete query at org.springframework.orm.jpa.EntityManagerFactoryUtils.convertJpaAccessExceptionIfPossible(EntityManagerFactoryUtils.java:396) at org.springframework.orm.jpa.vendor.HibernateJpaDialect.translateExceptionIfPossible(HibernateJpaDialect.java:227) at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.translateExceptionIfPossible(AbstractEntityManagerFactoryBean.java:527) at org.springframework.dao.support.ChainedPersistenceExceptionTranslator.translateExceptionIfPossible(ChainedPersistenceExceptionTranslator.java:61) at org.springframework.dao.support.DataAccessUtils.translateIfNecessary(DataAccessUtils.java:242) at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:153) at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:185) at org.springframework.data.jpa.repository.support.CrudMethodMetadataPostProcessor$CrudMethodMetadataPopulatingMethodInterceptor.invoke(CrudMethodMetadataPostProcessor.java:135) at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:185) at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:92) at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:185) at org.springframework.data.repository.core.support.SurroundingTransactionDetectorMethodInterceptor.invoke(SurroundingTransactionDetectorMethodInterceptor.java:61) at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:185) at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:212) at com.sun.proxy.$Proxy88.modifyByIdAndUserId(Unknown Source) at com.baidu.HelloPeopleApplicationTests.contextLoads(HelloPeopleApplicationTests.java:42) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:498) at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50) at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12) at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47) at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17) at org.springframework.test.context.junit4.statements.RunBeforeTestExecutionCallbacks.evaluate(RunBeforeTestExecutionCallbacks.java:73) at org.springframework.test.context.junit4.statements.RunAfterTestExecutionCallbacks.evaluate(RunAfterTestExecutionCallbacks.java:83) at org.springframework.test.context.junit4.statements.RunBeforeTestMethodCallbacks.evaluate(RunBeforeTestMethodCallbacks.java:75) at org.springframework.test.context.junit4.statements.RunAfterTestMethodCallbacks.evaluate(RunAfterTestMethodCallbacks.java:86) at org.springframework.test.context.junit4.statements.SpringRepeat.evaluate(SpringRepeat.java:84) at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325) at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:251) at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:97) at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290) at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71) at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288) at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58) at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268) at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61) at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:70) at org.junit.runners.ParentRunner.run(ParentRunner.java:363) at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:190) at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:86) at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38) at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:538) at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:760) at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:460) at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:206) Caused by: javax.persistence.TransactionRequiredException: Executing an update/delete query at org.hibernate.query.internal.AbstractProducedQuery.executeUpdate(AbstractProducedQuery.java:1496) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:498) at org.springframework.orm.jpa.SharedEntityManagerCreator$DeferredQueryInvocationHandler.invoke(SharedEntityManagerCreator.java:380) at com.sun.proxy.$Proxy95.executeUpdate(Unknown Source) at org.springframework.data.jpa.repository.query.JpaQueryExecution$ModifyingExecution.doExecute(JpaQueryExecution.java:256) at org.springframework.data.jpa.repository.query.JpaQueryExecution.execute(JpaQueryExecution.java:91) at org.springframework.data.jpa.repository.query.AbstractJpaQuery.doExecute(AbstractJpaQuery.java:136) at org.springframework.data.jpa.repository.query.AbstractJpaQuery.execute(AbstractJpaQuery.java:125) at org.springframework.data.repository.core.support.RepositoryFactorySupport$QueryExecutorMethodInterceptor.doInvoke(RepositoryFactorySupport.java:590) at org.springframework.data.repository.core.support.RepositoryFactorySupport$QueryExecutorMethodInterceptor.invoke(RepositoryFactorySupport.java:578) at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:185) at org.springframework.data.projection.DefaultMethodInvokingMethodInterceptor.invoke(DefaultMethodInvokingMethodInterceptor.java:59) at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:185) at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:294) at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:98) at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:185) at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:139) ... 41 more

对于该异常的原因是更新和删除操作没有进行事务处理,解决办法是在service层调用CustomerRepository接口的方法的方法上添加注解@Transactional进行事务的处理,然后在调用service层的方法

@Service
public class CustomerService {
    @Autowired
    private CustomerRepository customerRepository;
    @Transactional
    public void deleteByCustomerId(Integer id) {
        customerRepository.deleteByCustomerId(id);
    }
    @Transactional
    public Integer modifyByIdAndUserId(String customerName,Integer id) {
        return customerRepository.modifyByIdAndUserId(customerName, id);
    }
Integer line = customerService.modifyByIdAndUserId("张三", 4);
        System.out.println(line);
        customerService.deleteByCustomerId(3);

执行后如图所示:

这里写图片描述

jpa两种自定义SQL的方式

当你的抽象类继承了JpaRepository类时,就会拥有一些基本的增删改查操作。但是,很多时候只有这些简单的功能是不够的的,jpa也支持原生SQL和实体类SQL进行自定义查询。

1. 原生SQL

@Query(value = "SELECT t2.userId, t1.title, t1.content, t1.completeTime, t2.scheduleState" +
            " FROM schedule t1 LEFT JOIN schedule_user t2 ON t1.id = t2.schedule_id " +
            " WHERE t2.user_id = ?1 AND t2.schedule_state = ?2", nativeQuery=true)
    List<ScheduleUserView> findScheduleListByState(Long userId, int scheduleState);

2. 实体类SQL

@Query(value = "SELECT new com.x3.schedule.saas.table.ScheduleUserView(" +
            " t2.userId, t1.title, t1.content, t1.completeTime, t2.scheduleState)" +
            " FROM ScheduleTable t1 LEFT JOIN ScheduleUserTable t2 ON t1.scheduleId = t2.scheduleId " +
            " WHERE t2.userId = ?1 AND t2.scheduleState = ?2")
    List<ScheduleUserView> findScheduleListByState(Long userId, int scheduleState);

以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。

相关文章

  • 在SpringBoot中如何利用Redis实现互斥锁

    在SpringBoot中如何利用Redis实现互斥锁

    当我们利用Redis存储热点数据时,突然就过期失效或者被删除了,导致大量请求同时访问数据库,增加了数据库的负载,为减轻数据库的负载我们利用互斥锁,本文重点介绍在SpringBoot中如何利用Redis实现互斥锁,感兴趣的朋友一起看看吧
    2023-09-09
  • 搭建MyBatis开发环境及基本的CURD介绍

    搭建MyBatis开发环境及基本的CURD介绍

    这篇文章主要介绍了搭建MyBatis开发环境及基本的CURD,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2020-08-08
  • 8种常见的Java不规范代码

    8种常见的Java不规范代码

    本文主要介绍了8种常见的Java不规范代码。具有很好的参考价值,下面跟着小编一起来看下吧
    2017-01-01
  • Java报错:java.lang.UnsatisfiedLinkError问题的解决办法

    Java报错:java.lang.UnsatisfiedLinkError问题的解决办法

    在Java开发中,java.lang.UnsatisfiedLinkError是一种与本地方法调用相关的常见异常,本文将详细分析这一异常的背景、可能的原因、错误代码示例、正确代码示例,以及编写代码时需要注意的事项,需要的朋友可以参考下
    2024-09-09
  • IDEA插件推荐之Maven-Helper的教程图解

    IDEA插件推荐之Maven-Helper的教程图解

    这篇文章主要介绍了IDEA插件推荐之Maven-Helper的相关知识,本文通过图文并茂的形式给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考
    2020-07-07
  • springboot ehcache 配置使用方法代码详解

    springboot ehcache 配置使用方法代码详解

    EhCache是一个比较成熟的Java缓存框架,Springboot对ehcache的使用非常支持,所以在Springboot中只需做些配置就可使用,且使用方式也简易,今天给大家分享springboot ehcache 配置使用教程,一起看看吧
    2021-06-06
  • ExecutorService实现获取线程返回值

    ExecutorService实现获取线程返回值

    这篇文章主要介绍了ExecutorService实现获取线程返回值,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2022-08-08
  • java响应式编程之Reactor使用示例解析

    java响应式编程之Reactor使用示例解析

    这篇文章主要为大家介绍了java响应式编程之Reactor使用示例解析,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-07-07
  • 如何在Spring Boot中使用MQTT

    如何在Spring Boot中使用MQTT

    这篇文章主要介绍了如何在Spring Boot中使用MQTT,帮助大家更好的理解和学习使用Spring Boot,感兴趣的朋友可以了解下
    2021-04-04
  • 解读SpringMVC 请求参数接收

    解读SpringMVC 请求参数接收

    这篇文章主要介绍了SpringMVC请求参数接收的相关操作,本文通过示例代码给大家介绍的非常详细,感兴趣的朋友跟随小编一起看看吧
    2024-07-07

最新评论