Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[BE] 테스트 데이터 클리너 구현 #199

Merged
merged 4 commits into from
Aug 5, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

c: 다음과 같이 truncateTablesQuery를 미리 저장해 놓는 방식으로 해 봐도 좋을 것 같아요

@PostConstruct
    public void getTableNames() {
        String sql = """
                SELECT TABLE_NAME
                FROM INFORMATION_SCHEMA.TABLES
                WHERE TABLE_SCHEMA = 'PUBLIC'
                """;
        List<String> tableNames = em.createNativeQuery(sql).getResultList();
        StringBuilder stringBuilder = new StringBuilder();

        for (String tableName : tableNames) {
            String truncateQuery = String.format(TRUNCATE_FORMAT, tableName);
            stringBuilder.append(truncateQuery);
        }
        truncateTablesQuery = stringBuilder.toString();
    }

    private void truncate() {
        em.createNativeQuery(String.format(REFERENTIAL_FORMAT, false)).executeUpdate();
        em.createNativeQuery(truncateTablesQuery).executeUpdate();
        em.createNativeQuery(String.format(REFERENTIAL_FORMAT, true)).executeUpdate();
    }

실행 결과
image

Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
package server.haengdong.support.extension;

import jakarta.persistence.EntityManager;
import jakarta.persistence.PersistenceContext;
import java.util.List;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

@Component
class DatabaseCleaner {

@PersistenceContext
private EntityManager em;

@Transactional
public void clear() {
em.clear();
truncate();
}

private void truncate() {
em.createNativeQuery("SET REFERENTIAL_INTEGRITY FALSE").executeUpdate();
getTruncateQueries().forEach(query -> em.createNativeQuery(query).executeUpdate());
em.createNativeQuery("SET REFERENTIAL_INTEGRITY TRUE").executeUpdate();
}

private List<String> getTruncateQueries() {
String sql = """
SELECT Concat('TRUNCATE TABLE ', TABLE_NAME, ' RESTART IDENTITY', ';') AS q
FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_SCHEMA = 'PUBLIC'
""";

return em.createNativeQuery(sql).getResultList();
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

r: clear 를 한번 할 때마다 truncate 쿼리문 생성 쿼리를 날릴 필요는 없을 것 같아요.

Copy link
Contributor

@Arachneee Arachneee Aug 4, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
@Transactional
public void clear() {
em.clear();
truncate();
}
private void truncate() {
em.createNativeQuery("SET REFERENTIAL_INTEGRITY FALSE").executeUpdate();
getTruncateQueries().forEach(query -> em.createNativeQuery(query).executeUpdate());
em.createNativeQuery("SET REFERENTIAL_INTEGRITY TRUE").executeUpdate();
}
private List<String> getTruncateQueries() {
String sql = """
SELECT Concat('TRUNCATE TABLE ', TABLE_NAME, ' RESTART IDENTITY', ';') AS q
FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_SCHEMA = 'PUBLIC'
""";
return em.createNativeQuery(sql).getResultList();
}
private List<String> tableNames;
@PostConstruct
public void getTableNames() {
String sql = """
SELECT TABLE_NAME
FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_SCHEMA = 'PUBLIC'
""";
tableNames = em.createNativeQuery(sql).getResultList();
}
@Transactional
public void clear() {
em.clear();
truncate();
}
private void truncate() {
em.createNativeQuery("SET REFERENTIAL_INTEGRITY FALSE").executeUpdate();
tableNames.forEach(tableName -> em.createNativeQuery("TRUNCATE TABLE " + tableName + "RESTART IDENTITY;").executeUpdate());
em.createNativeQuery("SET REFERENTIAL_INTEGRITY TRUE").executeUpdate();
}

개행이 조금 이상한데 이런 방식으로 빈 등록 후 한번만 날려도 될 것 같습니다.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

r: 쿼리문을 상수로 선언해놓고 재사용 하는 것이 좋을 것 같습니다.
그리고 MySQL 기준 테이블 truncate 하면 auto_increment가 초기화되기 때문에 restart identity 지워도 되겠네요.

static final String referentialFormat = "SET REFERENTIAL_INTEGRITY %b;";
static final String truncateFormat = "TRUNCATE TABLE %s;"

// ... 

private void truncate() {
    em.createNativeQuery(String.format(referentialFormat, false)).executeUpdate();
    tableNames.forEach(tableName -> em.createNativeQuery(String.format(truncateForamt, tableName)).executeUpdate());
    em.createNativeQuery(String.format(referentialFormat, true)).executeUpdate();
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package server.haengdong.support.extension;

import org.junit.jupiter.api.extension.AfterEachCallback;
import org.junit.jupiter.api.extension.ExtensionContext;
import org.springframework.test.context.junit.jupiter.SpringExtension;

public class DatabaseCleanerExtension implements AfterEachCallback {

@Override
public void afterEach(ExtensionContext context) {
DatabaseCleaner databaseCleaner = getDataCleaner(context);
databaseCleaner.clear();
}

private DatabaseCleaner getDataCleaner(ExtensionContext extensionContext) {
return SpringExtension.getApplicationContext(extensionContext)
.getBean(DatabaseCleaner.class);
}
}
Loading