PostgreSQL数据库表字段删除造成的报错

问题现象

  • 我们信控平台使用Java语言开发,Spring Cloud微服务架构,采用容器化部署,所有服务都部署在docker里面,使用docker-compose进行管理,使用portainer进行监控
  • 对于业务数据,我们使用PostgreSQL存储,在JDL文件里维护表结构,使用jhipster工具生成代码
  • 生成的代码,还比较标准,数据持久层,就是JPA,生成的接口也都是标准RESTful,增删改查都有
  • 在公司测试环境,进行平台程序的某次更新后,发现平台首页打不开了
  • 按下F12键,刷新页面,发现有一个GET请求报错,这个错误没有被前端页面代码捕获处理,抛出异常,整个页面就打不开了,平台进不去了
  • 查看服务日志docker logs -f core,确实有报错输出
  • 日志如下:
2023-07-14 17:05:08.696 ERROR 1 --- [  XNIO-1 task-2] o.z.problem.spring.common.AdviceTraits   : Internal Server Error
org.springframework.data.mapping.PropertyReferenceException: No property 'executeDate' found for type 'VipRoute'
	at org.springframework.data.mapping.PropertyPath.<init>(PropertyPath.java:91)
	at org.springframework.data.mapping.PropertyPath.create(PropertyPath.java:438)
	at org.springframework.data.mapping.PropertyPath.create(PropertyPath.java:414)
	at org.springframework.data.mapping.PropertyPath.lambda$from$0(PropertyPath.java:367)
	at java.base/java.util.concurrent.ConcurrentMap.computeIfAbsent(Unknown Source)
	at org.springframework.data.mapping.PropertyPath.from(PropertyPath.java:349)
	at org.springframework.data.mapping.PropertyPath.from(PropertyPath.java:332)
	at org.springframework.data.jpa.repository.query.QueryUtils.toJpaOrder(QueryUtils.java:718)
	at org.springframework.data.jpa.repository.query.QueryUtils.toOrders(QueryUtils.java:671)
	at org.springframework.data.jpa.repository.support.SimpleJpaRepository.getQuery(SimpleJpaRepository.java:817)
	at org.springframework.data.jpa.repository.support.SimpleJpaRepository.getQuery(SimpleJpaRepository.java:774)
	at org.springframework.data.jpa.repository.support.SimpleJpaRepository.findAll(SimpleJpaRepository.java:515)
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
	at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
	at java.base/java.lang.reflect.Method.invoke(Unknown Source)
	at org.springframework.data.repository.core.support.RepositoryMethodInvoker$RepositoryFragmentMethodInvoker.lambda$new$0(RepositoryMethodInvoker.java:289)
	at org.springframework.data.repository.core.support.RepositoryMethodInvoker.doInvoke(RepositoryMethodInvoker.java:137)
	at org.springframework.data.repository.core.support.RepositoryMethodInvoker.invoke(RepositoryMethodInvoker.java:121)
	at org.springframework.data.repository.core.support.RepositoryComposition$RepositoryFragments.invoke(RepositoryComposition.java:530)
	at org.springframework.data.repository.core.support.RepositoryComposition.invoke(RepositoryComposition.java:286)
	at org.springframework.data.repository.core.support.RepositoryFactorySupport$ImplementationMethodExecutionInterceptor.invoke(RepositoryFactorySupport.java:640)
	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
	at org.springframework.data.repository.core.support.QueryExecutorMethodInterceptor.doInvoke(QueryExecutorMethodInterceptor.java:164)
	at org.springframework.data.repository.core.support.QueryExecutorMethodInterceptor.invoke(QueryExecutorMethodInterceptor.java:139)
	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
	at org.springframework.data.projection.DefaultMethodInvokingMethodInterceptor.invoke(DefaultMethodInvokingMethodInterceptor.java:81)
	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
	at org.springframework.transaction.interceptor.TransactionInterceptor$1.proceedWithInvocation(TransactionInterceptor.java:123)
	at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:388)
	at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:119)
	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
	at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:137)
	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
	at org.springframework.data.jpa.repository.support.CrudMethodMetadataPostProcessor$CrudMethodMetadataPopulatingMethodInterceptor.invoke(CrudMethodMetadataPostProcessor.java:174)
	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
	at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:97)
	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
	at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:215)
	at com.sun.proxy.$Proxy331.findAll(Unknown Source)
	at com.newatc.api.viproute.service.GuardTaskService.getVipRouteList(GuardTaskService.java:172)
	at com.newatc.api.viproute.service.GuardTaskService$$FastClassBySpringCGLIB$$5d93c921.invoke(<generated>)
	at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:218)
	at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:793)
	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163)
	at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:763)
	at org.springframework.transaction.interceptor.TransactionInterceptor$1.proceedWithInvocation(TransactionInterceptor.java:123)
	at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:388)
	at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:119)
	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
	at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:763)
	at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:708)
	at com.newatc.api.viproute.service.GuardTaskService$$EnhancerBySpringCGLIB$$faa0b28e.getVipRouteList(<generated>)
	at com.newatc.api.rest.GuardTaskController.getVipRouteList(GuardTaskController.java:63)
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
	at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
	at java.base/java.lang.reflect.Method.invoke(Unknown Source)
	at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:205)
	at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:150)
	at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:117)
	at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:895)
	at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:808)
	at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87)
	at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1070)
	at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:963)
	at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1006)
	at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:898)
	at javax.servlet.http.HttpServlet.service(HttpServlet.java:497)
	at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:883)
	at javax.servlet.http.HttpServlet.service(HttpServlet.java:584)
	at io.undertow.servlet.handlers.ServletHandler.handleRequest(ServletHandler.java:74)
	......

