Skip to content

Commit 53c7f80

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 b47fc35 commit 53c7f80

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
@@ -74,6 +74,7 @@
7474
* @author Christoph Strobl
7575
* @author Ninad Divadkar
7676
* @author Anqing Shao
77+
* @author Mark Paluch
7778
* @param <K> the Redis key type against which the template works (usually a String)
7879
* @param <V> the Redis value type against which the template works
7980
* @see StringRedisTemplate
@@ -212,10 +213,7 @@ public <T> T execute(RedisCallback<T> action, boolean exposeConnection, boolean
212213
// TODO: any other connection processing?
213214
return postProcessResult(result, connToUse, existingConnection);
214215
} finally {
215-
216-
if (!enableTransactionSupport) {
217-
RedisConnectionUtils.releaseConnection(conn, factory);
218-
}
216+
RedisConnectionUtils.releaseConnection(conn, factory);
219217
}
220218
}
221219

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

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

42+
/**
43+
* Base class with integration tests for transactional use.
44+
*
45+
* @author Thomas Darimont
46+
* @author Christoph Strobl
47+
* @author Mark Paluch
48+
*/
4249
@RunWith(RelaxedJUnit4ClassRunner.class)
4350
@Transactional(transactionManager = "transactionManager")
4451
public abstract class AbstractTransactionalTestBase {
@@ -129,6 +136,19 @@ public void valueOperationSetShouldBeCommittedCorrectly() {
129136
}
130137
}
131138

139+
/**
140+
* @see DATAREDIS-548
141+
*/
142+
@Test
143+
@Transactional(readOnly = true)
144+
public void valueOperationShouldWorkWithReadOnlyTransactions() {
145+
146+
this.valuesShouldHaveBeenPersisted = false;
147+
for (String key : KEYS) {
148+
template.opsForValue().get(key);
149+
}
150+
}
151+
132152
/**
133153
* @see DATAREDIS-73
134154
*/
@@ -146,7 +166,7 @@ public void listOperationLPushShoudBeRolledBackCorrectly() {
146166
*/
147167
@Rollback(false)
148168
@Test
149-
public void listOperationLPushShoudBeCommittedCorrectly() {
169+
public void listOperationLPushShouldBeCommittedCorrectly() {
150170

151171
this.valuesShouldHaveBeenPersisted = true;
152172
for (String key : KEYS) {

0 commit comments

Comments
 (0)