SkyLark1670 2021-12-13 15:38 采纳率: 100%
浏览 116
已结题

多线程下使用Spring JPA的属性转换AttributeConverter导致的异常情况

问题遇到的现象和发生背景

使用JPA进行数据库的查询和更新操作,其中实体类中的updateTime字段使用了自动更新策略,并手写实现接口AttributeConverter进行转换。java字段为Date,数据库中使用Number(14)。单线程执行任何查询和更新都没有问题,但是通过多线程,查询或更新不同的记录时,会有概率出现转换异常。目前尚未发现问题原因。

问题相关代码,请勿粘贴截图

//实体类 
@Data
@Entity
@Table(name = "my_order")
@EntityListeners(AuditingEntityListener.class)
public class Order
{
    @Column(name = "fundCode")
    private String fundCode;

    @Column(name = "APPLICATIONAMOUNT")
    private double updateBal;

    @Id
    @Column(name = "orderId")
    private String orderId;

    @Column(name = "CREATEDTIME")
    @CreatedDate
    @Convert(converter = AppDateConvertDBLong.class)
    private Date createTime;

    @Column(name = "UPDATETIME")
    @LastModifiedDate
    @Convert(converter = AppDateConvertDBLong.class)
    private Date updateTime; //该字段使用自动生成策略并实现转换接口
}

//转换接口
public class AppDateConvertDBLong implements AttributeConverter<Date,Long>
{
    private static final SimpleDateFormat sdf=new SimpleDateFormat("yyyyMMddHHmmss");
    @Override
    public Long convertToDatabaseColumn(Date attribute)
    {
        try
        {
            return attribute == null ? null : Long.parseLong(sdf.format(attribute));
        }
        catch (NumberFormatException e)
        {
            logger.error("convertToDatabaseColumn error : {}",attribute);
            logger.error("convertToDatabaseColumn error :",e);
            //如果失败默认返回当前时间
            return DateUtils.getLong14ForDate();
        }
    }

    @Override
    public Date convertToEntityAttribute(Long dbData)
    {
        try
        {
            return dbData == null ? null : sdf.parse(String.valueOf(dbData));
        } catch (ParseException e)
        {
            logger.error("convertToEntityAttribute error : {}",dbData);
            logger.error("convertToEntityAttribute error :",e);
            return null;
        }
    }
}
运行结果及报错内容

分别来自两个方向的异常:
1 update Date转Long


