-
Notifications
You must be signed in to change notification settings - Fork 0
[Database] 쿼리 자동생성 기능 개발 #63
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
Changes from 5 commits
fa6dd03
263a851
c7fe85f
f297129
7264806
f1a1895
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,28 @@ | ||
| package config; | ||
|
|
||
| import app.model.User; | ||
| import java.util.List; | ||
|
|
||
| public class DatabaseConfig { | ||
| private final AppConfig appConfig = new AppConfig(); | ||
|
|
||
| public static final List<Class<?>> ENTITY_CLASSES = List.of( | ||
| User.class | ||
| ); | ||
|
|
||
| public static final List<String> RESOLVED_WORD = List.of( | ||
| "user" | ||
| ); | ||
|
|
||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 하드코딩된 환경 설정: 데이터베이스 URL, 사용자명이 소스 코드에 하드코딩되어 있습니다. 운영 환경마다 다른 DB 주소를 사용해야 하므로 환경 변수나 설정 파일에서 읽도록 변경하세요. 특히 파일 시스템 절대 경로( |
||
| public static final String H2_DB_URL = "jdbc:h2:tcp://localhost//Users/apple/h2/testdb"; | ||
| public static final String H2_DB_USER = "sa"; | ||
| public static final String H2_DB_PASSWORD = ""; | ||
|
|
||
| public static final boolean CREATE_TABLES = false; | ||
| public static final boolean DROP_IF_EXISTS = false; | ||
|
|
||
| public void config(){ | ||
| DdlGenerator ddlGenerator = appConfig.ddlGenerator(); | ||
| if(CREATE_TABLES) ddlGenerator.generateTables(); | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,111 @@ | ||
| package config; | ||
|
|
||
| import database.ConnectionManager; | ||
| import org.slf4j.Logger; | ||
| import org.slf4j.LoggerFactory; | ||
|
|
||
| import java.lang.reflect.Field; | ||
| import java.lang.reflect.Modifier; | ||
| import java.sql.Connection; | ||
| import java.sql.SQLException; | ||
| import java.sql.Statement; | ||
| import java.time.LocalDateTime; | ||
| import java.util.List; | ||
|
|
||
| public class DdlGenerator { | ||
| private static final Logger log = LoggerFactory.getLogger(DdlGenerator.class); | ||
| private final List<String> resolvedWord = DatabaseConfig.RESOLVED_WORD; | ||
| private final ConnectionManager connectionManager; | ||
| private final boolean dropIfExists = DatabaseConfig.DROP_IF_EXISTS; | ||
| private final List<Class<?>> entityClasses = DatabaseConfig.ENTITY_CLASSES; | ||
|
|
||
| public DdlGenerator(ConnectionManager connectionManager) { | ||
| this.connectionManager = connectionManager; | ||
| } | ||
|
|
||
| public void generateTables() { | ||
| try (Connection conn = connectionManager.getConnection(); | ||
| Statement stmt = conn.createStatement()) { | ||
|
|
||
| for (Class<?> entityClass : entityClasses) { | ||
| String tableName = toTableName(entityClass); | ||
| String ddl = buildDdlForEntity(entityClass, tableName); | ||
| log.info("DDL for {}:\n{}", tableName, ddl); | ||
| stmt.execute(ddl); | ||
| } | ||
|
|
||
|
Comment on lines
+31
to
+36
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. SQL 인젝션 취약점: |
||
| } catch (SQLException e) { | ||
| throw new RuntimeException("DDL 생성/실행 중 오류", e); | ||
| } | ||
|
Comment on lines
+37
to
+39
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 예외 처리 미흡: |
||
| } | ||
|
|
||
| private String buildDdlForEntity(Class<?> entityClass, String tableName) { | ||
| StringBuilder ddl = new StringBuilder(); | ||
|
|
||
| if (dropIfExists) { | ||
| ddl.append("DROP TABLE IF EXISTS ").append(tableName).append(";\n"); | ||
| } | ||
|
|
||
| ddl.append("CREATE TABLE ").append(tableName).append(" (\n"); | ||
|
|
||
| Field[] fields = entityClass.getDeclaredFields(); | ||
|
|
||
| boolean firstColumn = true; | ||
|
|
||
| for (Field field : fields) { | ||
| if (Modifier.isStatic(field.getModifiers())) { | ||
| continue; | ||
| } | ||
|
|
||
| String columnName = field.getName(); | ||
| Class<?> fieldType = field.getType(); | ||
|
|
||
| if (!firstColumn) { | ||
| ddl.append(",\n"); | ||
| } | ||
| firstColumn = false; | ||
|
|
||
| if ("id".equals(columnName) && (fieldType == Long.class || fieldType == long.class)) { | ||
| ddl.append(" id BIGINT AUTO_INCREMENT PRIMARY KEY"); | ||
| } else { | ||
| String sqlType = toSqlType(fieldType); | ||
| ddl.append(" ").append(columnName).append(" ").append(sqlType); | ||
| } | ||
| } | ||
|
|
||
| ddl.append("\n);"); | ||
|
|
||
| return ddl.toString(); | ||
| } | ||
|
|
||
| private String toSqlType(Class<?> fieldType) { | ||
| if (fieldType == Long.class || fieldType == long.class) { | ||
| return "BIGINT"; | ||
| } else if (fieldType == Integer.class || fieldType == int.class) { | ||
| return "INT"; | ||
| } else if (fieldType == String.class) { | ||
| return "VARCHAR(255)"; | ||
| } else if (fieldType == Boolean.class || fieldType == boolean.class) { | ||
| return "BOOLEAN"; | ||
| } else if (fieldType == LocalDateTime.class || | ||
| fieldType == java.util.Date.class || | ||
| fieldType == java.sql.Timestamp.class) { | ||
| return "TIMESTAMP"; | ||
| } else if (fieldType == Double.class || fieldType == double.class) { | ||
| return "DOUBLE"; | ||
| } else if (fieldType == Float.class || fieldType == float.class) { | ||
| return "FLOAT"; | ||
| } | ||
| return "VARCHAR(255)"; | ||
| } | ||
|
|
||
| private String toTableName(Class<?> clazz) { | ||
| String name = clazz.getSimpleName().toLowerCase(); | ||
|
|
||
| for(String word : resolvedWord){ | ||
| if(word.equals(name)) | ||
| return "`" + word + "`"; | ||
| } | ||
| return name; | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,7 @@ | ||
| package database; | ||
|
|
||
| import java.sql.Connection; | ||
|
|
||
| public interface ConnectionManager { | ||
| Connection getConnection(); | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
AppConfig 불필요한 인스턴스화:
DatabaseConfig에서new AppConfig()를 생성하면 AppConfig의 싱글톤 인스턴스들이 다시 만들어질 가능성이 있습니다. WebServer에서 이미 만든 AppConfig 인스턴스를 주입받도록 리팩토링하세요.