diff --git a/eeos/src/main/java/com/blackcompany/eeos/auth/application/event/DeletedMemberEventListener.java b/eeos/src/main/java/com/blackcompany/eeos/auth/application/event/DeletedMemberEventListener.java index ac5ceec8..84feb794 100644 --- a/eeos/src/main/java/com/blackcompany/eeos/auth/application/event/DeletedMemberEventListener.java +++ b/eeos/src/main/java/com/blackcompany/eeos/auth/application/event/DeletedMemberEventListener.java @@ -1,7 +1,7 @@ package com.blackcompany.eeos.auth.application.event; import com.blackcompany.eeos.auth.application.domain.token.TokenResolver; -import com.blackcompany.eeos.auth.persistence.BlackAuthenticationRepository; +import com.blackcompany.eeos.auth.persistence.InvalidTokenRepository; import com.blackcompany.eeos.target.persistence.AttendRepository; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; @@ -17,7 +17,7 @@ @Slf4j public class DeletedMemberEventListener { private final AttendRepository attendRepository; - private final BlackAuthenticationRepository blackAuthenticationRepository; + private final InvalidTokenRepository invalidTokenRepository; private final TokenResolver tokenResolver; @Async @@ -33,7 +33,7 @@ private void deleteTargetData(Long memberId) { } private void saveUsedToken(String token, Long memberId) { - blackAuthenticationRepository.save(token, memberId, getExpiredDate(token)); + invalidTokenRepository.save(token, memberId, getExpiredDate(token)); } private Long getExpiredDate(String token) { diff --git a/eeos/src/main/java/com/blackcompany/eeos/auth/application/service/DeactivateMemberService.java b/eeos/src/main/java/com/blackcompany/eeos/auth/application/service/DeactivateMemberService.java index c91042d2..8eb2cb07 100644 --- a/eeos/src/main/java/com/blackcompany/eeos/auth/application/service/DeactivateMemberService.java +++ b/eeos/src/main/java/com/blackcompany/eeos/auth/application/service/DeactivateMemberService.java @@ -4,7 +4,7 @@ import com.blackcompany.eeos.auth.application.event.DeletedMemberEvent; import com.blackcompany.eeos.auth.application.usecase.LogOutUsecase; import com.blackcompany.eeos.auth.application.usecase.WithDrawUsecase; -import com.blackcompany.eeos.auth.persistence.BlackAuthenticationRepository; +import com.blackcompany.eeos.auth.persistence.InvalidTokenRepository; import com.blackcompany.eeos.auth.persistence.OAuthMemberRepository; import com.blackcompany.eeos.member.persistence.MemberRepository; import lombok.RequiredArgsConstructor; @@ -16,7 +16,7 @@ @RequiredArgsConstructor @Transactional(readOnly = true) public class DeactivateMemberService implements LogOutUsecase, WithDrawUsecase { - private final BlackAuthenticationRepository blackAuthenticationRepository; + private final InvalidTokenRepository invalidTokenRepository; private final TokenResolver tokenResolver; private final ApplicationEventPublisher eventPublisher; private final MemberRepository memberRepository; @@ -39,7 +39,7 @@ public void withDraw(final String token, final Long memberId) { } private void saveUsedToken(final String token, final Long memberId) { - blackAuthenticationRepository.save(token, memberId, getExpiredToken(token)); + invalidTokenRepository.save(token, memberId, getExpiredToken(token)); } private Long getExpiredToken(final String token) { diff --git a/eeos/src/main/java/com/blackcompany/eeos/auth/application/service/ReissueService.java b/eeos/src/main/java/com/blackcompany/eeos/auth/application/service/ReissueService.java index 8ec4127a..23c25e5e 100644 --- a/eeos/src/main/java/com/blackcompany/eeos/auth/application/service/ReissueService.java +++ b/eeos/src/main/java/com/blackcompany/eeos/auth/application/service/ReissueService.java @@ -5,7 +5,7 @@ import com.blackcompany.eeos.auth.application.exception.InvalidTokenException; import com.blackcompany.eeos.auth.application.support.AuthenticationTokenGenerator; import com.blackcompany.eeos.auth.application.usecase.ReissueUsecase; -import com.blackcompany.eeos.auth.persistence.BlackAuthenticationRepository; +import com.blackcompany.eeos.auth.persistence.InvalidTokenRepository; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -15,30 +15,30 @@ @Transactional(readOnly = true) public class ReissueService implements ReissueUsecase { private final AuthenticationTokenGenerator authenticationTokenGenerator; - private final BlackAuthenticationRepository blackAuthenticationRepository; + private final InvalidTokenRepository invalidTokenRepository; private final TokenResolver tokenResolver; @Transactional @Override public TokenModel execute(final String token) { - Long memberId = tokenResolver.getUserDataByRefreshToken(token); - validateToken(token); + + Long memberId = tokenResolver.getUserDataByRefreshToken(token); saveUsedToken(token, memberId); return authenticationTokenGenerator.execute(memberId); } private void validateToken(final String token) { - boolean isExistToken = blackAuthenticationRepository.isExistToken(token); + Boolean isExistToken = invalidTokenRepository.isExistToken(token); - if (isExistToken) { + if (Boolean.TRUE.equals(isExistToken)) { throw new InvalidTokenException(); } } private void saveUsedToken(final String token, final Long memberId) { - blackAuthenticationRepository.save(token, memberId, getExpiredToken(token)); + invalidTokenRepository.save(token, memberId, getExpiredToken(token)); } private Long getExpiredToken(final String token) { diff --git a/eeos/src/main/java/com/blackcompany/eeos/auth/persistence/AccountRepository.java b/eeos/src/main/java/com/blackcompany/eeos/auth/persistence/AccountRepository.java index 0eb6df1e..d8a9d5a3 100644 --- a/eeos/src/main/java/com/blackcompany/eeos/auth/persistence/AccountRepository.java +++ b/eeos/src/main/java/com/blackcompany/eeos/auth/persistence/AccountRepository.java @@ -1,6 +1,5 @@ package com.blackcompany.eeos.auth.persistence; -import java.util.List; import java.util.Optional; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.Query; @@ -8,9 +7,6 @@ public interface AccountRepository extends JpaRepository { - @Query("SELECT a.memberId FROM AccountEntity a WHERE a.loginId = :loginId AND a.passWd = :passWd") - List findByMemberId(@Param("loginId") String loginId, @Param("passWd") String passWd); - @Query("SELECT a.passWd FROM AccountEntity a WHERE a.loginId=:loginId") Optional findByLoginId(@Param("loginId") String loginId); } diff --git a/eeos/src/main/java/com/blackcompany/eeos/auth/persistence/BlackAuthenticationEntity.java b/eeos/src/main/java/com/blackcompany/eeos/auth/persistence/BlackAuthenticationEntity.java deleted file mode 100644 index dc6f64d3..00000000 --- a/eeos/src/main/java/com/blackcompany/eeos/auth/persistence/BlackAuthenticationEntity.java +++ /dev/null @@ -1,22 +0,0 @@ -package com.blackcompany.eeos.auth.persistence; - -import lombok.AllArgsConstructor; -import lombok.Getter; -import lombok.NoArgsConstructor; -import lombok.Setter; -import lombok.ToString; -import org.springframework.data.annotation.Id; -import org.springframework.data.redis.core.RedisHash; -import org.springframework.data.redis.core.TimeToLive; - -@RedisHash("MemberAuthentication") -@Getter -@Setter -@ToString -@AllArgsConstructor -@NoArgsConstructor -public class BlackAuthenticationEntity { - @Id private String token; - private Long memberId; - @TimeToLive private Long expiration; -} diff --git a/eeos/src/main/java/com/blackcompany/eeos/auth/persistence/BlackAuthenticationRepository.java b/eeos/src/main/java/com/blackcompany/eeos/auth/persistence/InvalidTokenRepository.java similarity index 85% rename from eeos/src/main/java/com/blackcompany/eeos/auth/persistence/BlackAuthenticationRepository.java rename to eeos/src/main/java/com/blackcompany/eeos/auth/persistence/InvalidTokenRepository.java index f020d068..ff4ae0c5 100644 --- a/eeos/src/main/java/com/blackcompany/eeos/auth/persistence/BlackAuthenticationRepository.java +++ b/eeos/src/main/java/com/blackcompany/eeos/auth/persistence/InvalidTokenRepository.java @@ -7,7 +7,7 @@ @Repository @RequiredArgsConstructor -public class BlackAuthenticationRepository { +public class InvalidTokenRepository { private final RedisTemplate redisTemplate; @@ -15,7 +15,7 @@ public void save(String token, Long memberId, Long expiration) { redisTemplate.opsForValue().set(token, memberId, expiration, TimeUnit.MILLISECONDS); } - public boolean isExistToken(String key) { + public Boolean isExistToken(String key) { return redisTemplate.hasKey(key); } } diff --git a/eeos/src/main/java/com/blackcompany/eeos/config/RedisConfig.java b/eeos/src/main/java/com/blackcompany/eeos/config/RedisConfig.java index 66c4c658..b0eabd35 100644 --- a/eeos/src/main/java/com/blackcompany/eeos/config/RedisConfig.java +++ b/eeos/src/main/java/com/blackcompany/eeos/config/RedisConfig.java @@ -6,6 +6,8 @@ import org.springframework.data.redis.connection.RedisConnectionFactory; import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory; import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer; +import org.springframework.data.redis.serializer.StringRedisSerializer; @Configuration public class RedisConfig { @@ -26,6 +28,14 @@ public RedisTemplate redisTemplate() { redisTemplate.setConnectionFactory(redisConnectionFactory()); redisTemplate.setEnableTransactionSupport(true); + redisTemplate.setKeySerializer(new StringRedisSerializer()); + redisTemplate.setHashKeySerializer(new StringRedisSerializer()); + + redisTemplate.setValueSerializer(new GenericJackson2JsonRedisSerializer()); + redisTemplate.setHashValueSerializer(new GenericJackson2JsonRedisSerializer()); + + redisTemplate.afterPropertiesSet(); + return redisTemplate; } } diff --git a/eeos/src/main/java/com/blackcompany/eeos/member/application/service/CreateAdminMemberService.java b/eeos/src/main/java/com/blackcompany/eeos/member/application/service/CreateAdminMemberService.java index fe1ec193..11f67628 100644 --- a/eeos/src/main/java/com/blackcompany/eeos/member/application/service/CreateAdminMemberService.java +++ b/eeos/src/main/java/com/blackcompany/eeos/member/application/service/CreateAdminMemberService.java @@ -46,10 +46,10 @@ public void init() { @Override public Long create() { MemberEntity savedMember = saveMember(memberEntityConverter.toEntity(createMember())); - AccountEntity savedAccount = - saveAccount(accountEntityConverter.toEntity(createAccount(savedMember.getId()))); - OAuthMemberEntity savedOauthMember = - saveOauthMember(oauthMemberEntityConverter.toEntity(savedMember.getId())); + + saveAccount(accountEntityConverter.toEntity(createAccount(savedMember.getId()))); + saveOauthMember(oauthMemberEntityConverter.toEntity(savedMember.getId())); + return savedMember.getId(); } @@ -60,9 +60,7 @@ public boolean isExist() { .filter(MemberEntity::isAdmin) .collect(Collectors.toList()); - if (!findAdminAccount() || !members.isEmpty() || !findAdminOauthMember()) return true; - - return false; + return !members.isEmpty() || !findAdminAccount() || !findAdminOauthMember(); } private MemberEntity saveMember(MemberEntity entity) { diff --git a/eeos/src/main/java/com/blackcompany/eeos/program/application/support/ProgramAttendScheduler.java b/eeos/src/main/java/com/blackcompany/eeos/program/application/support/ProgramAttendScheduler.java index 19fe1e7a..1b0edaa6 100644 --- a/eeos/src/main/java/com/blackcompany/eeos/program/application/support/ProgramAttendScheduler.java +++ b/eeos/src/main/java/com/blackcompany/eeos/program/application/support/ProgramAttendScheduler.java @@ -1,6 +1,5 @@ package com.blackcompany.eeos.program.application.support; -import com.blackcompany.eeos.program.persistence.ProgramRepository; import com.blackcompany.eeos.program.persistence.RedisDelayedQueue; import com.blackcompany.eeos.target.application.event.EndAttendModeEvent; import java.util.Set; @@ -15,7 +14,6 @@ public class ProgramAttendScheduler { private final RedisDelayedQueue redisDelayedQueue; - private final ProgramRepository programRepository; private final ApplicationEventPublisher eventPublisher; @Transactional diff --git a/eeos/src/test/java/com/blackcompany/eeos/auth/application/service/ReissueServiceTest.java b/eeos/src/test/java/com/blackcompany/eeos/auth/application/service/ReissueServiceTest.java index d47bc445..efce893b 100644 --- a/eeos/src/test/java/com/blackcompany/eeos/auth/application/service/ReissueServiceTest.java +++ b/eeos/src/test/java/com/blackcompany/eeos/auth/application/service/ReissueServiceTest.java @@ -7,32 +7,34 @@ import com.blackcompany.eeos.auth.application.domain.token.TokenResolver; import com.blackcompany.eeos.auth.application.exception.InvalidTokenException; import com.blackcompany.eeos.auth.application.support.AuthenticationTokenGenerator; -import com.blackcompany.eeos.auth.persistence.BlackAuthenticationRepository; +import com.blackcompany.eeos.auth.persistence.InvalidTokenRepository; +import com.blackcompany.eeos.common.DataClearExtension; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; -import org.mockito.InjectMocks; -import org.mockito.Mock; -import org.mockito.junit.jupiter.MockitoExtension; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.boot.test.mock.mockito.SpyBean; -@ExtendWith(MockitoExtension.class) +@SpringBootTest +@ExtendWith(DataClearExtension.class) class ReissueServiceTest { - @Mock AuthenticationTokenGenerator authenticationTokenGenerator; - @Mock BlackAuthenticationRepository blackAuthenticationRepository; - - @Mock TokenResolver tokenResolver; - @InjectMocks ReissueService reissueService; + @SpyBean AuthenticationTokenGenerator authenticationTokenGenerator; + @Autowired InvalidTokenRepository invalidTokenRepository; + @MockBean TokenResolver tokenResolver; + @Autowired ReissueService reissueService; @Test @DisplayName("블랙리스트에 등록된 토큰이라면 예외가 발생한다.") void exception_when_token_invalid() { // given String token = "token"; - Long memberId = 1L; + Long memberId = 2L; + Long validTime = 1000L * 1; - when(tokenResolver.getUserDataByRefreshToken(token)).thenReturn(memberId); - when(blackAuthenticationRepository.isExistToken(token)).thenReturn(Boolean.TRUE); + invalidTokenRepository.save(token, memberId, validTime); // when & then assertThrows(InvalidTokenException.class, () -> reissueService.execute(token)); @@ -43,11 +45,10 @@ void exception_when_token_invalid() { void token_valid() { // given String token = "token"; - Long memberId = 1L; - Long validTime = 1L; + Long memberId = 2L; + Long validTime = 1000L * 1; when(tokenResolver.getUserDataByRefreshToken(token)).thenReturn(memberId); - when(blackAuthenticationRepository.isExistToken(token)).thenReturn(Boolean.FALSE); when(tokenResolver.getExpiredDateByRefreshToken(token)).thenReturn(validTime); // when @@ -55,7 +56,7 @@ void token_valid() { // then assertAll( - () -> verify(blackAuthenticationRepository).save(token, memberId, validTime), + () -> assertTrue(invalidTokenRepository.isExistToken(token)), () -> verify(authenticationTokenGenerator).execute(memberId)); } } diff --git a/eeos/src/test/java/com/blackcompany/eeos/common/DataClearExtension.java b/eeos/src/test/java/com/blackcompany/eeos/common/DataClearExtension.java index d657c828..46f55028 100644 --- a/eeos/src/test/java/com/blackcompany/eeos/common/DataClearExtension.java +++ b/eeos/src/test/java/com/blackcompany/eeos/common/DataClearExtension.java @@ -1,7 +1,10 @@ package com.blackcompany.eeos.common; +import java.util.ArrayList; +import java.util.List; import org.junit.jupiter.api.extension.BeforeEachCallback; import org.junit.jupiter.api.extension.ExtensionContext; +import org.springframework.context.ApplicationContext; import org.springframework.stereotype.Component; import org.springframework.test.context.junit.jupiter.SpringExtension; @@ -10,11 +13,15 @@ public class DataClearExtension implements BeforeEachCallback { @Override public void beforeEach(ExtensionContext context) { - DatabaseCleaner dataCleaner = getDataCleaner(context); - dataCleaner.clear(); + ApplicationContext appContext = SpringExtension.getApplicationContext(context); + List dataCleaners = getDataCleaners(appContext); + + for (DatabaseCleaner cleaner : dataCleaners) { + cleaner.clear(); + } } - private DatabaseCleaner getDataCleaner(final ExtensionContext extensionContext) { - return SpringExtension.getApplicationContext(extensionContext).getBean(DatabaseCleaner.class); + private List getDataCleaners(ApplicationContext appContext) { + return new ArrayList<>(appContext.getBeansOfType(DatabaseCleaner.class).values()); } } diff --git a/eeos/src/test/java/com/blackcompany/eeos/common/DatabaseCleaner.java b/eeos/src/test/java/com/blackcompany/eeos/common/DatabaseCleaner.java index 3c843297..8ab5e85f 100644 --- a/eeos/src/test/java/com/blackcompany/eeos/common/DatabaseCleaner.java +++ b/eeos/src/test/java/com/blackcompany/eeos/common/DatabaseCleaner.java @@ -1,47 +1,5 @@ package com.blackcompany.eeos.common; -import java.util.List; -import javax.persistence.EntityManager; -import javax.persistence.PersistenceContext; -import org.springframework.stereotype.Component; -import org.springframework.transaction.annotation.Transactional; - -@Component -public class DatabaseCleaner { - private static final String FOREIGN_KEY_CHECK_FORMAT = "SET FOREIGN_KEY_CHECKS = %d"; - private static final String TRUNCATE_FORMAT = "TRUNCATE TABLE %s"; - private static final String AUTO_INCREMENT_FORMAT = "ALTER TABLE %s AUTO_INCREMENT = 1"; - - @PersistenceContext private EntityManager entityManager; - - @Transactional - public void clear() { - disableForeignKeyChecks(); - List tableNames = getTableNames(); - truncate(tableNames); - enableForeignKeyChecks(); - } - - private void disableForeignKeyChecks() { - entityManager.createNativeQuery(String.format(FOREIGN_KEY_CHECK_FORMAT, 0)).executeUpdate(); - } - - private List getTableNames() { - String query = - "SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA = DATABASE()"; - return entityManager.createNativeQuery(query).getResultList(); - } - - private void enableForeignKeyChecks() { - entityManager.createNativeQuery(String.format(FOREIGN_KEY_CHECK_FORMAT, 1)).executeUpdate(); - } - - private void truncate(List tableNames) { - for (String tableName : tableNames) { - entityManager.createNativeQuery(String.format(TRUNCATE_FORMAT, tableName)).executeUpdate(); - entityManager - .createNativeQuery(String.format(AUTO_INCREMENT_FORMAT, tableName)) - .executeUpdate(); - } - } +public interface DatabaseCleaner { + void clear(); } diff --git a/eeos/src/test/java/com/blackcompany/eeos/common/MySqlDatabaseCleaner.java b/eeos/src/test/java/com/blackcompany/eeos/common/MySqlDatabaseCleaner.java new file mode 100644 index 00000000..820f090b --- /dev/null +++ b/eeos/src/test/java/com/blackcompany/eeos/common/MySqlDatabaseCleaner.java @@ -0,0 +1,48 @@ +package com.blackcompany.eeos.common; + +import java.util.List; +import javax.persistence.EntityManager; +import javax.persistence.PersistenceContext; +import org.springframework.stereotype.Component; +import org.springframework.transaction.annotation.Transactional; + +@Component +public class MySqlDatabaseCleaner implements DatabaseCleaner { + private static final String FOREIGN_KEY_CHECK_FORMAT = "SET FOREIGN_KEY_CHECKS = %d"; + private static final String TRUNCATE_FORMAT = "TRUNCATE TABLE %s"; + private static final String AUTO_INCREMENT_FORMAT = "ALTER TABLE %s AUTO_INCREMENT = 1"; + + @PersistenceContext private EntityManager entityManager; + + @Override + @Transactional + public void clear() { + disableForeignKeyChecks(); + List tableNames = getTableNames(); + truncate(tableNames); + enableForeignKeyChecks(); + } + + private void disableForeignKeyChecks() { + entityManager.createNativeQuery(String.format(FOREIGN_KEY_CHECK_FORMAT, 0)).executeUpdate(); + } + + private List getTableNames() { + String query = + "SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA = DATABASE()"; + return entityManager.createNativeQuery(query).getResultList(); + } + + private void enableForeignKeyChecks() { + entityManager.createNativeQuery(String.format(FOREIGN_KEY_CHECK_FORMAT, 1)).executeUpdate(); + } + + private void truncate(List tableNames) { + for (String tableName : tableNames) { + entityManager.createNativeQuery(String.format(TRUNCATE_FORMAT, tableName)).executeUpdate(); + entityManager + .createNativeQuery(String.format(AUTO_INCREMENT_FORMAT, tableName)) + .executeUpdate(); + } + } +} diff --git a/eeos/src/test/java/com/blackcompany/eeos/common/RedisDatabaseCleaner.java b/eeos/src/test/java/com/blackcompany/eeos/common/RedisDatabaseCleaner.java new file mode 100644 index 00000000..3d6b23a2 --- /dev/null +++ b/eeos/src/test/java/com/blackcompany/eeos/common/RedisDatabaseCleaner.java @@ -0,0 +1,24 @@ +package com.blackcompany.eeos.common; + +import java.util.Set; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.stereotype.Component; + +@Component +public class RedisDatabaseCleaner implements DatabaseCleaner { + + private final RedisTemplate redisTemplate; + + public RedisDatabaseCleaner(RedisTemplate redisTemplate) { + this.redisTemplate = redisTemplate; + } + + @Override + public void clear() { + Set keys = redisTemplate.keys("*"); + + if (keys != null && !keys.isEmpty()) { + redisTemplate.delete(keys); + } + } +} diff --git a/eeos/src/test/java/com/blackcompany/eeos/study/redis/RedisTransactionTest.java b/eeos/src/test/java/com/blackcompany/eeos/study/redis/RedisTransactionTest.java new file mode 100644 index 00000000..2855de03 --- /dev/null +++ b/eeos/src/test/java/com/blackcompany/eeos/study/redis/RedisTransactionTest.java @@ -0,0 +1,52 @@ +package com.blackcompany.eeos.study.redis; + +import static org.junit.jupiter.api.Assertions.assertNull; +import static org.junit.jupiter.api.Assertions.assertTrue; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Tag; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.dao.DataAccessException; +import org.springframework.data.redis.core.RedisOperations; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.data.redis.core.SessionCallback; + +@SpringBootTest +@Tag("learning-test") +class RedisTransactionTest { + + @Autowired private RedisTemplate redisTemplate; + + @Autowired private TransactionalService transactionalService; + + @BeforeEach + void setup() { + redisTemplate.opsForValue().set("testKey", "testValue"); + } + + @Test + void redisTransactionInRedisTemplate() { + boolean existsInTransactional = transactionalService.checkKey("testKey"); + assertTrue(existsInTransactional); + } + + @Test + void redisTransactionInSessionCallback() { + redisTemplate.execute( + new SessionCallback() { + @Override + public Object execute(RedisOperations operations) throws DataAccessException { + operations.multi(); + Boolean beforeExec = operations.hasKey("testKey"); + assertNull(beforeExec); + operations.exec(); + + Boolean afterExec = operations.hasKey("testKey"); + assertTrue(afterExec); + return null; + } + }); + } +} diff --git a/eeos/src/test/java/com/blackcompany/eeos/study/redis/TransactionalService.java b/eeos/src/test/java/com/blackcompany/eeos/study/redis/TransactionalService.java new file mode 100644 index 00000000..35bb7038 --- /dev/null +++ b/eeos/src/test/java/com/blackcompany/eeos/study/redis/TransactionalService.java @@ -0,0 +1,21 @@ +package com.blackcompany.eeos.study.redis; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +@Service +public class TransactionalService { + private final RedisTemplate redisTemplate; + + @Autowired + public TransactionalService(RedisTemplate redisTemplate) { + this.redisTemplate = redisTemplate; + } + + @Transactional + public Boolean checkKey(String key) { + return redisTemplate.hasKey(key); + } +}