2012-06-21 13 views
6

Tất cả cấu hình Spring được viết đúng cách. Thao tác Non-Multi-Exec Redis hoạt động hoàn hảo.Cách triển khai Redis Multi-Exec bằng cách sử dụng Spring-data-Redis

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

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

Sau khi chạy mã trên thông qua kiểm tra Junit, Ngoại lệ được ném.

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 

Tôi kiểm tra máy chủ redis, hai lệnh trên đã được thực hiện và kết quả là chính xác. Vì vậy, vấn đề xuất hiện ở dòng cuối cùng của mã (template.exec()). Khi cơ bản JedisClient cố gắng để có được phản ứng multibulk từ EXEC, có vẻ như để ném NullPointerException

Tôi sử dụng spring-data-redis 1.0.0.RELEASE Cảm ơn bạn đã trợ giúp.

Trả lời

8

Lý do ngoại lệ có thể là triển khai mẫu Spring không tái sử dụng cùng một kết nối cho .multi().exec(). Bạn có thể thử sử dụng execute() qua gọi lại:

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

Tôi không nghĩ điều này là đúng. Miễn là đa và exec được gọi thông qua cùng một nhà máy và giao dịch được kích hoạt, sau đó bất kỳ cuộc gọi ở giữa sẽ sử dụng cùng một kết nối. Bạn có thể thấy từ RedisConnectionUtils – Olayinka

5
template.setEnableTransactionSupport(true); 

có lẽ bạn có thể sử dụng này để kích hoạt giao dịch