Caused by: javax.persistence.PersistenceException: Error attempting to apply AttributeConverter
        at org.hibernate.type.descriptor.converter.AttributeConverterSqlTypeDescriptorAdapter$2.doConversion(AttributeConverterSqlTypeDescriptorAdapter.java:148)
        at org.hibernate.type.descriptor.converter.AttributeConverterSqlTypeDescriptorAdapter$2.extract(AttributeConverterSqlTypeDescriptorAdapter.java:121)
        at org.hibernate.type.AbstractStandardBasicType.nullSafeGet(AbstractStandardBasicType.java:257)
        at org.hibernate.type.AbstractStandardBasicType.nullSafeGet(AbstractStandardBasicType.java:253)
        at org.hibernate.type.AbstractStandardBasicType.nullSafeGet(AbstractStandardBasicType.java:243)
        at org.hibernate.type.AbstractStandardBasicType.hydrate(AbstractStandardBasicType.java:329)
        at org.hibernate.persister.entity.AbstractEntityPersister.hydrate(AbstractEntityPersister.java:3131)
        at org.hibernate.loader.Loader.loadFromResultSet(Loader.java:1863)
        at org.hibernate.loader.Loader.hydrateEntityState(Loader.java:1791)
        at org.hibernate.loader.Loader.instanceNotYetLoaded(Loader.java:1764)
        at org.hibernate.loader.Loader.getRow(Loader.java:1616)
        at org.hibernate.loader.Loader.getRowFromResultSet(Loader.java:740)
        at org.hibernate.loader.Loader.getRowsFromResultSet(Loader.java:1039)
        at org.hibernate.loader.Loader.processResultSet(Loader.java:990)
        at org.hibernate.loader.Loader.doQuery(Loader.java:959)
        at org.hibernate.loader.Loader.doQueryAndInitializeNonLazyCollections(Loader.java:349)
        at org.hibernate.loader.Loader.doList(Loader.java:2843)
        at org.hibernate.loader.Loader.doList(Loader.java:2825)
        at org.hibernate.loader.Loader.listIgnoreQueryCache(Loader.java:2657)
        at org.hibernate.loader.Loader.list(Loader.java:2652)
        at org.hibernate.loader.hql.QueryLoader.list(QueryLoader.java:506)
        at org.hibernate.hql.internal.ast.QueryTranslatorImpl.list(QueryTranslatorImpl.java:400)
        at org.hibernate.engine.query.spi.HQLQueryPlan.performList(HQLQueryPlan.java:219)
        at org.hibernate.internal.SessionImpl.list(SessionImpl.java:1414)
        at org.hibernate.query.internal.AbstractProducedQuery.doList(AbstractProducedQuery.java:1636)
        at org.hibernate.query.internal.AbstractProducedQuery.list(AbstractProducedQuery.java:1604)
        at org.hibernate.query.Query.getResultList(Query.java:165)
        at org.hibernate.query.criteria.internal.compile.CriteriaQueryTypeQueryAdapter.getResultList(CriteriaQueryTypeQueryAdapter.java:76)
        at sun.reflect.GeneratedMethodAccessor437.invoke(Unknown Source)
        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:409)
        at com.sun.proxy.$Proxy335.getResultList(Unknown Source)
        at org.springframework.data.jpa.repository.query.JpaQueryExecution$CollectionExecution.doExecute(JpaQueryExecution.java:126)
        at org.springframework.data.jpa.repository.query.JpaQueryExecution.execute(JpaQueryExecution.java:88)
        at org.springframework.data.jpa.repository.query.AbstractJpaQuery.doExecute(AbstractJpaQuery.java:154)
        at org.springframework.data.jpa.repository.query.AbstractJpaQuery.execute(AbstractJpaQuery.java:142)
        at org.springframework.data.repository.core.support.QueryExecutorMethodInterceptor$QueryMethodInvoker.invoke(QueryExecutorMethodInterceptor.java:195)
        at org.springframework.data.repository.core.support.QueryExecutorMethodInterceptor.doInvoke(QueryExecutorMethodInterceptor.java:152)
        at org.springframework.data.repository.core.support.QueryExecutorMethodInterceptor.invoke(QueryExecutorMethodInterceptor.java:130)
        at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
        at org.springframework.data.projection.DefaultMethodInvokingMethodInterceptor.invoke(DefaultMethodInvokingMethodInterceptor.java:80)
        at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
        at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:367)
        at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:118)
        at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
        at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:139)
        ... 28 common frames omitted
Caused by: java.lang.NumberFormatException: For input string: ""
        at java.lang.NumberFormatException.forInputString(NumberFormatException.java:65)
        at java.lang.Long.parseLong(Long.java:601)
        at java.lang.Long.parseLong(Long.java:631)
        at java.text.DigitList.getLong(DigitList.java:195)
        at java.text.DecimalFormat.parse(DecimalFormat.java:2051)
        at java.text.SimpleDateFormat.subParse(SimpleDateFormat.java:2162)
        at java.text.SimpleDateFormat.parse(SimpleDateFormat.java:1514)
        at java.text.DateFormat.parse(DateFormat.java:364)
        at com.cicc.aiis.util.convertor.AppDateConvertDBLong.convertToEntityAttribute(AppDateConvertDBLong.java:43)
        at com.cicc.aiis.util.convertor.AppDateConvertDBLong.convertToEntityAttribute(AppDateConvertDBLong.java:15)
        at org.hibernate.metamodel.model.convert.internal.JpaAttributeConverterImpl.toDomainValue(JpaAttributeConverterImpl.java:45)
        at org.hibernate.type.descriptor.converter.AttributeConverterSqlTypeDescriptorAdapter$2.doConversion(AttributeConverterSqlTypeDescriptorAdapter.java:140)