排查解决

  • 报错日志里,核心是这一句org.springframework.data.mapping.PropertyReferenceException: No property 'executeDate' found for type 'VipRoute',这个报错并不是啥疑难杂症报错,而是个JPA的经典报错
  • 这个错误通常意味着你的代码中存在对一个名为“executeDate”的属性的引用,但是该属性在你的“VipRoute”类中并不存在
  • 检查了下代码提交记录,发现“VipRoute”类里,这个“executeDate”属性被删掉了,于是怀疑是实体类去除了字段,其他业务代码仍然保留导致的
  • 于是又检查了该实体类的其他相关代码,接口、服务层、持久层代码,都没发现“executeDate”属性的使用,直接使用全局搜索功能,搜索“executeDate”与“execute_date”,也都没有搜到,确实删干净了
  • 考虑到我们使用jhipster生成代码,基本上不存在字段删除了,有残余代码需要手动修改的
  • 接着怀疑是打包问题,因为我们是使用docker部署的,需要先将代码打车tar包,是使用maven的jib插件
  • 具体打包流程可参考这篇博客:Spring Boot:使用maven的jib插件打docker使用所需的镜像包
  • 怀疑打包时,把之前已生成的class文件拿来用了,数据库已经没有这个字段了,所以才报错,于是删掉并重复打包好几次,还是不行
  • 排除服务端所有可能报错的点之后,我又把目光回到了报错页面,最终发现了问题
  • 前端文件里的查询方法,带着排序字段“executeDate”,该字段作为排序字段传输到服务端,经过JPA代码,最终拼接到SQL语句里,导致了这个报错
  • 在更新完服务端代码后,未及时更新前端代码,导致了这个传参问题
  • 将最新的前端静态文件更新上去后,平台恢复正常

总结

  • 最后总结下,前端页面的查询条件,带着“executeDate”字段,而这个字段在服务端被删除,导致了这次报错
  • 对于实体类与数据库表,当一个字段在表里有,实体类没有时,并不会造成什么错误,只不过是冗余了一个字段
  • 如果一个字段实体类有,而数据库表里没有,那就不行了,使用到这个表的代码,增删改查都可能会报错
  • 对于实体类变动和数据库表变动,我们要做好记录,做好对应的代码修改
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

坚持是一种态度

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值