Skip to content

Commit 87f03bd

Browse files
mp911dechristophstrobl
authored andcommitted
DATAREDIS-548 - Release connection after command execution in read-only transactions.
We now unbind and release the connection from the transaction resources after a Redis command is invoked. Redis read operations return always null while using RedisTemplate in a transaction so Redis read transactions are not useful. Previously, RedisConnection's were bound as transactional resource when used in the scope of a @transactional(readOnly = true) method but not released on transaction completion. This was, because connections are not registered with a transaction synchronizer. Original Pull Request: #214
1 parent d6fee83 commit 87f03bd

File tree

3 files changed

+31
-8
lines changed

3 files changed

+31
-8
lines changed

src/main/java/org/springframework/data/redis/core/RedisConnectionUtils.java

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2011-2015 the original author or authors.
2+
* Copyright 2011-2016 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -39,6 +39,7 @@
3939
* @author Costin Leau
4040
* @author Christoph Strobl
4141
* @author Thomas Darimont
42+
* @author Mark Paluch
4243
*/
4344
public abstract class RedisConnectionUtils {
4445

@@ -199,8 +200,12 @@ public static void releaseConnection(RedisConnection conn, RedisConnectionFactor
199200
return;
200201
}
201202

202-
// Only release non-transactional/non-bound connections.
203-
if (!isConnectionTransactional(conn, factory)) {
203+
// release transactional/read-only and non-transactional/non-bound connections.
204+
// transactional connections for read-only transactions get no synchronizer registered
205+
if (isConnectionTransactional(conn, factory)
206+
&& TransactionSynchronizationManager.isCurrentTransactionReadOnly()) {
207+
unbindConnection(factory);
208+
} else if (!isConnectionTransactional(conn, factory)) {
204209
if (log.isDebugEnabled()) {
205210
log.debug("Closing Redis Connection");
206211
}

src/main/java/org/springframework/data/redis/core/RedisTemplate.java

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,7 @@
7272
* @author Costin Leau
7373
* @author Christoph Strobl
7474
* @author Anqing Shao
75+
* @author Mark Paluch
7576
* @param <K> the Redis key type against which the template works (usually a String)
7677
* @param <V> the Redis value type against which the template works
7778
* @see StringRedisTemplate
@@ -199,10 +200,7 @@ public <T> T execute(RedisCallback<T> action, boolean exposeConnection, boolean
199200
// TODO: any other connection processing?
200201
return postProcessResult(result, connToUse, existingConnection);
201202
} finally {
202-
203-
if (!enableTransactionSupport) {
204-
RedisConnectionUtils.releaseConnection(conn, factory);
205-
}
203+
RedisConnectionUtils.releaseConnection(conn, factory);
206204
}
207205
}
208206

src/test/java/org/springframework/data/redis/connection/AbstractTransactionalTestBase.java

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,13 @@
4040
import org.springframework.transaction.PlatformTransactionManager;
4141
import org.springframework.transaction.annotation.Transactional;
4242

43+
/**
44+
* Base class with integration tests for transactional use.
45+
*
46+
* @author Thomas Darimont
47+
* @author Christoph Strobl
48+
* @author Mark Paluch
49+
*/
4350
@RunWith(RelaxedJUnit4ClassRunner.class)
4451
@Transactional
4552
@TransactionConfiguration(transactionManager = "transactionManager")
@@ -131,6 +138,19 @@ public void valueOperationSetShouldBeCommittedCorrectly() {
131138
}
132139
}
133140

141+
/**
142+
* @see DATAREDIS-548
143+
*/
144+
@Test
145+
@Transactional(readOnly = true)
146+
public void valueOperationShouldWorkWithReadOnlyTransactions() {
147+
148+
this.valuesShouldHaveBeenPersisted = false;
149+
for (String key : KEYS) {
150+
template.opsForValue().get(key);
151+
}
152+
}
153+
134154
/**
135155
* @see DATAREDIS-73
136156
*/
@@ -148,7 +168,7 @@ public void listOperationLPushShoudBeRolledBackCorrectly() {
148168
*/
149169
@Rollback(false)
150170
@Test
151-
public void listOperationLPushShoudBeCommittedCorrectly() {
171+
public void listOperationLPushShouldBeCommittedCorrectly() {
152172

153173
this.valuesShouldHaveBeenPersisted = true;
154174
for (String key : KEYS) {

0 commit comments

Comments
 (0)