Spring Data JPA findById()引发ClassCastException

时间:2018-06-26 05:55:01

标签: java spring spring-data-jpa optional classcastexception

我有一个使用Spring Data JPA的findById()方法的方法。但是,此方法在getSupportedKey()方法的第1行上返回ClassCastException,我在其中调用findById():

MySupportedKey cannot be cast to java.util.Optional

private MySupportedKey getSupportedKey(String tenant, String key) {
        Optional<MySupportedKey> mySupportedKeyOptional = mySupportedKeyRepository.findById(new MySupportedKeyId(tenant, key));
        MySupportedKey mySupportedKey= null;
        if(mySupportedKeyOptional !=null) {
             mySupportedKey= mySupportedKeyOptional.orElse(null);
        }
        return mySupportedKey;
    }

我已经很久没打过头了,但是我什么也没得到。请帮助我解决此问题。我正在使用 spring-data-jpa:2.0.8.RELEASE

添加存储库源代码:

public interface MySupportedKeyRepository extends JpaRepository<MySupportedKey, MySupportedKeyId> {

List<MySupportedKey> findByIdTenant(@NotNull String tenant);
}

添加完整的堆栈错误跟踪:

java.lang.ClassCastException: com.test.service.user.entity.MySupportedKey cannot be cast to java.util.Optional
at com.test.service.user.repository.MySupportedKeyRepository$MockitoMock$1304362870.findById(Unknown Source)
at com.test.service.user.repository.MySupportedKeyRepository$MockitoMock$1304362870.findById(Unknown Source)
at com.test.service.user.userpreferences.PreferencesServiceImpl.getSupportedKey(PreferencesServiceImpl.java:217)
at com.test.service.user.userpreferences.PreferencesServiceImpl.updateUserPreferences(PreferencesServiceImpl.java:167)
at com.test.service.user.userpreferences.PreferencesServiceImpl.lambda$2(PreferencesServiceImpl.java:92)
at java.util.ArrayList.forEach(Unknown Source)
at com.test.service.user.userpreferences.PreferencesServiceImpl.updateUserPreferences(PreferencesServiceImpl.java:92)
at com.test.service.user.preferences.PreferencesServiceImplTest.updateUserPreferences(PreferencesServiceImplTest.java:300)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
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.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26)
at org.mockito.internal.junit.JUnitRule$1.evaluateSafely(JUnitRule.java:52)
at org.mockito.internal.junit.JUnitRule$1.evaluate(JUnitRule.java:43)
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.RunPrepareTestInstanceCallbacks.evaluate(RunPrepareTestInstanceCallbacks.java:64)
at org.springframework.test.context.junit4.statements.SpringRepeat.evaluate(SpringRepeat.java:84)
at org.springframework.test.context.junit4.statements.SpringFailOnTimeout.evaluate(SpringFailOnTimeout.java:87)
at org.springframework.test.context.junit4.statements.ProfileValueChecker.evaluate(ProfileValueChecker.java:103)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)
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.springframework.test.context.junit4.statements.ProfileValueChecker.evaluate(ProfileValueChecker.java:103)
at org.springframework.test.context.junit4.rules.SpringClassRule$TestContextManagerCacheEvictor.evaluate(SpringClassRule.java:230)
at org.junit.rules.RunRules.evaluate(RunRules.java:20)
at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
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)

3 个答案:

答案 0 :(得分:3)

您为存储库设置了一个Mockito模拟,并可能告诉它在调用MySupportedKey时返回一个findById实例。 但是由于findById应该返回Optional,所以您现在得到了异常。

您可以看到这是来自Mockito的堆栈跟踪的前两行。

java.lang.ClassCastException: com.test.service.user.entity.MySupportedKey cannot be cast to java.util.Optional
at com.test.service.user.repository.MySupportedKeyRepository$MockitoMock$1304362870.findById(Unknown Source)

答案 1 :(得分:0)

在您的以下方法中修改 Optional 处理以获取如下所示的正确表示形式:

private MySupportedKey getSupportedKey(String tenant, String key) {
            Optional<MySupportedKey> mySupportedKeyOptional = mySupportedKeyRepository.findById(new MySupportedKeyId(tenant, key));
            MySupportedKey mySupportedKey= null;
            if(mySupportedKeyOptional.isPresent()) {
                 mySupportedKey= mySupportedKeyOptional.get();
            }
            return mySupportedKey;
        }

答案 2 :(得分:0)

