2012-06-21 47 views
6

所有的Spring配置都是正確編寫的。非多執行Redis操作完美地工作。如何使用Spring-data-Redis實現Redis Multi-Exec

@Autowired 
@Qualifier("stringRedisTemplate") 
StringRedisTemplate template; 

void test(){ 
    template.multi(); 
    template.boundValueOps("somevkey").increment(1); 
    template.boundZSetOps("somezkey").add("zvalue", timestamp); 
    template.exec(); 
} 

在通過Junit測試運行上面的代碼之後,拋出異常。

org.springframework.data.redis.RedisSystemException: Unknown exception; nested exception is org.springframework.data.redis.RedisSystemException: Unknown jedis exception; nested exception is java.lang.NullPointerException 
     at org.springframework.data.redis.connection.jedis.JedisUtils.convertJedisAccessException(JedisUtils.java:93) 
     at org.springframework.data.redis.connection.jedis.JedisConnectionFactory.translateExceptionIfPossible(JedisConnectionFactory.java:155) 
     at org.springframework.dao.support.ChainedPersistenceExceptionTranslator.translateExceptionIfPossible(ChainedPersistenceExceptionTranslator.java:58) 
     at org.springframework.dao.support.DataAccessUtils.translateIfNecessary(DataAccessUtils.java:213) 
     at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:163) 
     at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172) 
     at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:202) 
     at $Proxy66.appendUserStream(Unknown Source) 
     at com.uniu.test.repository.StreamCacheRepositoryTest.testAppendUserStream(StreamCacheRepositoryTest.java:23) 
     at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 
     at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) 
     at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) 
     at java.lang.reflect.Method.invoke(Method.java:597) 
     at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:44) 
     at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:15) 
     at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:41) 
     at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:20) 
     at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:28) 
     at org.springframework.test.context.junit4.statements.RunBeforeTestMethodCallbacks.evaluate(RunBeforeTestMethodCallbacks.java:74) 
     at org.springframework.test.context.junit4.statements.RunAfterTestMethodCallbacks.evaluate(RunAfterTestMethodCallbacks.java:83) 
     at org.springframework.test.context.junit4.statements.SpringRepeat.evaluate(SpringRepeat.java:72) 
     at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:231) 
     at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:49) 
     at org.junit.runners.ParentRunner$3.run(ParentRunner.java:193) 
     at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:52) 
     at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:191) 
     at org.junit.runners.ParentRunner.access$000(ParentRunner.java:42) 
     at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:184) 
     at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61) 
     at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:71) 
     at org.junit.runners.ParentRunner.run(ParentRunner.java:236) 
     at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:174) 
     at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:49) 
     at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38) 
     at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:467) 
     at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:683) 
     at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:390) 
     at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197) 
    Caused by: org.springframework.data.redis.RedisSystemException: Unknown jedis exception; nested exception is java.lang.NullPointerException 
     at org.springframework.data.redis.connection.jedis.JedisConnection.convertJedisAccessException(JedisConnection.java:119) 
     at org.springframework.data.redis.connection.jedis.JedisConnection.exec(JedisConnection.java:523) 
     at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 
     at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) 
     at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) 
     at java.lang.reflect.Method.invoke(Method.java:597) 
     at org.springframework.data.redis.core.CloseSuppressingInvocationHandler.invoke(CloseSuppressingInvocationHandler.java:58) 
     at $Proxy70.exec(Unknown Source) 
     at org.springframework.data.redis.core.RedisTemplate$1.doInRedis(RedisTemplate.java:416) 
     at org.springframework.data.redis.core.RedisTemplate$1.doInRedis(RedisTemplate.java:412) 
     at org.springframework.data.redis.core.RedisTemplate.execute(RedisTemplate.java:162) 
     at org.springframework.data.redis.core.RedisTemplate.execute(RedisTemplate.java:133) 
     at org.springframework.data.redis.core.RedisTemplate.execute(RedisTemplate.java:121) 
     at org.springframework.data.redis.core.RedisTemplate.exec(RedisTemplate.java:412) 
     at com.uniu.repository.impl.StreamCacheRepositoryRedisImpl.appendUserStream(StreamCacheRepositoryRedisImpl.java:37) 
     at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 
     at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) 
     at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) 
     at java.lang.reflect.Method.invoke(Method.java:597) 
     at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:318) 
     at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:183) 
     at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:150) 
     at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:155) 
     ... 33 more 
    Caused by: java.lang.NullPointerException 
     at redis.clients.jedis.BinaryTransaction.exec(BinaryTransaction.java:31) 
     at org.springframework.data.redis.connection.jedis.JedisConnection.exec(JedisConnection.java:521) 
     ... 54 more 

我檢查redis服務器,上面的兩個命令已經執行,結果是正確的。所以問題出現在代碼的最後一行(template.exec())。當底層JedisClient試圖從EXEC獲得多堆響應時,它似乎拋出空指針異常

我使用spring-data-redis 1.0.0.RELEASE 感謝您的幫助。

回答

8

該異常的原因可能是Spring模板實現不會重用.multi().exec()的相同連接。您可以嘗試通過回撥使用​​:

private RedisTemplate template = ...; 

template.execute(

    new RedisCallback() { 

    @Override 
    public Object doInRedis(RedisConnection connection) 
     throws DataAccessException { 

     connection.multi(); 

     //do whatever you need, like deleting and repopulating some keys 

     connection.expire(CHANNEL_KEY.getBytes(), EXPIRE_SECS); 
     connection.exec(); 
     return null; 
    } 

    } 

); 
+0

我不認爲這是真的。只要multi和exec通過相同的工廠調用並且事務處於啓用狀態,那麼兩者之間的任何調用都將使用相同的連接。你可以從RedisConnectionUtils中看到 – Olayinka

5
template.setEnableTransactionSupport(true); 

也許你可以用戶這使交易