//2 查询时 Long转Date
java.text.ParseException: Unparseable date: "411207231111"
        at java.text.DateFormat.parse(DateFormat.java:366)
        at com.cicc.aiis.util.convertor.AppDateConvertDBLong.convertToEntityAttribute(AppDateConvertDBLong.java:43)
        at com.cicc.aiis.util.convertor.AppDateConvertDBLong.convertToEntityAttribute(AppDateConvertDBLong.java:15)
        at org.hibernate.metamodel.model.convert.internal.JpaAttributeConverterImpl.toDomainValue(JpaAttributeConverterImpl.java:45)
        at org.hibernate.type.descriptor.converter.AttributeConverterMutabilityPlanImpl.deepCopyNotNull(AttributeConverterMutabilityPlanImpl.java:33)
        at org.hibernate.type.descriptor.java.MutableMutabilityPlan.deepCopy(MutableMutabilityPlan.java:35)
        at org.hibernate.type.AbstractStandardBasicType.deepCopy(AbstractStandardBasicType.java:308)
        at org.hibernate.type.AbstractStandardBasicType.deepCopy(AbstractStandardBasicType.java:304)
        at org.hibernate.type.TypeHelper.deepCopy(TypeHelper.java:55)
        at org.hibernate.engine.internal.TwoPhaseLoad.initializeEntityFromEntityEntryLoadedState(TwoPhaseLoad.java:340)
        at org.hibernate.engine.internal.TwoPhaseLoad.initializeEntity(TwoPhaseLoad.java:156)
        at org.hibernate.engine.internal.TwoPhaseLoad.initializeEntity(TwoPhaseLoad.java:126)
        at org.hibernate.loader.Loader.initializeEntitiesAndCollections(Loader.java:1193)
        at org.hibernate.loader.Loader.processResultSet(Loader.java:1001)
        at org.hibernate.loader.Loader.doQuery(Loader.java:959)
        at org.hibernate.loader.Loader.doQueryAndInitializeNonLazyCollections(Loader.java:349)
        at org.hibernate.loader.Loader.doList(Loader.java:2843)
        at org.hibernate.loader.Loader.doList(Loader.java:2825)
        at org.hibernate.loader.Loader.listIgnoreQueryCache(Loader.java:2657)
        at org.hibernate.loader.Loader.list(Loader.java:2652)
        at org.hibernate.loader.hql.QueryLoader.list(QueryLoader.java:506)
        at org.hibernate.hql.internal.ast.QueryTranslatorImpl.list(QueryTranslatorImpl.java:400)
        at org.hibernate.engine.query.spi.HQLQueryPlan.performList(HQLQueryPlan.java:219)
        at org.hibernate.internal.SessionImpl.list(SessionImpl.java:1414)
        at org.hibernate.query.internal.AbstractProducedQuery.doList(AbstractProducedQuery.java:1636)
        at org.hibernate.query.internal.AbstractProducedQuery.list(AbstractProducedQuery.java:1604)
        at org.hibernate.query.Query.getResultList(Query.java:165)
        at org.hibernate.query.criteria.internal.compile.CriteriaQueryTypeQueryAdapter.getResultList(CriteriaQueryTypeQueryAdapter.java:76)
        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:409)
        at com.sun.proxy.$Proxy335.getResultList(Unknown Source)
        at org.springframework.data.jpa.repository.query.JpaQueryExecution$CollectionExecution.doExecute(JpaQueryExecution.java:126)
        at org.springframework.data.jpa.repository.query.JpaQueryExecution.execute(JpaQueryExecution.java:88)
        at org.springframework.data.jpa.repository.query.AbstractJpaQuery.doExecute(AbstractJpaQuery.java:154)
        at org.springframework.data.jpa.repository.query.AbstractJpaQuery.execute(AbstractJpaQuery.java:142)
        at org.springframework.data.repository.core.support.QueryExecutorMethodInterceptor$QueryMethodInvoker.invoke(QueryExecutorMethodInterceptor.java:195)
        at org.springframework.data.repository.core.support.QueryExecutorMethodInterceptor.doInvoke(QueryExecutorMethodInterceptor.java:152)
        at org.springframework.data.repository.core.support.QueryExecutorMethodInterceptor.invoke(QueryExecutorMethodInterceptor.java:130)
        at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
        at org.springframework.data.projection.DefaultMethodInvokingMethodInterceptor.invoke(DefaultMethodInvokingMethodInterceptor.java:80)
        at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
        at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:367)
        at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:118)
        at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
        at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:139)
        at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
        at org.springframework.data.jpa.repository.support.CrudMethodMetadataPostProcessor$CrudMethodMetadataPopulatingMethodInterceptor.invoke(CrudMethodMetadataPostProcessor.java:149)
        at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
        at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:95)
        at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
        at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:212)
        at com.sun.proxy.$Proxy257.findSubEntrustOrdersByEntrustPortfolioIdAndOrderStatus(Unknown Source)
        at com.cicc.aiis.service.trade.EntrustPortfolioServiceImpl.querySubEntrustsByStatus(EntrustPortfolioServiceImpl.java:329)
        at com.cicc.aiis.service.trade.EntrustPortfolioServiceImpl$$FastClassBySpringCGLIB$$592c3f78.invoke(<generated>)
        at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:218)
        at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:688)
        at com.cicc.aiis.service.trade.EntrustPortfolioServiceImpl$$EnhancerBySpringCGLIB$$dde6175e.querySubEntrustsByStatus(<generated>)
        at com.cicc.aiis.service.trade.EntranceServiceImpl.reservationToOrder(EntranceServiceImpl.java:148)
        at com.cicc.aiis.service.trade.EntranceServiceImpl$$FastClassBySpringCGLIB$$dfb5bb5b.invoke(<generated>)
        at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:218)
        at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:688)
        at com.cicc.aiis.service.trade.EntranceServiceImpl$$EnhancerBySpringCGLIB$$6cb190e7.reservationToOrder(<generated>)
        at com.cicc.aiis.service.impl.ReservationOrderServiceImpl.processOrder(ReservationOrderServiceImpl.java:114)
        at com.cicc.aiis.service.impl.ReservationOrderServiceImpl.processEachOrder(ReservationOrderServiceImpl.java:99)
        at java.util.stream.ForEachOps$ForEachOp$OfRef.accept(ForEachOps.java:184)
        at java.util.ArrayList$ArrayListSpliterator.forEachRemaining(ArrayList.java:1374)
        at java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:481)
        at java.util.stream.ForEachOps$ForEachTask.compute(ForEachOps.java:291)
        at java.util.concurrent.CountedCompleter.exec(CountedCompleter.java:731)
        at java.util.concurrent.ForkJoinTask.doExec(ForkJoinTask.java:289)
        at java.util.concurrent.ForkJoinPool$WorkQueue.runTask(ForkJoinPool.java:1056)
        at java.util.concurrent.ForkJoinPool.runWorker(ForkJoinPool.java:1692)
        at java.util.concurrent.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:157)
