NoSql인 MongoDB가 Transaction을 지원하지만,
방대한 데이터를 다루는 NoSql에서는 Transaction과 같은 고비용 처리 사용을 지양한다.
그럼에도 불구하고, Test code에서 MongoDB Transaction을 Rollback하기 위해
@Transactional Annotation 사용하려고 시도 했던 것을 정리
Test code에 바로 @Transactional Annotaiton을 작성했을 때 오류가 발생함
@Test @Transactional public void test1() throws Exception{ // ...something }
java.lang.IllegalStateException: Failed to retrieve PlatformTransactionManager for @Transactional test
- Spring에서 MongoDB Transaction을 사용하기 위해서는 Configuration을 추가해 줘야함
@Configuration public class MongoTransactionConfig { @Bean public MongoTransactionManager transactionManager(MongoDatabaseFactory mongoDatabaseFactory) { return new MongoTransactionManager(mongoDatabaseFactory); } }
org.springframework.dao.InvalidDataAccessApiUsageException: Query failed with error code 20 and error message 'Transaction numbers are only allowed on a replica set member or mongos' on server dev-mongodb-ip:27017; nested exception is com.mongodb.MongoQueryException: Query failed with error code 20 and error message 'Transaction numbers are only allowed on a replica set member or mongos' on server dev-mongodb-ip:27017
- MongoDB Transaction을 사용하기 위해서는 MongoDB Replica set 구성을 해야만 한다.
├── js
│ └── dbUserCreate.js
│── scripts
│ ├── mongoCreateUser.sh
│ └── rs-init.sh
├── replicaset
│ ├── rs01a
│ ├── rs01p
│ └── rs01s
├── .env
├── docker-compose.yml
└── restart-mongodb-replica.sh
- .env
MONGODB_VERSION=5.0.18
- docker-compose.yml
version: '3.8' services: rs01p: image: mongo:${MONGODB_VERSION} container_name: rs01p ports: - 10021:10021 volumes: - ./replicaset/rs01p:/data/db - ./scripts:/scripts - ./js:/js command: - '--port' - '10021' - '--replSet' - 'rs01' - '--bind_ip_all' rs01s: image: mongo:${MONGODB_VERSION} container_name: rs01s ports: - 10022:10022 volumes: - ./replicaset/rs01s:/data/db command: - '--port' - '10022' - '--replSet' - 'rs01' - '--bind_ip_all' rs01a: image: mongo:${MONGODB_VERSION} container_name: rs01a ports: - 10023:10023 volumes: - ./replicaset/rs01a:/data/db command: - '--port' - '10023' - '--replSet' - 'rs01' - '--bind_ip_all'
- rs-init.sh
- replicaset 설정 진행
mongo --port 10021 <<EOF use databaseName; var config = { "_id": "rs01", "version": 1, "members": [ { "_id": 1, "host": "rs01p:10021", "priority": 2 }, { "_id": 2, "host": "rs01s022", "priority": 1 }, { "_id": 3, "host": "rs01a:10023", "priority": 0 } ] }; rs.initiate(config); rs.status(); db.setProfilingLevel(2); db.getProfilingStatus(); EOF
- mongoCreateUser.sh
- DB User 데이터 생성
use databaseName
을 통해 사용할 DB 선택mongo --port 10021 <<EOF use databaseName; db.createUser({ user: "mongo", pwd: "mongo123", roles: [ { role: "dbOwner", db: "databaseName", }, ], }); db.getUsers(); EOF
./restart-mongodb.sh
쉘 입력DATA_FILE_PATH="./replicaset"
DOCKER_FILE_PATH="./docker-compose.yml"
MONGO_PRIMARY_NAME="rs01p"
REPLICA_INIT_FILE_PATH="/scripts/rs-init.sh"
MONGO_CREATE_USER_FILE_PATH="/scripts/mongoCreateUser.sh"
UP_CONTAINER_DELAY=10
REPLICA_CONFIG_DELAY=25
SHARD_CONFIG_DELAY=60
echo "****************** Reset docker container Shell Script ******************"
echo "Data File Path: ${DATA_FILE_PATH}"
echo "Docker File Path: ${DOCKER_FILE_PATH}"
echo "MongoDB Primary name: ${MONGO_PRIMARY_NAME}"
echo "Replica set init Script File Path: ${REPLICA_INIT_FILE_PATH}"
sleep 1;
echo "****************** Stop docker container ******************"
docker-compose -f ${DOCKER_FILE_PATH} stop
echo "****************** Completed Stop docker container ******************"
sleep 1;
echo "****************** Down docker container ******************"
docker-compose -f ${DOCKER_FILE_PATH} down
echo "****************** Completed Down docker container ******************"
sleep 1;
echo "****************** Remove Data ******************"
rm -rf ${DATA_FILE_PATH}
echo "****************** Completed Remove Data ******************"
sleep 1;
echo "****************** Up docker container ******************"
docker-compose -f ${DOCKER_FILE_PATH} up -d
echo "****************** Completed Up docker container ******************"
echo "****** Waiting for ${UP_CONTAINER_DELAY} seconds ******"
sleep $UP_CONTAINER_DELAY;
echo "****************** Run Replica Set Shell Script ******************"
docker exec -it ${MONGO_PRIMARY_NAME} bash -c "${REPLICA_INIT_FILE_PATH}"
echo "****** Waiting for ${REPLICA_CONFIG_DELAY} seconds for replicaset configuration to be applied ******"
sleep $REPLICA_CONFIG_DELAY
echo "****************** Run Create DB User Shell Script ******************"
docker exec -it ${MONGO_PRIMARY_NAME} bash -c "${MONGO_CREATE_USER_FILE_PATH}"
echo "****************** Completed Replica Shell Script ******************"
Configuration
+Replica set
구성을 통해
Test Code에서 @Transactional Annotation 사용 가능