无法添加评论,只想详细说明Jens的答案,因为花了我一段时间才弄清楚如何解决(成为新手)。 要解决此问题,我从以下位置更改了代码:

    SELECT 
        '25597' AS company_id,    
        to_date('03/20/2019','mm/dd/yyyy') AS rec_date,
        P.*

    FROM

    (  
    SELECT D.FieldYear -- This column does not get loaded - just for comparison with the year column
           ,F.ColumnName Field 
           ,CASE F.IsPercent
            WHEN 1 THEN D.FieldValue * 100.0
                   ELSE D.FieldValue
            END FieldValue
     FROM (SELECT 
         CAST(FieldYear AS Number) FieldYear
        , FieldType
        , CASE FieldValue 
            WHEN n'' THEN NULL
            ELSE CAST (FieldValue AS Number(38,8))
          END FieldValue
    FROM 
       (SELECT IncomeStatementField AS FieldType
        ,Y1 as "2013"
        ,Y2 as "2014"
        ,Y3 as "2015"
        ,Y4 as "2016"
        ,Y5 as "2017"
        ,Y6 as "2018" 
        ,Y7 as "2019"
        ,Y8 as "2020"
        ,Y9 as "2021"
        ,Y10 as "2022"
        ,Y11 as "2023"
        ,Y12 as "2024"
        ,Y13 as "2025"
        ,Y14 as "2026"
        ,Y15 as "2027"
        ,Y16 as "2028"
        ,Y17 as "2029"
        ,Y18 as "2030"
        ,Y19 as "2031"
        ,Y20 as "2032"
        ,Y21 as "2033"
        ,Y22 as "2034"
        ,Y23 as  "2035"
        ,Y24 as "2036"
        ,Y25 as "2037"
        ,Y26 as "2038"
        ,Y27 as "2039"
        ,Y28 as "2040"
        ,Y29 as "2041"
        ,Y30 as "2042"
        ,Y31 as "2043"
        ,Y32 as "2044"
        ,Y33 as "2045"
        ,Y34 as "2046"
        ,Y35 as "2047"

      FROM TBLTMPLTS_LOAD_INCSTATEMT_RAW) 
    UNPIVOT
       (FieldValue FOR FieldYear IN 
        ("2013"
        ,"2014"
        ,"2015"
        ,"2016"
        ,"2017"
        ,"2018"
        ,"2019"
        ,"2020"
        ,"2021"
        ,"2022"
        ,"2023"
        ,"2024"
        ,"2025"
        ,"2026"
        ,"2027"
        ,"2028"
        ,"2029"
        ,"2030"
        ,"2031"
        ,"2032"
        ,"2033"
        ,"2034"
        ,"2035"
        ,"2036"
        ,"2037"
        ,"2038"
        ,"2039"
        ,"2040"
        ,"2041"
        ,"2042"
        ,"2043"
        ,"2044"
        ,"2045"
        ,"2046"
        ,"2047"
    )
    )) D 
     JOIN tblTemplates_Fields F ON D.FieldType = F.FieldName

     WHERE F.TemplateSection = 'Income Statement'
     AND F.TemplateType In ('All', 'ALL','Industrial')
     AND    (TemplateVersion = '1' or (TemplateVersion is null and '1' <> 'V8')))  P

     PIVOT
    (
    SUM(FieldValue) 
    FOR Field IN 
        ('year',
        'sales',
        'ebitda_margin',
        'op_margin',
        'pretax_charges',
        'net_int_exp',
        'pretax_margin',
        'tax_rate','after_tax_income_gaap',
        'pretax_income',
        'net_income_adjustment',
        'ret_income',
        'shares',
        'eps',
        'dps',
        'accrual_adj_to_net_income',
        'minority_interest',
        'cash_movement',
        'working_cap',
        'int_rate_cash',
        'net_wc',
        'net_wc_to_sales',
        'sales_growth',
        'int_rate_debt',
        'roce',
        'net_debt',
        'free_cash_flow',
        'stock_issuance','debt_issuance','disposals','capex','cash_flow_from_ops','amortization','depreciation','pref_div','net_income_adjusted','capex_sales_check'
        )
    )  pvt

收件人

when(mongoRepository.findById(Mockito.anyString())).thenAnswer(new Answer<MongoObj>() {
        @Override
        public MongoObj answer(InvocationOnMock invocation) throws Throwable {
            MongoObj repush = new MongoObj();
            //Some other code

            return repush;
        }
    });

希望这会有所帮助!