我的解答思路和尝试过的方法

其中第一个异常问题 我甚至在代码中显示的setUpdateTime(new Date),也会报错
而第二个异常,数据库中绝对是可读的14位时间戳 20211213112328 抛异常时却显示读到了411207231111 ,这个很诡异啊,411207231111 这个数据在数据库也搜不到。多试几次还会出现别的数字,比如11123 这种随机的错误的时间数字
最关键的时候只要使用多线程,就会出现,单线程就一点问题没有。我用的是List.parallelStream().forEach的方式

我想要达到的结果

希望高人指点,谢谢

  • 写回答

2条回答 默认 最新

  • 宁-静-致-远 2021-12-13 17:17
    关注

    SimpleDateFormat 不是线程安全类,这个不要定义为静态的,如有帮助请采纳

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(1条)

报告相同问题?

问题事件

  • 系统已结题 12月21日
  • 已采纳回答 12月13日
  • 创建了问题 12月13日

悬赏问题

  • ¥15 stata空间计量LM检验
  • ¥15 NAO机器人说出txt文本内容
  • ¥15 关于k8s node节点被释放后如何驱逐节点并添加新节点
  • ¥15 subprocess.CalledProcessError: Command ‘[‘ninja‘, ‘-v‘]‘ returned non-zero exit status 1
  • ¥15 for循环处理大量数据怎么优化
  • ¥15 笔记本接显卡扩展坞重启报错
  • ¥15 为什么这个指令报错啊,一直弄不懂为什么,想问问该怎么弄,决求解决,ubuntu刚入手
  • ¥15 用百度飞将的paddleyolo库里的yolov7训练自己数据集
  • ¥15 Saber里如何查看磁芯的磁通密度
  • ¥25 关于下拉菜单、数据库、关联选项的问题