Spring DATA JPA与Hibernate一起作为JPA提供者

时间:2017-08-27 11:44:35

标签: java spring hibernate jpa spring-data-jpa

将Spring引导应用程序与spring数据jpa一起使用hibernate作为jpa提供程序。

在一个扩展JpaRepository的接口中创建了一个默认方法。

请检查代码。

public interface UserDao extends JpaRepository<User, UUID> {

default void softDelete(UUID id) {
    User existingUser = findOne(id);

    if (existingUser != null)
        existingUser.setActive(false);

    throw new EntityNotFoundException();
    }
}

现在,当我从服务层调用此 softDelete()时,它不会返回现有用户。它返回NULL。

这是日志堆栈跟踪。

    2017-08-27 13:25:01 [http-nio-8080-exec-2] ERROR o.a.c.c.C.[.[.[.[dispatcherServlet] - Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is org.springframework.orm.jpa.JpaObjectRetrievalFailureException: nested exception is javax.persistence.EntityNotFoundException] with root cause
javax.persistence.EntityNotFoundException: null
    at org.rout.projmgmt.dao.UserDao.softDelete(UserDao.java:31)
    at java.lang.invoke.MethodHandle.invokeWithArguments(MethodHandle.java:627)
    at org.springframework.data.projection.DefaultMethodInvokingMethodInterceptor.invoke(DefaultMethodInvokingMethodInterceptor.java:62)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
    at org.springframework.transaction.interceptor.TransactionInterceptor$1.proceedWithInvocation(TransactionInterceptor.java:99)
    at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:282)
    at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:96)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
    at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:136)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
    at org.springframework.data.jpa.repository.support.CrudMethodMetadataPostProcessor$CrudMethodMetadataPopulatingMethodInterceptor.invoke(CrudMethodMetadataPostProcessor.java:133)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
    at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:92)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
    at org.springframework.data.repository.core.support.SurroundingTransactionDetectorMethodInterceptor.invoke(SurroundingTransactionDetectorMethodInterceptor.java:57)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
    at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:213)
    at com.sun.proxy.$Proxy107.softDelete(Unknown Source)
    at org.rout.projmgmt.service.user.UserServiceImpl.delete(UserServiceImpl.java:53)
    at org.rout.projmgmt.controller.UserController.delete(UserController.java:53)
    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.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:205)
    at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:133)
    at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:97)
    at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:827)
    at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:738)
    at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:85)
    at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:967)
    at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:901)
    at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:970)
    at org.springframework.web.servlet.FrameworkServlet.doDelete(FrameworkServlet.java:894)

知道我错过了什么???

3 个答案:

答案 0 :(得分:3)

一些事情:

  1. 无论您是否获得记录,您都会得到EntityNotFoundException例外,因为我假设您想要在找不到任何记录时发送该例外。
  2. 您可能也希望返回用户,但返回类型无效。我会将返回类型修改为User,如下所示:

    default User softDelete(UUID id) {
        User existingUser = findOne(id);
        if (existingUser != null) {
            existingUser.setActive(false);
        } else {
            throw new EntityNotFoundException();
        }
        return existingUser;//you may want to save this user again with isActive flag now false
    }
    

答案 1 :(得分:0)

除了SMA提供的答案外,还有几件事。

  1. 我现在不记得了,但是AFAIR建议也将 Spring Data Repository 的自定义类命名为存储库,而不是 Dao

  2. 您确定在数据库中拥有此用户吗?你如何初始化数据库 - 飞路? Spring Boot自动 schema.sql data.sql 文件?

  3. 使用您提供的代码即使实体位于数据库中,也会抛出异常。

答案 2 :(得分:0)

SMA让你的问题得到了解决!我只需要补充一点,您应该尝试使用JpaRepository而不在其中放置任何逻辑,只需将其用于CRUD操作并在服务层中执行逻辑。像这样:

public interface UserDao extends JpaRepository<User, UUID> {

@Modifying
@Query("update User u set u.active = false where u.id = :id")
default User softDelete(@Param("id) UUID id) throws EntityNotFoundException;
}

然后您可以在服务中执行错误处理。 reference docs显示了编写自定义查询以更好地满足您需求的一些很好的示例