From 948f8722bc75da5728bae05703ea5766ed51142d Mon Sep 17 00:00:00 2001 From: socar-shinyoung Date: Sun, 10 Mar 2024 22:42:29 +0900 Subject: [PATCH 1/4] =?UTF-8?q?fix:=20code=20review=20=EB=B0=98=EC=98=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - QueryTranslator 역할 분리 - 1차적으로는 역할별로 분리하고 위임 --- .../java/persistence/sql/QueryTranslator.java | 223 ++++-------------- .../persistence/sql/ddl/ColumnTranslator.java | 95 ++++++++ .../sql/ddl/CreateQueryTranslator.java | 21 ++ .../sql/ddl/DropQueryTranslator.java | 16 ++ .../persistence/sql/ddl/TableTranslator.java | 53 +++++ .../strategy/DefaultConstraintsStrategy.java | 2 +- .../sql/dml/DeleteQueryTranslator.java | 47 ++++ .../sql/dml/InsertQueryTranslator.java | 30 +++ .../sql/dml/SelectQueryTranslator.java | 40 ++++ .../sql/ddl/query/QueryTranslator1Test.java | 2 +- .../sql/ddl/query/QueryTranslator2Test.java | 2 +- .../sql/ddl/query/QueryTranslator3Test.java | 2 +- .../sql/ddl/query/QueryTranslatorTest.java | 2 +- 13 files changed, 347 insertions(+), 188 deletions(-) create mode 100644 src/main/java/persistence/sql/ddl/ColumnTranslator.java create mode 100644 src/main/java/persistence/sql/ddl/CreateQueryTranslator.java create mode 100644 src/main/java/persistence/sql/ddl/DropQueryTranslator.java create mode 100644 src/main/java/persistence/sql/ddl/TableTranslator.java create mode 100644 src/main/java/persistence/sql/dml/DeleteQueryTranslator.java create mode 100644 src/main/java/persistence/sql/dml/InsertQueryTranslator.java create mode 100644 src/main/java/persistence/sql/dml/SelectQueryTranslator.java diff --git a/src/main/java/persistence/sql/QueryTranslator.java b/src/main/java/persistence/sql/QueryTranslator.java index 0c04686f9..7ec563f71 100644 --- a/src/main/java/persistence/sql/QueryTranslator.java +++ b/src/main/java/persistence/sql/QueryTranslator.java @@ -1,229 +1,86 @@ package persistence.sql; -import static persistence.sql.ddl.common.StringConstants.COLUMN_DEFINITION_DELIMITER; -import static persistence.sql.ddl.common.StringConstants.SCHEMA_TABLE_DELIMITER; -import jakarta.persistence.Column; -import jakarta.persistence.Id; -import jakarta.persistence.Table; -import jakarta.persistence.Transient; import java.lang.reflect.Field; -import java.util.Arrays; -import java.util.Comparator; -import java.util.stream.Collectors; -import java.util.stream.Stream; -import persistence.sql.ddl.common.StringConstants; -import persistence.sql.ddl.constraints.strategy.ConstraintsStrategy; -import persistence.sql.ddl.constraints.strategy.DefaultConstraintsStrategy; -import persistence.sql.ddl.type.DataTypeMapping; -import persistence.sql.ddl.type.impl.DefaultDataTypeMapping; +import persistence.sql.ddl.ColumnTranslator; +import persistence.sql.ddl.CreateQueryTranslator; +import persistence.sql.ddl.DropQueryTranslator; +import persistence.sql.ddl.TableTranslator; import persistence.sql.dml.ColumnValueTranslator; +import persistence.sql.dml.DeleteQueryTranslator; +import persistence.sql.dml.InsertQueryTranslator; +import persistence.sql.dml.SelectQueryTranslator; public class QueryTranslator { - protected final ConstraintsStrategy constraintsStrategy; + private final TableTranslator tableTranslator = new TableTranslator(); - protected final DataTypeMapping dataTypeMapping; + private final ColumnTranslator columnTranslator = new ColumnTranslator(); - protected final ColumnValueTranslator columnValueTranslator; + private final ColumnValueTranslator columnValueTranslator = new ColumnValueTranslator(); - public QueryTranslator() { - this( - new DefaultConstraintsStrategy(), - new DefaultDataTypeMapping(), - new ColumnValueTranslator() - ); - } + private final SelectQueryTranslator selectQueryTranslator; + + private final DeleteQueryTranslator deleteQueryTranslator; + + private final InsertQueryTranslator insertQueryTranslator; + + private final DropQueryTranslator dropQueryTranslator; - protected QueryTranslator( - ConstraintsStrategy constraintsStrategy, - DataTypeMapping dataTypeMapping, - ColumnValueTranslator columnValueTranslator - ) { - this.constraintsStrategy = constraintsStrategy; - this.dataTypeMapping = dataTypeMapping; - this.columnValueTranslator = columnValueTranslator; + private final CreateQueryTranslator createQueryTranslator; + + public QueryTranslator() { + this.selectQueryTranslator = new SelectQueryTranslator(columnTranslator, + columnValueTranslator, tableTranslator); + this.deleteQueryTranslator = new DeleteQueryTranslator(columnTranslator, + columnValueTranslator, tableTranslator); + this.insertQueryTranslator = new InsertQueryTranslator(columnTranslator, + columnValueTranslator, tableTranslator); + this.dropQueryTranslator = new DropQueryTranslator(tableTranslator); + this.createQueryTranslator = new CreateQueryTranslator(columnTranslator, tableTranslator); } public String getCreateTableQuery(final Class entityClass) { - return String.format( - "CREATE TABLE %s (%s)", - getTableNameFrom(entityClass), - getTableColumnDefinitionFrom(entityClass) - ); + return createQueryTranslator.getCreateTableQuery(entityClass); } public String getDropTableQuery(Class entityClass) { - return String.format( - "DROP TABLE %s", - getTableNameFrom(entityClass) - ); + return dropQueryTranslator.getDropTableQuery(entityClass); } public String getInsertQuery(Object entity) { - Class entityClass = entity.getClass(); - - return String.format( - "INSERT INTO %s (%s) VALUES (%s)", - getTableNameFrom(entityClass), - getColumnNamesClauseWithoutPrimaryKey(entityClass), - getColumnValueClause(entity) - ); + return insertQueryTranslator.getInsertQuery(entity); } public String getSelectAllQuery(Class entityClass) { - return String.format( - "SELECT %s FROM %s", - getColumnNamesClause(entityClass), - getTableNameFrom(entityClass) - ); + return selectQueryTranslator.getSelectAllQuery(entityClass); } public String getSelectByIdQuery(Class entityClass, Object id) { - return String.format( - "SELECT %s FROM %s WHERE %s = %s", - getColumnNamesClause(entityClass), - getTableNameFrom(entityClass), - getPrimaryKeyColumnName(entityClass), - columnValueTranslator.getPrimaryKeyValueClauseFromEntityClassAndId(entityClass, id) - ); + return selectQueryTranslator.getSelectByIdQuery(entityClass, id); } public String getDeleteAllQuery(Class entityClass) { - return String.format( - "DELETE FROM %s", - getTableNameFrom(entityClass) - ); + return deleteQueryTranslator.getDeleteAllQuery(entityClass); } public String getDeleteByIdQuery(Class entityClass, Object id) { - return String.format( - "DELETE FROM %s WHERE %s = %s", - getTableNameFrom(entityClass), - getPrimaryKeyColumnName(entityClass), - columnValueTranslator.getPrimaryKeyValueClauseFromEntityClassAndId(entityClass, id) - ); + return deleteQueryTranslator.getDeleteByIdQuery(entityClass, id); } public String getDeleteQueryFromEntity(Class entityClass, Object entity) { - return String.format( - "DELETE FROM %s WHERE %s = %s", - getTableNameFrom(entityClass), - getPrimaryKeyColumnName(entityClass), - columnValueTranslator.getPrimaryKeyValueClauseFromEntityClassAndEntityObject(entityClass, entity) - ); - } - - - private String getPrimaryKeyColumnName(Class entityClass) { - return Arrays.stream(entityClass.getDeclaredFields()) - .filter(field -> field.isAnnotationPresent(Id.class)) - .findFirst() - .map(this::getColumnNameFrom) - .orElseThrow(() -> new IllegalStateException("Primary key not found")); + return deleteQueryTranslator.getDeleteQueryFromEntity(entityClass, entity); } public String getTableNameFrom(Class entityClass) { - return Stream.of( - getSchemaNameFrom(entityClass), - getOnlyTableNameFrom(entityClass) - ) - .filter(s -> !s.isBlank()) - .collect(Collectors.joining(SCHEMA_TABLE_DELIMITER)); - } - - public String getTableColumnDefinitionFrom(Class entityClass) { - return getColumnFieldStream(entityClass) - .map(this::getColumnDefinitionFrom) - .collect(Collectors.joining(COLUMN_DEFINITION_DELIMITER)); + return tableTranslator.getTableNameFrom(entityClass); } public String getColumnDefinitionFrom(Field field) { - return Stream.of( - getColumnNameFrom(field), - getColumnDataTypeDefinitionFrom(field), - getColumnConstraintsFrom(field) - ) - .filter(s -> !s.isBlank()) - .collect(Collectors.joining(" ")); - } - - public String getColumnNameFrom(Field field) { - if (!field.isAnnotationPresent(Column.class)) { - return field.getName(); - } - - Column column = field.getAnnotation(Column.class); - - if (column.name().isEmpty()) { - return field.getName(); - } - - return column.name(); + return columnTranslator.getColumnDefinitionFrom(field); } - public String getColumnDataTypeDefinitionFrom(Field field) { - return dataTypeMapping.getDataTypeDefinitionFrom(field); - } - - public String getColumnConstraintsFrom(Field field) { - return constraintsStrategy.getConstraintsFrom(field); - } - - public String getColumnValueClause(Object entity) { - return columnValueTranslator.getColumnValueClause(entity); - } - - protected String getColumnNamesClause(Class entityClass) { - return getColumnFieldStream(entityClass) - .map(this::getColumnNameFrom) - .collect(Collectors.joining(COLUMN_DEFINITION_DELIMITER)); - } - - protected String getColumnNamesClauseWithoutPrimaryKey(Class entityClass) { - return getColumnFieldStream(entityClass) - .filter(field -> !field.isAnnotationPresent(Id.class)) - .map(this::getColumnNameFrom) - .collect(Collectors.joining(COLUMN_DEFINITION_DELIMITER)); - } - - protected static Stream getColumnFieldStream(Class entityClass) { - return Arrays.stream(entityClass.getDeclaredFields()) - .filter(field -> !field.isAnnotationPresent(Transient.class)) - .sorted(Comparator.comparing(field -> field.isAnnotationPresent(Id.class) ? 0 : 1)); - } - - protected String getOnlyTableNameFrom(final Class entityClass) { - if (entityClass.isAnnotationPresent(Table.class)) { - Table table = entityClass.getAnnotation(Table.class); - return getOnlyTableNameFrom(table); - } - - return entityClass.getSimpleName(); - } - - protected String getOnlyTableNameFrom(Table table) { - if (!table.name().isEmpty()) { - return table.name(); - } - - return StringConstants.EMPTY_STRING; - } - - protected String getSchemaNameFrom(Class entityClass) { - if (entityClass.isAnnotationPresent(Table.class)) { - Table table = entityClass.getAnnotation(Table.class); - return getSchemaNameFrom(table); - } - - return StringConstants.EMPTY_STRING; - } - - protected String getSchemaNameFrom(Table table) { - if (!table.schema().isEmpty()) { - return table.schema(); - } - - return StringConstants.EMPTY_STRING; + public String getColumnDefinitionsFrom(Class entityClass) { + return columnTranslator.getColumnDefinitionsFrom(entityClass); } } diff --git a/src/main/java/persistence/sql/ddl/ColumnTranslator.java b/src/main/java/persistence/sql/ddl/ColumnTranslator.java new file mode 100644 index 000000000..b4b8b65ca --- /dev/null +++ b/src/main/java/persistence/sql/ddl/ColumnTranslator.java @@ -0,0 +1,95 @@ +package persistence.sql.ddl; + +import static persistence.sql.ddl.common.StringConstants.COLUMN_DEFINITION_DELIMITER; + +import jakarta.persistence.Column; +import jakarta.persistence.Id; +import jakarta.persistence.Transient; +import java.lang.reflect.Field; +import java.util.Arrays; +import java.util.Comparator; +import java.util.stream.Collectors; +import java.util.stream.Stream; +import persistence.sql.ddl.constraints.strategy.ConstraintsStrategy; +import persistence.sql.ddl.constraints.strategy.DefaultConstraintsStrategy; +import persistence.sql.ddl.type.DataTypeMapping; +import persistence.sql.ddl.type.impl.DefaultDataTypeMapping; + +public class ColumnTranslator { + + private final ConstraintsStrategy constraintsStrategy; + + private final DataTypeMapping dataTypeMapping; + + public ColumnTranslator() { + this( + new DefaultConstraintsStrategy(), + new DefaultDataTypeMapping() + ); + } + + public ColumnTranslator( + ConstraintsStrategy constraintsStrategy, + DataTypeMapping dataTypeMapping + ) { + this.constraintsStrategy = constraintsStrategy; + this.dataTypeMapping = dataTypeMapping; + } + + public String getColumnDefinitionsFrom(Class entityClass) { + return getColumnFieldStream(entityClass) + .map(this::getColumnDefinitionFrom) + .collect(Collectors.joining(COLUMN_DEFINITION_DELIMITER)); + } + + public String getColumnDefinitionFrom(Field field) { + return Stream.of( + getColumnNameFrom(field), + dataTypeMapping.getDataTypeDefinitionFrom(field), + constraintsStrategy.getConstraintsFrom(field) + ) + .filter(s -> !s.isBlank()) + .collect(Collectors.joining(" ")); + } + + public String getColumnNameFrom(Field field) { + if (!field.isAnnotationPresent(Column.class)) { + return field.getName(); + } + + Column column = field.getAnnotation(Column.class); + + if (column.name().isEmpty()) { + return field.getName(); + } + + return column.name(); + } + + public String getPrimaryKeyColumnName(Class entityClass) { + return Arrays.stream(entityClass.getDeclaredFields()) + .filter(field -> field.isAnnotationPresent(Id.class)) + .findFirst() + .map(this::getColumnNameFrom) + .orElseThrow(() -> new IllegalStateException("Primary key not found")); + } + + public String getColumnNamesClauseWithoutPrimaryKey(Class entityClass) { + return getColumnFieldStream(entityClass) + .filter(field -> !field.isAnnotationPresent(Id.class)) + .map(this::getColumnNameFrom) + .collect(Collectors.joining(COLUMN_DEFINITION_DELIMITER)); + } + + public String getColumnNamesClause(Class entityClass) { + return getColumnFieldStream(entityClass) + .map(this::getColumnNameFrom) + .collect(Collectors.joining(COLUMN_DEFINITION_DELIMITER)); + } + + protected static Stream getColumnFieldStream(Class entityClass) { + return Arrays.stream(entityClass.getDeclaredFields()) + .filter(field -> !field.isAnnotationPresent(Transient.class)) + .sorted(Comparator.comparing(field -> field.isAnnotationPresent(Id.class) ? 0 : 1)); + } +} diff --git a/src/main/java/persistence/sql/ddl/CreateQueryTranslator.java b/src/main/java/persistence/sql/ddl/CreateQueryTranslator.java new file mode 100644 index 000000000..a81165004 --- /dev/null +++ b/src/main/java/persistence/sql/ddl/CreateQueryTranslator.java @@ -0,0 +1,21 @@ +package persistence.sql.ddl; + +public class CreateQueryTranslator { + private final ColumnTranslator columnTranslator; + + private final TableTranslator tableTranslator; + + public CreateQueryTranslator(ColumnTranslator columnTranslator, + TableTranslator tableTranslator) { + this.columnTranslator = columnTranslator; + this.tableTranslator = tableTranslator; + } + + public String getCreateTableQuery(final Class entityClass) { + return String.format( + "CREATE TABLE %s (%s)", + tableTranslator.getTableNameFrom(entityClass), + columnTranslator.getColumnDefinitionsFrom(entityClass) + ); + } +} diff --git a/src/main/java/persistence/sql/ddl/DropQueryTranslator.java b/src/main/java/persistence/sql/ddl/DropQueryTranslator.java new file mode 100644 index 000000000..35762e84f --- /dev/null +++ b/src/main/java/persistence/sql/ddl/DropQueryTranslator.java @@ -0,0 +1,16 @@ +package persistence.sql.ddl; + +public class DropQueryTranslator { + private final TableTranslator tableTranslator; + + public DropQueryTranslator(TableTranslator tableTranslator) { + this.tableTranslator = tableTranslator; + } + + public String getDropTableQuery(Class entityClass) { + return String.format( + "DROP TABLE %s", + tableTranslator.getTableNameFrom(entityClass) + ); + } +} diff --git a/src/main/java/persistence/sql/ddl/TableTranslator.java b/src/main/java/persistence/sql/ddl/TableTranslator.java new file mode 100644 index 000000000..2004c85c2 --- /dev/null +++ b/src/main/java/persistence/sql/ddl/TableTranslator.java @@ -0,0 +1,53 @@ +package persistence.sql.ddl; + +import static persistence.sql.ddl.common.StringConstants.SCHEMA_TABLE_DELIMITER; + +import jakarta.persistence.Table; +import java.util.stream.Collectors; +import java.util.stream.Stream; +import persistence.sql.ddl.common.StringConstants; + +public class TableTranslator { + public String getTableNameFrom(Class entityClass) { + return Stream.of( + getSchemaNameFrom(entityClass), + getOnlyTableNameFrom(entityClass) + ) + .filter(s -> !s.isBlank()) + .collect(Collectors.joining(SCHEMA_TABLE_DELIMITER)); + } + + public String getSchemaNameFrom(Class entityClass) { + if (entityClass.isAnnotationPresent(Table.class)) { + Table table = entityClass.getAnnotation(Table.class); + return getSchemaNameFrom(table); + } + + return StringConstants.EMPTY_STRING; + } + + public String getSchemaNameFrom(Table table) { + if (!table.schema().isEmpty()) { + return table.schema(); + } + + return StringConstants.EMPTY_STRING; + } + + public String getOnlyTableNameFrom(final Class entityClass) { + if (entityClass.isAnnotationPresent(Table.class)) { + Table table = entityClass.getAnnotation(Table.class); + return getOnlyTableNameFrom(table); + } + + return entityClass.getSimpleName(); + } + + public String getOnlyTableNameFrom(Table table) { + if (!table.name().isEmpty()) { + return table.name(); + } + + return StringConstants.EMPTY_STRING; + } +} diff --git a/src/main/java/persistence/sql/ddl/constraints/strategy/DefaultConstraintsStrategy.java b/src/main/java/persistence/sql/ddl/constraints/strategy/DefaultConstraintsStrategy.java index 711fcce92..9feeb29a0 100644 --- a/src/main/java/persistence/sql/ddl/constraints/strategy/DefaultConstraintsStrategy.java +++ b/src/main/java/persistence/sql/ddl/constraints/strategy/DefaultConstraintsStrategy.java @@ -4,8 +4,8 @@ import java.util.List; import java.util.stream.Collectors; import persistence.sql.ddl.common.StringConstants; -import persistence.sql.ddl.constraints.impl.AutoIncrementConstraintsTranslator; import persistence.sql.ddl.constraints.ConstraintsTranslator; +import persistence.sql.ddl.constraints.impl.AutoIncrementConstraintsTranslator; import persistence.sql.ddl.constraints.impl.NotNullConstraintsTranslator; import persistence.sql.ddl.constraints.impl.UniqueConstraintsTranslator; diff --git a/src/main/java/persistence/sql/dml/DeleteQueryTranslator.java b/src/main/java/persistence/sql/dml/DeleteQueryTranslator.java new file mode 100644 index 000000000..c7cca2387 --- /dev/null +++ b/src/main/java/persistence/sql/dml/DeleteQueryTranslator.java @@ -0,0 +1,47 @@ +package persistence.sql.dml; + +import persistence.sql.ddl.ColumnTranslator; +import persistence.sql.ddl.TableTranslator; + +public class DeleteQueryTranslator { + private final ColumnTranslator columnTranslator; + + private final ColumnValueTranslator columnValueTranslator; + + private final TableTranslator tableTranslator; + + public DeleteQueryTranslator( + ColumnTranslator columnTranslator, + ColumnValueTranslator columnValueTranslator, + TableTranslator tableTranslator + ) { + this.columnTranslator = columnTranslator; + this.columnValueTranslator = columnValueTranslator; + this.tableTranslator = tableTranslator; + } + + public String getDeleteAllQuery(Class entityClass) { + return String.format( + "DELETE FROM %s", + tableTranslator.getTableNameFrom(entityClass) + ); + } + + public String getDeleteByIdQuery(Class entityClass, Object id) { + return String.format( + "DELETE FROM %s WHERE %s = %s", + tableTranslator.getTableNameFrom(entityClass), + columnTranslator.getPrimaryKeyColumnName(entityClass), + columnValueTranslator.getPrimaryKeyValueClauseFromEntityClassAndId(entityClass, id) + ); + } + + public String getDeleteQueryFromEntity(Class entityClass, Object entity) { + return String.format( + "DELETE FROM %s WHERE %s = %s", + tableTranslator.getTableNameFrom(entityClass), + columnTranslator.getPrimaryKeyColumnName(entityClass), + columnValueTranslator.getPrimaryKeyValueClauseFromEntityClassAndEntityObject(entityClass, entity) + ); + } +} diff --git a/src/main/java/persistence/sql/dml/InsertQueryTranslator.java b/src/main/java/persistence/sql/dml/InsertQueryTranslator.java new file mode 100644 index 000000000..f87ca5fa9 --- /dev/null +++ b/src/main/java/persistence/sql/dml/InsertQueryTranslator.java @@ -0,0 +1,30 @@ +package persistence.sql.dml; + +import persistence.sql.ddl.ColumnTranslator; +import persistence.sql.ddl.TableTranslator; + +public class InsertQueryTranslator { + private final ColumnTranslator columnTranslator; + + private final ColumnValueTranslator columnValueTranslator; + + private final TableTranslator tableTranslator; + + public InsertQueryTranslator(ColumnTranslator columnTranslator, + ColumnValueTranslator columnValueTranslator, TableTranslator tableTranslator) { + this.columnTranslator = columnTranslator; + this.columnValueTranslator = columnValueTranslator; + this.tableTranslator = tableTranslator; + } + + public String getInsertQuery(Object entity) { + Class entityClass = entity.getClass(); + + return String.format( + "INSERT INTO %s (%s) VALUES (%s)", + tableTranslator.getTableNameFrom(entityClass), + columnTranslator.getColumnNamesClauseWithoutPrimaryKey(entityClass), + columnValueTranslator.getColumnValueClause(entity) + ); + } +} diff --git a/src/main/java/persistence/sql/dml/SelectQueryTranslator.java b/src/main/java/persistence/sql/dml/SelectQueryTranslator.java new file mode 100644 index 000000000..6ad764e1d --- /dev/null +++ b/src/main/java/persistence/sql/dml/SelectQueryTranslator.java @@ -0,0 +1,40 @@ +package persistence.sql.dml; + +import persistence.sql.ddl.ColumnTranslator; +import persistence.sql.ddl.TableTranslator; + +public class SelectQueryTranslator { + private final ColumnTranslator columnTranslator; + + private final ColumnValueTranslator columnValueTranslator; + + private final TableTranslator tableTranslator; + + public SelectQueryTranslator( + ColumnTranslator columnTranslator, + ColumnValueTranslator columnValueTranslator, + TableTranslator tableTranslator + ) { + this.columnTranslator = columnTranslator; + this.columnValueTranslator = columnValueTranslator; + this.tableTranslator = tableTranslator; + } + + public String getSelectAllQuery(Class entityClass) { + return String.format( + "SELECT %s FROM %s", + columnTranslator.getColumnNamesClause(entityClass), + tableTranslator.getTableNameFrom(entityClass) + ); + } + + public String getSelectByIdQuery(Class entityClass, Object id) { + return String.format( + "SELECT %s FROM %s WHERE %s = %s", + columnTranslator.getColumnNamesClause(entityClass), + tableTranslator.getTableNameFrom(entityClass), + columnTranslator.getPrimaryKeyColumnName(entityClass), + columnValueTranslator.getPrimaryKeyValueClauseFromEntityClassAndId(entityClass, id) + ); + } +} diff --git a/src/test/java/persistence/sql/ddl/query/QueryTranslator1Test.java b/src/test/java/persistence/sql/ddl/query/QueryTranslator1Test.java index 69b0525b8..0d449a3f0 100644 --- a/src/test/java/persistence/sql/ddl/query/QueryTranslator1Test.java +++ b/src/test/java/persistence/sql/ddl/query/QueryTranslator1Test.java @@ -54,7 +54,7 @@ void getTableNameByClassName() { @Test @DisplayName("클래스 정보를 바탕으로 컬럼 선언문 가져오기") void getColumnDefinitionStatement() { - String columnDefinitionStatement = queryTranslator.getTableColumnDefinitionFrom(entityClass); + String columnDefinitionStatement = queryTranslator.getColumnDefinitionsFrom(entityClass); log.debug("Column definition statement: {}", columnDefinitionStatement); diff --git a/src/test/java/persistence/sql/ddl/query/QueryTranslator2Test.java b/src/test/java/persistence/sql/ddl/query/QueryTranslator2Test.java index eb8d8c4b3..54d26ee24 100644 --- a/src/test/java/persistence/sql/ddl/query/QueryTranslator2Test.java +++ b/src/test/java/persistence/sql/ddl/query/QueryTranslator2Test.java @@ -54,7 +54,7 @@ void getTableNameByClassName() { @Test @DisplayName("클래스 정보와 @Id, @Column 어노테이션을 바탕으로 컬럼 선언문 가져오기") void getColumnDefinitionStatement() { - String columnDefinitionStatement = queryTranslator.getTableColumnDefinitionFrom(entityClass); + String columnDefinitionStatement = queryTranslator.getColumnDefinitionsFrom(entityClass); log.debug("Column definition statement: {}", columnDefinitionStatement); diff --git a/src/test/java/persistence/sql/ddl/query/QueryTranslator3Test.java b/src/test/java/persistence/sql/ddl/query/QueryTranslator3Test.java index 2c58a341f..16f8eadfa 100644 --- a/src/test/java/persistence/sql/ddl/query/QueryTranslator3Test.java +++ b/src/test/java/persistence/sql/ddl/query/QueryTranslator3Test.java @@ -54,7 +54,7 @@ void getTableNameByClassName() { @Test @DisplayName("클래스 정보와 @Id, @Column, @Transient 어노테이션을 바탕으로 컬럼 선언문 가져오기") void getColumnDefinitionStatement() { - String columnDefinitionStatement = queryTranslator.getTableColumnDefinitionFrom(entityClass); + String columnDefinitionStatement = queryTranslator.getColumnDefinitionsFrom(entityClass); log.debug("Column definition statement: {}", columnDefinitionStatement); diff --git a/src/test/java/persistence/sql/ddl/query/QueryTranslatorTest.java b/src/test/java/persistence/sql/ddl/query/QueryTranslatorTest.java index ce7307826..b84341db2 100644 --- a/src/test/java/persistence/sql/ddl/query/QueryTranslatorTest.java +++ b/src/test/java/persistence/sql/ddl/query/QueryTranslatorTest.java @@ -84,7 +84,7 @@ void getTableNameWithSchema() { @Test @DisplayName("클래스 정보와 @Id, @Column, @Transient 어노테이션을 바탕으로 컬럼 선언문 가져오기") void getColumnDefinitionStatement() { - String columnDefinitionStatement = queryTranslator.getTableColumnDefinitionFrom(entityClass); + String columnDefinitionStatement = queryTranslator.getColumnDefinitionsFrom(entityClass); log.debug("Column definition statement: {}", columnDefinitionStatement); From b71fc0d536eecb0b9fbbb604bec18a2a6341f33d Mon Sep 17 00:00:00 2001 From: socar-shinyoung Date: Mon, 11 Mar 2024 00:18:19 +0900 Subject: [PATCH 2/4] =?UTF-8?q?feat:=204=EB=8B=A8=EA=B3=84=20-=20Simple=20?= =?UTF-8?q?Entity=20Object?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 요구사항1 - find - 요구사항2 - persist (insert) - 요구사항3 - remove (delete) --- src/main/java/jdbc/RowMapper.java | 3 +- .../persistence/entity/EntityManager.java | 29 ++++ .../entity/EntityRowMapperFactory.java | 50 ++++++ .../entity/impl/EntityManagerImpl.java | 48 ++++++ .../exception/ReflectionRuntimeException.java | 7 + .../exception/UnsupportedClassException.java | 2 +- .../UnsupportedFieldException.java | 2 +- .../java/persistence/sql/QueryTranslator.java | 8 +- .../persistence/sql/ddl/ColumnTranslator.java | 2 +- .../AutoIncrementConstraintsTranslator.java | 2 +- .../impl/NotNullConstraintsTranslator.java | 2 +- .../impl/UniqueConstraintsTranslator.java | 2 +- .../persistence/sql/ddl/entity/Person.java | 42 ++++- .../sql/dml/ColumnValueTranslator.java | 2 +- .../sql/dml/DeleteQueryTranslator.java | 6 +- .../sql/dml/SelectQueryTranslator.java | 8 + .../entity/impl/EntityManagerImplTest.java | 155 ++++++++++++++++++ .../sql/ddl/query/QueryTranslatorTest.java | 16 +- 18 files changed, 369 insertions(+), 17 deletions(-) create mode 100644 src/main/java/persistence/entity/EntityManager.java create mode 100644 src/main/java/persistence/entity/EntityRowMapperFactory.java create mode 100644 src/main/java/persistence/entity/impl/EntityManagerImpl.java create mode 100644 src/main/java/persistence/exception/ReflectionRuntimeException.java rename src/main/java/persistence/{sql => }/exception/UnsupportedClassException.java (84%) rename src/main/java/persistence/{sql/exception/constraints => exception}/UnsupportedFieldException.java (82%) create mode 100644 src/test/java/persistence/entity/impl/EntityManagerImplTest.java diff --git a/src/main/java/jdbc/RowMapper.java b/src/main/java/jdbc/RowMapper.java index 1dd7310c0..c44445bf2 100644 --- a/src/main/java/jdbc/RowMapper.java +++ b/src/main/java/jdbc/RowMapper.java @@ -5,5 +5,6 @@ @FunctionalInterface public interface RowMapper { - T mapRow(final ResultSet resultSet) throws SQLException; + T mapRow(final ResultSet resultSet) + throws SQLException, InstantiationException, IllegalAccessException; } diff --git a/src/main/java/persistence/entity/EntityManager.java b/src/main/java/persistence/entity/EntityManager.java new file mode 100644 index 000000000..7f57775b0 --- /dev/null +++ b/src/main/java/persistence/entity/EntityManager.java @@ -0,0 +1,29 @@ +package persistence.entity; + +public interface EntityManager { + /** + * Finds an entity by its id + * + * @param entityClass the entity class + * @param id the id of the entity + * @return the entity + * + * @param the entity type + */ + T find(Class entityClass, Long id); + + /** + * Persists the entity object + * + * @param entity entity object to persist + * @return the persisted entity object + */ + Object persist(Object entity); + + /** + * Removes the entity object + * + * @param entity entity object to remove + */ + void remove(Object entity); +} diff --git a/src/main/java/persistence/entity/EntityRowMapperFactory.java b/src/main/java/persistence/entity/EntityRowMapperFactory.java new file mode 100644 index 000000000..54f46a6c9 --- /dev/null +++ b/src/main/java/persistence/entity/EntityRowMapperFactory.java @@ -0,0 +1,50 @@ +package persistence.entity; + +import java.lang.reflect.Constructor; +import java.lang.reflect.Field; +import java.lang.reflect.InvocationTargetException; +import java.util.List; +import java.util.stream.Collectors; +import jdbc.RowMapper; +import persistence.exception.ReflectionRuntimeException; +import persistence.sql.ddl.ColumnTranslator; + +public class EntityRowMapperFactory { + + private EntityRowMapperFactory() { + // Do nothing + } + + public static class LazyLoadEntityRowMapperFactory { + private static final EntityRowMapperFactory INSTANCE = new EntityRowMapperFactory(); + } + + public static EntityRowMapperFactory getInstance() { + return LazyLoadEntityRowMapperFactory.INSTANCE; + } + + public RowMapper getRowMapper(Class entityClass) { + return resultSet -> { + try { + ColumnTranslator columnTranslator = new ColumnTranslator(); + Constructor declaredConstructor = entityClass.getDeclaredConstructor(); + declaredConstructor.setAccessible(true); + T entity = entityClass.getDeclaredConstructor().newInstance(); + + List columnFieldList = columnTranslator.getColumnFieldStream(entityClass) + .collect(Collectors.toList()); + + for (Field field : columnFieldList) { + field.setAccessible(true); + String columnName = columnTranslator.getColumnNameFrom(field); + field.set(entity, resultSet.getObject(columnName)); + } + + return entity; + } catch (InstantiationException | IllegalAccessException | NoSuchMethodException | + InvocationTargetException e) { + throw new ReflectionRuntimeException(entityClass, e); + } + }; + } +} diff --git a/src/main/java/persistence/entity/impl/EntityManagerImpl.java b/src/main/java/persistence/entity/impl/EntityManagerImpl.java new file mode 100644 index 000000000..2d65fe5cd --- /dev/null +++ b/src/main/java/persistence/entity/impl/EntityManagerImpl.java @@ -0,0 +1,48 @@ +package persistence.entity.impl; + +import jdbc.JdbcTemplate; +import persistence.entity.EntityManager; +import persistence.entity.EntityRowMapperFactory; +import persistence.sql.QueryTranslator; + +public class EntityManagerImpl implements EntityManager { + private final JdbcTemplate jdbcTemplate; + + private final QueryTranslator queryTranslator; + + public EntityManagerImpl(JdbcTemplate jdbcTemplate) { + this(jdbcTemplate, new QueryTranslator()); + } + + public EntityManagerImpl(JdbcTemplate jdbcTemplate, QueryTranslator queryTranslator) { + this.jdbcTemplate = jdbcTemplate; + this.queryTranslator = queryTranslator; + } + + + @Override + public T find(Class entityClass, Long id) { + String selectByIdQuery = queryTranslator.getSelectByIdQuery(entityClass, id); + + return jdbcTemplate.queryForObject( + selectByIdQuery, + EntityRowMapperFactory.getInstance().getRowMapper(entityClass) + ); + } + + @Override + public Object persist(Object entity) { + String insertQuery = queryTranslator.getInsertQuery(entity); + + jdbcTemplate.execute(insertQuery); + + return entity; + } + + @Override + public void remove(Object entity) { + String deleteQueryFromEntity = queryTranslator.getDeleteQueryFromEntity(entity); + + jdbcTemplate.execute(deleteQueryFromEntity); + } +} diff --git a/src/main/java/persistence/exception/ReflectionRuntimeException.java b/src/main/java/persistence/exception/ReflectionRuntimeException.java new file mode 100644 index 000000000..5ef8b726c --- /dev/null +++ b/src/main/java/persistence/exception/ReflectionRuntimeException.java @@ -0,0 +1,7 @@ +package persistence.exception; + +public class ReflectionRuntimeException extends RuntimeException { + public ReflectionRuntimeException(Class clazz, Exception e) { + super("Reflection error on class: " + clazz.getName(), e); + } +} diff --git a/src/main/java/persistence/sql/exception/UnsupportedClassException.java b/src/main/java/persistence/exception/UnsupportedClassException.java similarity index 84% rename from src/main/java/persistence/sql/exception/UnsupportedClassException.java rename to src/main/java/persistence/exception/UnsupportedClassException.java index b4b143027..2d5bc48e3 100644 --- a/src/main/java/persistence/sql/exception/UnsupportedClassException.java +++ b/src/main/java/persistence/exception/UnsupportedClassException.java @@ -1,4 +1,4 @@ -package persistence.sql.exception; +package persistence.exception; public class UnsupportedClassException extends RuntimeException { diff --git a/src/main/java/persistence/sql/exception/constraints/UnsupportedFieldException.java b/src/main/java/persistence/exception/UnsupportedFieldException.java similarity index 82% rename from src/main/java/persistence/sql/exception/constraints/UnsupportedFieldException.java rename to src/main/java/persistence/exception/UnsupportedFieldException.java index f252d1ac6..7ab2fd96a 100644 --- a/src/main/java/persistence/sql/exception/constraints/UnsupportedFieldException.java +++ b/src/main/java/persistence/exception/UnsupportedFieldException.java @@ -1,4 +1,4 @@ -package persistence.sql.exception.constraints; +package persistence.exception; import java.lang.reflect.Field; diff --git a/src/main/java/persistence/sql/QueryTranslator.java b/src/main/java/persistence/sql/QueryTranslator.java index 7ec563f71..27cea114a 100644 --- a/src/main/java/persistence/sql/QueryTranslator.java +++ b/src/main/java/persistence/sql/QueryTranslator.java @@ -60,6 +60,10 @@ public String getSelectByIdQuery(Class entityClass, Object id) { return selectQueryTranslator.getSelectByIdQuery(entityClass, id); } + public String getSelectCountQuery(Class entityClass) { + return selectQueryTranslator.getSelectCountQuery(entityClass); + } + public String getDeleteAllQuery(Class entityClass) { return deleteQueryTranslator.getDeleteAllQuery(entityClass); } @@ -68,8 +72,8 @@ public String getDeleteByIdQuery(Class entityClass, Object id) { return deleteQueryTranslator.getDeleteByIdQuery(entityClass, id); } - public String getDeleteQueryFromEntity(Class entityClass, Object entity) { - return deleteQueryTranslator.getDeleteQueryFromEntity(entityClass, entity); + public String getDeleteQueryFromEntity(Object entity) { + return deleteQueryTranslator.getDeleteQueryFromEntity(entity); } public String getTableNameFrom(Class entityClass) { diff --git a/src/main/java/persistence/sql/ddl/ColumnTranslator.java b/src/main/java/persistence/sql/ddl/ColumnTranslator.java index b4b8b65ca..458f8629c 100644 --- a/src/main/java/persistence/sql/ddl/ColumnTranslator.java +++ b/src/main/java/persistence/sql/ddl/ColumnTranslator.java @@ -87,7 +87,7 @@ public String getColumnNamesClause(Class entityClass) { .collect(Collectors.joining(COLUMN_DEFINITION_DELIMITER)); } - protected static Stream getColumnFieldStream(Class entityClass) { + public Stream getColumnFieldStream(Class entityClass) { return Arrays.stream(entityClass.getDeclaredFields()) .filter(field -> !field.isAnnotationPresent(Transient.class)) .sorted(Comparator.comparing(field -> field.isAnnotationPresent(Id.class) ? 0 : 1)); diff --git a/src/main/java/persistence/sql/ddl/constraints/impl/AutoIncrementConstraintsTranslator.java b/src/main/java/persistence/sql/ddl/constraints/impl/AutoIncrementConstraintsTranslator.java index 5ebc1055d..58d454e88 100644 --- a/src/main/java/persistence/sql/ddl/constraints/impl/AutoIncrementConstraintsTranslator.java +++ b/src/main/java/persistence/sql/ddl/constraints/impl/AutoIncrementConstraintsTranslator.java @@ -3,7 +3,7 @@ import jakarta.persistence.Id; import java.lang.reflect.Field; import persistence.sql.ddl.constraints.ConstraintsTranslator; -import persistence.sql.exception.constraints.UnsupportedFieldException; +import persistence.exception.UnsupportedFieldException; public class AutoIncrementConstraintsTranslator implements ConstraintsTranslator { private static final String AUTO_INCREMENT = "AUTO_INCREMENT"; diff --git a/src/main/java/persistence/sql/ddl/constraints/impl/NotNullConstraintsTranslator.java b/src/main/java/persistence/sql/ddl/constraints/impl/NotNullConstraintsTranslator.java index e3ae8b5d1..772a24a6b 100644 --- a/src/main/java/persistence/sql/ddl/constraints/impl/NotNullConstraintsTranslator.java +++ b/src/main/java/persistence/sql/ddl/constraints/impl/NotNullConstraintsTranslator.java @@ -4,7 +4,7 @@ import java.lang.reflect.Field; import persistence.sql.ddl.common.StringConstants; import persistence.sql.ddl.constraints.ConstraintsTranslator; -import persistence.sql.exception.constraints.UnsupportedFieldException; +import persistence.exception.UnsupportedFieldException; public class NotNullConstraintsTranslator implements ConstraintsTranslator { diff --git a/src/main/java/persistence/sql/ddl/constraints/impl/UniqueConstraintsTranslator.java b/src/main/java/persistence/sql/ddl/constraints/impl/UniqueConstraintsTranslator.java index 14560f459..51933066c 100644 --- a/src/main/java/persistence/sql/ddl/constraints/impl/UniqueConstraintsTranslator.java +++ b/src/main/java/persistence/sql/ddl/constraints/impl/UniqueConstraintsTranslator.java @@ -4,7 +4,7 @@ import java.lang.reflect.Field; import persistence.sql.ddl.common.StringConstants; import persistence.sql.ddl.constraints.ConstraintsTranslator; -import persistence.sql.exception.constraints.UnsupportedFieldException; +import persistence.exception.UnsupportedFieldException; public class UniqueConstraintsTranslator implements ConstraintsTranslator { diff --git a/src/main/java/persistence/sql/ddl/entity/Person.java b/src/main/java/persistence/sql/ddl/entity/Person.java index e491b06d6..7c214d134 100644 --- a/src/main/java/persistence/sql/ddl/entity/Person.java +++ b/src/main/java/persistence/sql/ddl/entity/Person.java @@ -7,6 +7,7 @@ import jakarta.persistence.Id; import jakarta.persistence.Table; import jakarta.persistence.Transient; +import java.util.Objects; @Table(name = "users") @Entity @@ -27,7 +28,7 @@ public class Person { @Transient private Integer index; - protected Person() { + public Person() { } @@ -44,6 +45,26 @@ public Person(Long id, String name, Integer age, String email) { this.email = email; } + public Long getId() { + return id; + } + + public String getName() { + return name; + } + + public Integer getAge() { + return age; + } + + public String getEmail() { + return email; + } + + public Integer getIndex() { + return index; + } + @Override public String toString() { return "Person{" + @@ -53,4 +74,23 @@ public String toString() { ", email='" + email + '\'' + '}'; } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + Person person = (Person) o; + return Objects.equals(id, person.id) && Objects.equals(name, person.name) + && Objects.equals(age, person.age) && Objects.equals(email, + person.email); + } + + @Override + public int hashCode() { + return Objects.hash(id, name, age, email); + } } diff --git a/src/main/java/persistence/sql/dml/ColumnValueTranslator.java b/src/main/java/persistence/sql/dml/ColumnValueTranslator.java index c3a7f58a2..14d1661b1 100644 --- a/src/main/java/persistence/sql/dml/ColumnValueTranslator.java +++ b/src/main/java/persistence/sql/dml/ColumnValueTranslator.java @@ -8,7 +8,7 @@ import java.util.Arrays; import java.util.Comparator; import java.util.stream.Collectors; -import persistence.sql.exception.UnsupportedClassException; +import persistence.exception.UnsupportedClassException; public class ColumnValueTranslator { diff --git a/src/main/java/persistence/sql/dml/DeleteQueryTranslator.java b/src/main/java/persistence/sql/dml/DeleteQueryTranslator.java index c7cca2387..7942db943 100644 --- a/src/main/java/persistence/sql/dml/DeleteQueryTranslator.java +++ b/src/main/java/persistence/sql/dml/DeleteQueryTranslator.java @@ -36,7 +36,11 @@ public String getDeleteByIdQuery(Class entityClass, Object id) { ); } - public String getDeleteQueryFromEntity(Class entityClass, Object entity) { + public String getDeleteQueryFromEntity(Object entity) { + return getDeleteQueryFromEntity(entity.getClass(), entity); + } + + private String getDeleteQueryFromEntity(Class entityClass, Object entity) { return String.format( "DELETE FROM %s WHERE %s = %s", tableTranslator.getTableNameFrom(entityClass), diff --git a/src/main/java/persistence/sql/dml/SelectQueryTranslator.java b/src/main/java/persistence/sql/dml/SelectQueryTranslator.java index 6ad764e1d..54146d292 100644 --- a/src/main/java/persistence/sql/dml/SelectQueryTranslator.java +++ b/src/main/java/persistence/sql/dml/SelectQueryTranslator.java @@ -37,4 +37,12 @@ public String getSelectByIdQuery(Class entityClass, Object id) { columnValueTranslator.getPrimaryKeyValueClauseFromEntityClassAndId(entityClass, id) ); } + + public String getSelectCountQuery(Class entityClass) { + return String.format( + "SELECT COUNT(%s) FROM %s", + columnTranslator.getPrimaryKeyColumnName(entityClass), + tableTranslator.getTableNameFrom(entityClass) + ); + } } diff --git a/src/test/java/persistence/entity/impl/EntityManagerImplTest.java b/src/test/java/persistence/entity/impl/EntityManagerImplTest.java new file mode 100644 index 000000000..7a7f99091 --- /dev/null +++ b/src/test/java/persistence/entity/impl/EntityManagerImplTest.java @@ -0,0 +1,155 @@ +package persistence.entity.impl; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatExceptionOfType; +import static org.junit.jupiter.api.Assertions.assertAll; + +import database.DatabaseServer; +import database.H2; +import java.sql.SQLException; +import java.util.Map; +import java.util.function.Function; +import java.util.stream.Collectors; +import java.util.stream.Stream; +import jdbc.JdbcTemplate; +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; +import org.junit.jupiter.params.provider.ValueSource; +import persistence.entity.EntityManager; +import persistence.sql.QueryTranslator; +import persistence.sql.ddl.entity.Person; + +class EntityManagerImplTest { + private static DatabaseServer server; + + private EntityManager entityManager; + + private final static Map idToPersonMap = Stream.of( + new Person(1L, "root", 20, "root@gmail.com"), + new Person(2L, "test", 30, "test@gmail.com"), + new Person(3L, "user1", 40, "user1@gmail.com"), + new Person(4L, "user2", 50, "user2@gmail.com") + ).collect(Collectors.toMap(Person::getId, Function.identity())); + + @BeforeAll + static void beforeAll() throws SQLException { + server = new H2(); + server.start(); + } + + @AfterAll + static void afterAll() { + server.stop(); + } + + @BeforeEach + void setUp() throws SQLException { + JdbcTemplate jdbcTemplate = getJdbcTemplate(); + + entityManager = new EntityManagerImpl(jdbcTemplate); + + QueryTranslator queryTranslator = new QueryTranslator(); + + jdbcTemplate.execute(queryTranslator.getCreateTableQuery(Person.class)); + } + + @AfterEach + void tearDown() throws SQLException { + dropTable(); + } + + private static JdbcTemplate getJdbcTemplate() throws SQLException { + return new JdbcTemplate(server.getConnection()); + } + + private static Stream providePerson() { + return idToPersonMap.values().stream() + .map(Arguments::of); + } + + @DisplayName("요구사항1 - find 메서드를 통해 id에 해당하는 Person 레코드를 조회할 수 있다.") + @ParameterizedTest(name = "id: {0}") + @ValueSource(longs = {1, 2, 3, 4}) + void find(Long id) throws SQLException { + // given + initializeTable(); + Person givenPerson = idToPersonMap.get(id); + + // when + Person entity = entityManager.find(Person.class, id); + + // then + assertAll( + () -> assertThat(entity).isNotNull(), + () -> assertThat(entity).isEqualTo(givenPerson) + ); + } + + @DisplayName("요구사항2 - persist (insert) 메서드를 통해 Entity를 저장할 수 있다.") + @Test + void persist() { + // given + Person person = new Person("test", 20, "test@gmail.com"); + + // when + Object savedEntity = entityManager.persist(person); + + // then + assertThat(savedEntity).isEqualTo(person); + } + + @DisplayName("요구사항3 - remove (delete) 메서드를 통해 특정 Entity를 삭제할 수 있다.") + @ParameterizedTest(name = "person: {0}") + @MethodSource("providePerson") + void remove(Person givenPerson) throws SQLException { + // given + initializeTable(); + Long id = givenPerson.getId(); + + // when + entityManager.remove(givenPerson); + + // then + assertThatExceptionOfType(RuntimeException.class) + .isThrownBy(() -> + entityManager.find(Person.class, id) + ); + + Integer totalCountOfEntity = selectCountOfTable(); + assertThat(totalCountOfEntity).isEqualTo(idToPersonMap.size() - 1); + } + + private void initializeTable() throws SQLException { + JdbcTemplate jdbcTemplate = getJdbcTemplate(); + + QueryTranslator queryTranslator = new QueryTranslator(); + + for (Person person : idToPersonMap.values()) { + jdbcTemplate.execute(queryTranslator.getInsertQuery(person)); + } + } + + private void dropTable() throws SQLException { + JdbcTemplate jdbcTemplate = getJdbcTemplate(); + + QueryTranslator queryTranslator = new QueryTranslator(); + + jdbcTemplate.execute(queryTranslator.getDropTableQuery(Person.class)); + } + + private Integer selectCountOfTable() throws SQLException { + JdbcTemplate jdbcTemplate = getJdbcTemplate(); + + QueryTranslator queryTranslator = new QueryTranslator(); + + return jdbcTemplate.queryForObject(queryTranslator.getSelectCountQuery(Person.class), + resultSet -> resultSet.getInt(1)); + } +} diff --git a/src/test/java/persistence/sql/ddl/query/QueryTranslatorTest.java b/src/test/java/persistence/sql/ddl/query/QueryTranslatorTest.java index b84341db2..0698b0693 100644 --- a/src/test/java/persistence/sql/ddl/query/QueryTranslatorTest.java +++ b/src/test/java/persistence/sql/ddl/query/QueryTranslatorTest.java @@ -139,6 +139,16 @@ void getSelectByIdQuery() { assertThat(selectByIdQuery).isEqualTo("SELECT id, nick_name, old, email FROM users WHERE id = 1"); } + @Test + @DisplayName("요구사항 3 - 위의 정보를 바탕으로 count 쿼리 만들어보기") + void getSelectCountQuery() { + // when + String selectCountQuery = queryTranslator.getSelectCountQuery(Person.class); + + // then + assertThat(selectCountQuery).isEqualTo("SELECT COUNT(id) FROM users"); + } + @Test @DisplayName("요구사항 4 - 위의 정보를 바탕으로 delete 쿼리 만들어보기") void getDeleteAllQuery() { @@ -149,15 +159,11 @@ void getDeleteAllQuery() { // when String deleteAllQuery = queryTranslator.getDeleteAllQuery(Person.class); String deleteByIdQuery = queryTranslator.getDeleteByIdQuery(Person.class, givenId); - String deleteQueryFromEntity = queryTranslator.getDeleteQueryFromEntity( - Person.class, - givenEntity - ); + String deleteQueryFromEntity = queryTranslator.getDeleteQueryFromEntity(givenEntity); // then assertThat(deleteAllQuery).isEqualTo("DELETE FROM users"); assertThat(deleteByIdQuery).isEqualTo("DELETE FROM users WHERE id = 1"); assertThat(deleteQueryFromEntity).isEqualTo("DELETE FROM users WHERE id = 1"); - } } From ec75f607dd6e64aedf773baa9df5051874e30d1b Mon Sep 17 00:00:00 2001 From: socar-shinyoung Date: Mon, 11 Mar 2024 22:53:54 +0900 Subject: [PATCH 3/4] =?UTF-8?q?fix:=20code-review=20=EB=B0=98=EC=98=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 역할 분리... (솔직히 어떤게 좋을지 잘 모르겠습니다.) - 괜찮은 구조있다면, 공유해주세요~ --- src/main/java/persistence/Application.java | 26 ++--- .../entity/EntityRowMapperFactory.java | 16 ++-- .../entity/impl/EntityManagerImpl.java | 12 +-- .../sql/AbstractQueryTranslator.java | 70 ++++++++++++++ .../java/persistence/sql/QueryTranslator.java | 56 +++++------ .../sql/ddl/ColumnQueryTranslator.java | 32 +++++++ .../persistence/sql/ddl/ColumnTranslator.java | 95 ------------------- .../sql/ddl/CreateQueryTranslator.java | 60 ++++++++++-- .../sql/ddl/DropQueryTranslator.java | 8 +- ...Translator.java => TableQueryBuilder.java} | 2 +- .../sql/ddl/common/StringConstants.java | 2 + .../sql/dml/ColumnValueTranslator.java | 81 ---------------- .../sql/dml/DeleteQueryTranslator.java | 75 +++++++++++---- .../sql/dml/InsertQueryTranslator.java | 59 +++++++++--- .../sql/dml/SelectQueryTranslator.java | 68 +++++++++---- .../entity/impl/EntityManagerImplTest.java | 16 ++-- ...lator1Test.java => QueryBuilder1Test.java} | 16 ++-- ...lator2Test.java => QueryBuilder2Test.java} | 16 ++-- ...lator3Test.java => QueryBuilder3Test.java} | 16 ++-- ...lator4Test.java => QueryBuilder4Test.java} | 8 +- ...nslatorTest.java => QueryBuilderTest.java} | 36 +++---- .../sql/dml/ColumnValueTranslatorTest.java | 25 ----- 22 files changed, 415 insertions(+), 380 deletions(-) create mode 100644 src/main/java/persistence/sql/AbstractQueryTranslator.java create mode 100644 src/main/java/persistence/sql/ddl/ColumnQueryTranslator.java delete mode 100644 src/main/java/persistence/sql/ddl/ColumnTranslator.java rename src/main/java/persistence/sql/ddl/{TableTranslator.java => TableQueryBuilder.java} (97%) delete mode 100644 src/main/java/persistence/sql/dml/ColumnValueTranslator.java rename src/test/java/persistence/sql/ddl/query/{QueryTranslator1Test.java => QueryBuilder1Test.java} (81%) rename src/test/java/persistence/sql/ddl/query/{QueryTranslator2Test.java => QueryBuilder2Test.java} (82%) rename src/test/java/persistence/sql/ddl/query/{QueryTranslator3Test.java => QueryBuilder3Test.java} (83%) rename src/test/java/persistence/sql/ddl/query/{QueryTranslator4Test.java => QueryBuilder4Test.java} (79%) rename src/test/java/persistence/sql/ddl/query/{QueryTranslatorTest.java => QueryBuilderTest.java} (79%) delete mode 100644 src/test/java/persistence/sql/dml/ColumnValueTranslatorTest.java diff --git a/src/main/java/persistence/Application.java b/src/main/java/persistence/Application.java index 9c29423ba..c0963c328 100644 --- a/src/main/java/persistence/Application.java +++ b/src/main/java/persistence/Application.java @@ -28,19 +28,19 @@ public static void main(String[] args) { final JdbcTemplate jdbcTemplate = new JdbcTemplate(server.getConnection()); - QueryTranslator queryTranslator = new QueryTranslator(); + QueryTranslator queryBuilder = new QueryTranslator(); - jdbcTemplate.execute(queryTranslator.getCreateTableQuery(Person.class)); + jdbcTemplate.execute(queryBuilder.getCreateTableQuery(Person.class)); - executeInitializedQuery(jdbcTemplate, queryTranslator); + executeInitializedQuery(jdbcTemplate, queryBuilder); - querySelectAll(jdbcTemplate, queryTranslator); + querySelectAll(jdbcTemplate, queryBuilder); - querySelectById(jdbcTemplate, queryTranslator); + querySelectById(jdbcTemplate, queryBuilder); - jdbcTemplate.execute(queryTranslator.getDeleteByIdQuery(Person.class, 2L)); + jdbcTemplate.execute(queryBuilder.getDeleteByIdQuery(Person.class, 2L)); - querySelectAll(jdbcTemplate, queryTranslator); + querySelectAll(jdbcTemplate, queryBuilder); server.stop(); } catch (Exception e) { @@ -50,25 +50,25 @@ public static void main(String[] args) { } } - private static void querySelectById(JdbcTemplate jdbcTemplate, QueryTranslator queryTranslator) { + private static void querySelectById(JdbcTemplate jdbcTemplate, QueryTranslator queryBuilder) { Person person = jdbcTemplate.queryForObject( - queryTranslator.getSelectByIdQuery(Person.class, 2L), + queryBuilder.getSelectByIdQuery(Person.class, 2L), rowMapper ); logger.info("Person: {}", person); } - private static void querySelectAll(JdbcTemplate jdbcTemplate, QueryTranslator queryTranslator) { + private static void querySelectAll(JdbcTemplate jdbcTemplate, QueryTranslator queryBuilder) { List persons = jdbcTemplate.query( - queryTranslator.getSelectAllQuery(Person.class), + queryBuilder.getSelectAllQuery(Person.class), rowMapper ); persons.forEach(person -> logger.info("Person: {}", person)); } - private static void executeInitializedQuery(JdbcTemplate jdbcTemplate, QueryTranslator queryTranslator) { + private static void executeInitializedQuery(JdbcTemplate jdbcTemplate, QueryTranslator queryBuilder) { List persons = List.of( new Person("John", 23, "john@gmail.com"), new Person("Smith", 33, "smith@gmail.com"), @@ -76,7 +76,7 @@ private static void executeInitializedQuery(JdbcTemplate jdbcTemplate, QueryTran ); persons.stream() - .map(queryTranslator::getInsertQuery) + .map(queryBuilder::getInsertQuery) .forEach(jdbcTemplate::execute); } diff --git a/src/main/java/persistence/entity/EntityRowMapperFactory.java b/src/main/java/persistence/entity/EntityRowMapperFactory.java index 54f46a6c9..bc330b122 100644 --- a/src/main/java/persistence/entity/EntityRowMapperFactory.java +++ b/src/main/java/persistence/entity/EntityRowMapperFactory.java @@ -7,7 +7,7 @@ import java.util.stream.Collectors; import jdbc.RowMapper; import persistence.exception.ReflectionRuntimeException; -import persistence.sql.ddl.ColumnTranslator; +import persistence.sql.ddl.ColumnQueryTranslator; public class EntityRowMapperFactory { @@ -15,28 +15,32 @@ private EntityRowMapperFactory() { // Do nothing } - public static class LazyLoadEntityRowMapperFactory { + public static class CacheEntityRowMapperFactory { + private CacheEntityRowMapperFactory() { + // Do nothing + } + private static final EntityRowMapperFactory INSTANCE = new EntityRowMapperFactory(); } public static EntityRowMapperFactory getInstance() { - return LazyLoadEntityRowMapperFactory.INSTANCE; + return CacheEntityRowMapperFactory.INSTANCE; } public RowMapper getRowMapper(Class entityClass) { return resultSet -> { try { - ColumnTranslator columnTranslator = new ColumnTranslator(); + ColumnQueryTranslator columnQueryTranslator = new ColumnQueryTranslator(); Constructor declaredConstructor = entityClass.getDeclaredConstructor(); declaredConstructor.setAccessible(true); T entity = entityClass.getDeclaredConstructor().newInstance(); - List columnFieldList = columnTranslator.getColumnFieldStream(entityClass) + List columnFieldList = columnQueryTranslator.getColumnFieldStream(entityClass) .collect(Collectors.toList()); for (Field field : columnFieldList) { field.setAccessible(true); - String columnName = columnTranslator.getColumnNameFrom(field); + String columnName = columnQueryTranslator.getColumnNameFrom(field); field.set(entity, resultSet.getObject(columnName)); } diff --git a/src/main/java/persistence/entity/impl/EntityManagerImpl.java b/src/main/java/persistence/entity/impl/EntityManagerImpl.java index 2d65fe5cd..f00b95273 100644 --- a/src/main/java/persistence/entity/impl/EntityManagerImpl.java +++ b/src/main/java/persistence/entity/impl/EntityManagerImpl.java @@ -8,21 +8,21 @@ public class EntityManagerImpl implements EntityManager { private final JdbcTemplate jdbcTemplate; - private final QueryTranslator queryTranslator; + private final QueryTranslator queryBuilder; public EntityManagerImpl(JdbcTemplate jdbcTemplate) { this(jdbcTemplate, new QueryTranslator()); } - public EntityManagerImpl(JdbcTemplate jdbcTemplate, QueryTranslator queryTranslator) { + public EntityManagerImpl(JdbcTemplate jdbcTemplate, QueryTranslator queryBuilder) { this.jdbcTemplate = jdbcTemplate; - this.queryTranslator = queryTranslator; + this.queryBuilder = queryBuilder; } @Override public T find(Class entityClass, Long id) { - String selectByIdQuery = queryTranslator.getSelectByIdQuery(entityClass, id); + String selectByIdQuery = queryBuilder.getSelectByIdQuery(entityClass, id); return jdbcTemplate.queryForObject( selectByIdQuery, @@ -32,7 +32,7 @@ public T find(Class entityClass, Long id) { @Override public Object persist(Object entity) { - String insertQuery = queryTranslator.getInsertQuery(entity); + String insertQuery = queryBuilder.getInsertQuery(entity); jdbcTemplate.execute(insertQuery); @@ -41,7 +41,7 @@ public Object persist(Object entity) { @Override public void remove(Object entity) { - String deleteQueryFromEntity = queryTranslator.getDeleteQueryFromEntity(entity); + String deleteQueryFromEntity = queryBuilder.getDeleteQueryFromEntity(entity); jdbcTemplate.execute(deleteQueryFromEntity); } diff --git a/src/main/java/persistence/sql/AbstractQueryTranslator.java b/src/main/java/persistence/sql/AbstractQueryTranslator.java new file mode 100644 index 000000000..627282724 --- /dev/null +++ b/src/main/java/persistence/sql/AbstractQueryTranslator.java @@ -0,0 +1,70 @@ +package persistence.sql; + +import jakarta.persistence.Column; +import jakarta.persistence.Id; +import jakarta.persistence.Transient; +import java.lang.reflect.Field; +import java.util.Arrays; +import java.util.Comparator; +import java.util.stream.Stream; +import persistence.exception.UnsupportedClassException; + +public abstract class AbstractQueryTranslator { + + protected AbstractQueryTranslator() { + + } + + /** + * Get the stream of fields that are not annotated with @Transient from the entity class + * @param entityClass Entity class + * @return Stream of fields that are annotated with @Column or @Id + * @see Column + * @see Id + * @see Transient + */ + protected Stream getColumnFieldStream(Class entityClass) { + return Arrays.stream(entityClass.getDeclaredFields()) + .filter(field -> !field.isAnnotationPresent(Transient.class)) + .sorted(Comparator.comparing(field -> field.isAnnotationPresent(Id.class) ? 0 : 1)); + } + + /** + * Get the column name from the field + * @param field Field + * @return Column name from the field + */ + protected String getColumnNameFrom(Field field) { + if (!field.isAnnotationPresent(Column.class)) { + return field.getName(); + } + + Column column = field.getAnnotation(Column.class); + + if (column.name().isEmpty()) { + return field.getName(); + } + + return column.name(); + } + + /** + * Get the column value from the object + * @param columnValue Column value object + * @return Column value from the object + */ + protected String getColumnValueFromObject(Object columnValue) { + // TODO: remove this else-if statement + if (columnValue.getClass().equals(Boolean.class)) { + return columnValue == Boolean.TRUE ? "1" : "0"; + } else if (columnValue.getClass().equals(String.class)) { + return String.format("'%s'", columnValue); + } else if (columnValue.getClass().equals(Integer.class)) { + return columnValue.toString(); + } else if (columnValue.getClass().equals(Long.class)) { + return columnValue.toString(); + } + + throw new UnsupportedClassException(columnValue.getClass()); + } +} diff --git a/src/main/java/persistence/sql/QueryTranslator.java b/src/main/java/persistence/sql/QueryTranslator.java index 27cea114a..4eb97dc74 100644 --- a/src/main/java/persistence/sql/QueryTranslator.java +++ b/src/main/java/persistence/sql/QueryTranslator.java @@ -2,46 +2,42 @@ import java.lang.reflect.Field; -import persistence.sql.ddl.ColumnTranslator; import persistence.sql.ddl.CreateQueryTranslator; import persistence.sql.ddl.DropQueryTranslator; -import persistence.sql.ddl.TableTranslator; -import persistence.sql.dml.ColumnValueTranslator; +import persistence.sql.ddl.TableQueryBuilder; import persistence.sql.dml.DeleteQueryTranslator; import persistence.sql.dml.InsertQueryTranslator; import persistence.sql.dml.SelectQueryTranslator; -public class QueryTranslator { +public class QueryTranslator extends AbstractQueryTranslator { - private final TableTranslator tableTranslator = new TableTranslator(); + private final TableQueryBuilder tableQueryBuilder; - private final ColumnTranslator columnTranslator = new ColumnTranslator(); + private final SelectQueryTranslator selectQueryBuilder; - private final ColumnValueTranslator columnValueTranslator = new ColumnValueTranslator(); - - private final SelectQueryTranslator selectQueryTranslator; - - private final DeleteQueryTranslator deleteQueryTranslator; + private final DeleteQueryTranslator deleteQueryBuilder; private final InsertQueryTranslator insertQueryTranslator; private final DropQueryTranslator dropQueryTranslator; - private final CreateQueryTranslator createQueryTranslator; + private final CreateQueryTranslator createQueryBuilder; public QueryTranslator() { - this.selectQueryTranslator = new SelectQueryTranslator(columnTranslator, - columnValueTranslator, tableTranslator); - this.deleteQueryTranslator = new DeleteQueryTranslator(columnTranslator, - columnValueTranslator, tableTranslator); - this.insertQueryTranslator = new InsertQueryTranslator(columnTranslator, - columnValueTranslator, tableTranslator); - this.dropQueryTranslator = new DropQueryTranslator(tableTranslator); - this.createQueryTranslator = new CreateQueryTranslator(columnTranslator, tableTranslator); + this(new TableQueryBuilder()); + } + + public QueryTranslator(TableQueryBuilder tableQueryBuilder) { + this.tableQueryBuilder = tableQueryBuilder; + this.selectQueryBuilder = new SelectQueryTranslator(tableQueryBuilder); + this.deleteQueryBuilder = new DeleteQueryTranslator(tableQueryBuilder); + this.insertQueryTranslator = new InsertQueryTranslator(tableQueryBuilder); + this.dropQueryTranslator = new DropQueryTranslator(tableQueryBuilder); + this.createQueryBuilder = new CreateQueryTranslator(tableQueryBuilder); } public String getCreateTableQuery(final Class entityClass) { - return createQueryTranslator.getCreateTableQuery(entityClass); + return createQueryBuilder.getCreateTableQuery(entityClass); } public String getDropTableQuery(Class entityClass) { @@ -53,38 +49,38 @@ public String getInsertQuery(Object entity) { } public String getSelectAllQuery(Class entityClass) { - return selectQueryTranslator.getSelectAllQuery(entityClass); + return selectQueryBuilder.getSelectAllQuery(entityClass); } public String getSelectByIdQuery(Class entityClass, Object id) { - return selectQueryTranslator.getSelectByIdQuery(entityClass, id); + return selectQueryBuilder.getSelectByIdQuery(entityClass, id); } public String getSelectCountQuery(Class entityClass) { - return selectQueryTranslator.getSelectCountQuery(entityClass); + return selectQueryBuilder.getSelectCountQuery(entityClass); } public String getDeleteAllQuery(Class entityClass) { - return deleteQueryTranslator.getDeleteAllQuery(entityClass); + return deleteQueryBuilder.getDeleteAllQuery(entityClass); } public String getDeleteByIdQuery(Class entityClass, Object id) { - return deleteQueryTranslator.getDeleteByIdQuery(entityClass, id); + return deleteQueryBuilder.getDeleteByIdQuery(entityClass, id); } public String getDeleteQueryFromEntity(Object entity) { - return deleteQueryTranslator.getDeleteQueryFromEntity(entity); + return deleteQueryBuilder.getDeleteQueryFromEntity(entity); } public String getTableNameFrom(Class entityClass) { - return tableTranslator.getTableNameFrom(entityClass); + return tableQueryBuilder.getTableNameFrom(entityClass); } public String getColumnDefinitionFrom(Field field) { - return columnTranslator.getColumnDefinitionFrom(field); + return createQueryBuilder.getColumnDefinitionFrom(field); } public String getColumnDefinitionsFrom(Class entityClass) { - return columnTranslator.getColumnDefinitionsFrom(entityClass); + return createQueryBuilder.getColumnDefinitionsFrom(entityClass); } } diff --git a/src/main/java/persistence/sql/ddl/ColumnQueryTranslator.java b/src/main/java/persistence/sql/ddl/ColumnQueryTranslator.java new file mode 100644 index 000000000..c9407bc48 --- /dev/null +++ b/src/main/java/persistence/sql/ddl/ColumnQueryTranslator.java @@ -0,0 +1,32 @@ +package persistence.sql.ddl; + +import jakarta.persistence.Column; +import jakarta.persistence.Id; +import jakarta.persistence.Transient; +import java.lang.reflect.Field; +import java.util.Arrays; +import java.util.Comparator; +import java.util.stream.Stream; + +public class ColumnQueryTranslator { + + public String getColumnNameFrom(Field field) { + if (!field.isAnnotationPresent(Column.class)) { + return field.getName(); + } + + Column column = field.getAnnotation(Column.class); + + if (column.name().isEmpty()) { + return field.getName(); + } + + return column.name(); + } + + public Stream getColumnFieldStream(Class entityClass) { + return Arrays.stream(entityClass.getDeclaredFields()) + .filter(field -> !field.isAnnotationPresent(Transient.class)) + .sorted(Comparator.comparing(field -> field.isAnnotationPresent(Id.class) ? 0 : 1)); + } +} diff --git a/src/main/java/persistence/sql/ddl/ColumnTranslator.java b/src/main/java/persistence/sql/ddl/ColumnTranslator.java deleted file mode 100644 index 458f8629c..000000000 --- a/src/main/java/persistence/sql/ddl/ColumnTranslator.java +++ /dev/null @@ -1,95 +0,0 @@ -package persistence.sql.ddl; - -import static persistence.sql.ddl.common.StringConstants.COLUMN_DEFINITION_DELIMITER; - -import jakarta.persistence.Column; -import jakarta.persistence.Id; -import jakarta.persistence.Transient; -import java.lang.reflect.Field; -import java.util.Arrays; -import java.util.Comparator; -import java.util.stream.Collectors; -import java.util.stream.Stream; -import persistence.sql.ddl.constraints.strategy.ConstraintsStrategy; -import persistence.sql.ddl.constraints.strategy.DefaultConstraintsStrategy; -import persistence.sql.ddl.type.DataTypeMapping; -import persistence.sql.ddl.type.impl.DefaultDataTypeMapping; - -public class ColumnTranslator { - - private final ConstraintsStrategy constraintsStrategy; - - private final DataTypeMapping dataTypeMapping; - - public ColumnTranslator() { - this( - new DefaultConstraintsStrategy(), - new DefaultDataTypeMapping() - ); - } - - public ColumnTranslator( - ConstraintsStrategy constraintsStrategy, - DataTypeMapping dataTypeMapping - ) { - this.constraintsStrategy = constraintsStrategy; - this.dataTypeMapping = dataTypeMapping; - } - - public String getColumnDefinitionsFrom(Class entityClass) { - return getColumnFieldStream(entityClass) - .map(this::getColumnDefinitionFrom) - .collect(Collectors.joining(COLUMN_DEFINITION_DELIMITER)); - } - - public String getColumnDefinitionFrom(Field field) { - return Stream.of( - getColumnNameFrom(field), - dataTypeMapping.getDataTypeDefinitionFrom(field), - constraintsStrategy.getConstraintsFrom(field) - ) - .filter(s -> !s.isBlank()) - .collect(Collectors.joining(" ")); - } - - public String getColumnNameFrom(Field field) { - if (!field.isAnnotationPresent(Column.class)) { - return field.getName(); - } - - Column column = field.getAnnotation(Column.class); - - if (column.name().isEmpty()) { - return field.getName(); - } - - return column.name(); - } - - public String getPrimaryKeyColumnName(Class entityClass) { - return Arrays.stream(entityClass.getDeclaredFields()) - .filter(field -> field.isAnnotationPresent(Id.class)) - .findFirst() - .map(this::getColumnNameFrom) - .orElseThrow(() -> new IllegalStateException("Primary key not found")); - } - - public String getColumnNamesClauseWithoutPrimaryKey(Class entityClass) { - return getColumnFieldStream(entityClass) - .filter(field -> !field.isAnnotationPresent(Id.class)) - .map(this::getColumnNameFrom) - .collect(Collectors.joining(COLUMN_DEFINITION_DELIMITER)); - } - - public String getColumnNamesClause(Class entityClass) { - return getColumnFieldStream(entityClass) - .map(this::getColumnNameFrom) - .collect(Collectors.joining(COLUMN_DEFINITION_DELIMITER)); - } - - public Stream getColumnFieldStream(Class entityClass) { - return Arrays.stream(entityClass.getDeclaredFields()) - .filter(field -> !field.isAnnotationPresent(Transient.class)) - .sorted(Comparator.comparing(field -> field.isAnnotationPresent(Id.class) ? 0 : 1)); - } -} diff --git a/src/main/java/persistence/sql/ddl/CreateQueryTranslator.java b/src/main/java/persistence/sql/ddl/CreateQueryTranslator.java index a81165004..03bb19f63 100644 --- a/src/main/java/persistence/sql/ddl/CreateQueryTranslator.java +++ b/src/main/java/persistence/sql/ddl/CreateQueryTranslator.java @@ -1,21 +1,63 @@ package persistence.sql.ddl; -public class CreateQueryTranslator { - private final ColumnTranslator columnTranslator; +import static persistence.sql.ddl.common.StringConstants.COLUMN_DEFINITION_DELIMITER; - private final TableTranslator tableTranslator; +import java.lang.reflect.Field; +import java.util.stream.Collectors; +import java.util.stream.Stream; +import persistence.sql.AbstractQueryTranslator; +import persistence.sql.ddl.common.StringConstants; +import persistence.sql.ddl.constraints.strategy.ConstraintsStrategy; +import persistence.sql.ddl.constraints.strategy.DefaultConstraintsStrategy; +import persistence.sql.ddl.type.DataTypeMapping; +import persistence.sql.ddl.type.impl.DefaultDataTypeMapping; - public CreateQueryTranslator(ColumnTranslator columnTranslator, - TableTranslator tableTranslator) { - this.columnTranslator = columnTranslator; - this.tableTranslator = tableTranslator; +public class CreateQueryTranslator extends AbstractQueryTranslator { + private final TableQueryBuilder tableQueryBuilder; + + private final DataTypeMapping dataTypeMapping; + + private final ConstraintsStrategy constraintsStrategy; + + public CreateQueryTranslator(TableQueryBuilder tableQueryBuilder) { + this( + tableQueryBuilder, + new DefaultDataTypeMapping(), + new DefaultConstraintsStrategy() + ); + } + + public CreateQueryTranslator( + TableQueryBuilder tableQueryBuilder, + DataTypeMapping dataTypeMapping, + ConstraintsStrategy constraintsStrategy + ) { + this.tableQueryBuilder = tableQueryBuilder; + this.dataTypeMapping = dataTypeMapping; + this.constraintsStrategy = constraintsStrategy; } public String getCreateTableQuery(final Class entityClass) { return String.format( "CREATE TABLE %s (%s)", - tableTranslator.getTableNameFrom(entityClass), - columnTranslator.getColumnDefinitionsFrom(entityClass) + tableQueryBuilder.getTableNameFrom(entityClass), + getColumnDefinitionsFrom(entityClass) ); } + + public String getColumnDefinitionsFrom(Class entityClass) { + return getColumnFieldStream(entityClass) + .map(this::getColumnDefinitionFrom) + .collect(Collectors.joining(COLUMN_DEFINITION_DELIMITER)); + } + + public String getColumnDefinitionFrom(Field field) { + return Stream.of( + getColumnNameFrom(field), + dataTypeMapping.getDataTypeDefinitionFrom(field), + constraintsStrategy.getConstraintsFrom(field) + ) + .filter(s -> !s.isBlank()) + .collect(Collectors.joining(StringConstants.SPACE)); + } } diff --git a/src/main/java/persistence/sql/ddl/DropQueryTranslator.java b/src/main/java/persistence/sql/ddl/DropQueryTranslator.java index 35762e84f..fb28f0b2e 100644 --- a/src/main/java/persistence/sql/ddl/DropQueryTranslator.java +++ b/src/main/java/persistence/sql/ddl/DropQueryTranslator.java @@ -1,16 +1,16 @@ package persistence.sql.ddl; public class DropQueryTranslator { - private final TableTranslator tableTranslator; + private final TableQueryBuilder tableQueryBuilder; - public DropQueryTranslator(TableTranslator tableTranslator) { - this.tableTranslator = tableTranslator; + public DropQueryTranslator(TableQueryBuilder tableQueryBuilder) { + this.tableQueryBuilder = tableQueryBuilder; } public String getDropTableQuery(Class entityClass) { return String.format( "DROP TABLE %s", - tableTranslator.getTableNameFrom(entityClass) + tableQueryBuilder.getTableNameFrom(entityClass) ); } } diff --git a/src/main/java/persistence/sql/ddl/TableTranslator.java b/src/main/java/persistence/sql/ddl/TableQueryBuilder.java similarity index 97% rename from src/main/java/persistence/sql/ddl/TableTranslator.java rename to src/main/java/persistence/sql/ddl/TableQueryBuilder.java index 2004c85c2..9a3637102 100644 --- a/src/main/java/persistence/sql/ddl/TableTranslator.java +++ b/src/main/java/persistence/sql/ddl/TableQueryBuilder.java @@ -7,7 +7,7 @@ import java.util.stream.Stream; import persistence.sql.ddl.common.StringConstants; -public class TableTranslator { +public class TableQueryBuilder { public String getTableNameFrom(Class entityClass) { return Stream.of( getSchemaNameFrom(entityClass), diff --git a/src/main/java/persistence/sql/ddl/common/StringConstants.java b/src/main/java/persistence/sql/ddl/common/StringConstants.java index 0f644b8ec..9338935ca 100644 --- a/src/main/java/persistence/sql/ddl/common/StringConstants.java +++ b/src/main/java/persistence/sql/ddl/common/StringConstants.java @@ -14,4 +14,6 @@ private StringConstants() { public static final String COLUMN_DEFINITION_DELIMITER = ", "; + public static final String PRIMARY_KEY_NOT_FOUND = "Primary key not found"; + } diff --git a/src/main/java/persistence/sql/dml/ColumnValueTranslator.java b/src/main/java/persistence/sql/dml/ColumnValueTranslator.java deleted file mode 100644 index 14d1661b1..000000000 --- a/src/main/java/persistence/sql/dml/ColumnValueTranslator.java +++ /dev/null @@ -1,81 +0,0 @@ -package persistence.sql.dml; - -import static persistence.sql.ddl.common.StringConstants.COLUMN_DEFINITION_DELIMITER; - -import jakarta.persistence.Id; -import jakarta.persistence.Transient; -import java.lang.reflect.Field; -import java.util.Arrays; -import java.util.Comparator; -import java.util.stream.Collectors; -import persistence.exception.UnsupportedClassException; - -public class ColumnValueTranslator { - - public String getColumnValueClause(Object entity) { - Class clazz = entity.getClass(); - return Arrays.stream(clazz.getDeclaredFields()) - .filter(field -> !field.isAnnotationPresent(Transient.class)) - .filter(field -> !field.isAnnotationPresent(Id.class)) - .sorted(Comparator.comparing(field -> field.isAnnotationPresent(Id.class) ? 0 : 1)) - .map(field -> getNativeColumnValueStringFromEntity(entity, field)) - .collect(Collectors.joining(COLUMN_DEFINITION_DELIMITER)); - } - - public String getPrimaryKeyValueClauseFromEntityClassAndId(Class entityClass, Object id) { - Field primaryKeyField = Arrays.stream(entityClass.getDeclaredFields()) - .filter(field -> field.isAnnotationPresent(Id.class)) - .findFirst() - .orElseThrow(() -> new IllegalStateException("Primary key not found")); - - if (!primaryKeyField.getType().equals(id.getClass())) { - throw new IllegalStateException("Primary key type mismatch"); - } - - return getNativeColumnValueString(id); - } - - public String getPrimaryKeyValueClauseFromEntityClassAndEntityObject(Class entityClass, Object entity) { - try { - Field primaryKeyField = Arrays.stream(entityClass.getDeclaredFields()) - .filter(field -> field.isAnnotationPresent(Id.class)) - .findFirst() - .orElseThrow(() -> new IllegalStateException("Primary key not found")); - - primaryKeyField.setAccessible(true); - - Object id = primaryKeyField.get(entity); - - return getNativeColumnValueString(id); - } catch (IllegalAccessException e) { - throw new IllegalStateException(e); - } - } - - private String getNativeColumnValueStringFromEntity(Object entity, Field field) { - try { - field.setAccessible(true); - Object columnValue = field.get(entity); - - return getNativeColumnValueString(columnValue); - } catch (IllegalAccessException e) { - throw new IllegalStateException(e); - } - } - - private String getNativeColumnValueString(Object columnValue) { - // TODO: remove this else-if statement - if (columnValue.getClass().equals(Boolean.class)) { - return columnValue == Boolean.TRUE ? "1" : "0"; - } else if (columnValue.getClass().equals(String.class)) { - return String.format("'%s'", columnValue); - } else if (columnValue.getClass().equals(Integer.class)) { - return columnValue.toString(); - } else if (columnValue.getClass().equals(Long.class)) { - return columnValue.toString(); - } - - throw new UnsupportedClassException(columnValue.getClass()); - } - -} diff --git a/src/main/java/persistence/sql/dml/DeleteQueryTranslator.java b/src/main/java/persistence/sql/dml/DeleteQueryTranslator.java index 7942db943..846c7466a 100644 --- a/src/main/java/persistence/sql/dml/DeleteQueryTranslator.java +++ b/src/main/java/persistence/sql/dml/DeleteQueryTranslator.java @@ -1,38 +1,35 @@ package persistence.sql.dml; -import persistence.sql.ddl.ColumnTranslator; -import persistence.sql.ddl.TableTranslator; +import static persistence.sql.ddl.common.StringConstants.*; -public class DeleteQueryTranslator { - private final ColumnTranslator columnTranslator; +import jakarta.persistence.Id; +import java.lang.reflect.Field; +import java.util.Arrays; +import persistence.sql.AbstractQueryTranslator; +import persistence.sql.ddl.TableQueryBuilder; - private final ColumnValueTranslator columnValueTranslator; - - private final TableTranslator tableTranslator; +public class DeleteQueryTranslator extends AbstractQueryTranslator { + private final TableQueryBuilder tableQueryBuilder; public DeleteQueryTranslator( - ColumnTranslator columnTranslator, - ColumnValueTranslator columnValueTranslator, - TableTranslator tableTranslator + TableQueryBuilder tableQueryBuilder ) { - this.columnTranslator = columnTranslator; - this.columnValueTranslator = columnValueTranslator; - this.tableTranslator = tableTranslator; + this.tableQueryBuilder = tableQueryBuilder; } public String getDeleteAllQuery(Class entityClass) { return String.format( "DELETE FROM %s", - tableTranslator.getTableNameFrom(entityClass) + tableQueryBuilder.getTableNameFrom(entityClass) ); } public String getDeleteByIdQuery(Class entityClass, Object id) { return String.format( "DELETE FROM %s WHERE %s = %s", - tableTranslator.getTableNameFrom(entityClass), - columnTranslator.getPrimaryKeyColumnName(entityClass), - columnValueTranslator.getPrimaryKeyValueClauseFromEntityClassAndId(entityClass, id) + tableQueryBuilder.getTableNameFrom(entityClass), + getPrimaryKeyColumnName(entityClass), + getPrimaryKeyValueQueryFromEntityClassAndId(entityClass, id) ); } @@ -43,9 +40,47 @@ public String getDeleteQueryFromEntity(Object entity) { private String getDeleteQueryFromEntity(Class entityClass, Object entity) { return String.format( "DELETE FROM %s WHERE %s = %s", - tableTranslator.getTableNameFrom(entityClass), - columnTranslator.getPrimaryKeyColumnName(entityClass), - columnValueTranslator.getPrimaryKeyValueClauseFromEntityClassAndEntityObject(entityClass, entity) + tableQueryBuilder.getTableNameFrom(entityClass), + getPrimaryKeyColumnName(entityClass), + getPrimaryKeyValueQueryFromEntityClassAndEntityObject(entityClass, entity) ); } + + private String getPrimaryKeyColumnName(Class entityClass) { + return Arrays.stream(entityClass.getDeclaredFields()) + .filter(field -> field.isAnnotationPresent(Id.class)) + .findFirst() + .map(this::getColumnNameFrom) + .orElseThrow(() -> new IllegalStateException(PRIMARY_KEY_NOT_FOUND)); + } + + private String getPrimaryKeyValueQueryFromEntityClassAndId(Class entityClass, Object id) { + Field primaryKeyField = Arrays.stream(entityClass.getDeclaredFields()) + .filter(field -> field.isAnnotationPresent(Id.class)) + .findFirst() + .orElseThrow(() -> new IllegalStateException(PRIMARY_KEY_NOT_FOUND)); + + if (!primaryKeyField.getType().equals(id.getClass())) { + throw new IllegalStateException("Primary key type mismatch"); + } + + return getColumnValueFromObject(id); + } + + private String getPrimaryKeyValueQueryFromEntityClassAndEntityObject(Class entityClass, Object entity) { + try { + Field primaryKeyField = Arrays.stream(entityClass.getDeclaredFields()) + .filter(field -> field.isAnnotationPresent(Id.class)) + .findFirst() + .orElseThrow(() -> new IllegalStateException(PRIMARY_KEY_NOT_FOUND)); + + primaryKeyField.setAccessible(true); + + Object id = primaryKeyField.get(entity); + + return getColumnValueFromObject(id); + } catch (IllegalAccessException e) { + throw new IllegalStateException(e); + } + } } diff --git a/src/main/java/persistence/sql/dml/InsertQueryTranslator.java b/src/main/java/persistence/sql/dml/InsertQueryTranslator.java index f87ca5fa9..c891b54de 100644 --- a/src/main/java/persistence/sql/dml/InsertQueryTranslator.java +++ b/src/main/java/persistence/sql/dml/InsertQueryTranslator.java @@ -1,20 +1,21 @@ package persistence.sql.dml; -import persistence.sql.ddl.ColumnTranslator; -import persistence.sql.ddl.TableTranslator; +import static persistence.sql.ddl.common.StringConstants.COLUMN_DEFINITION_DELIMITER; -public class InsertQueryTranslator { - private final ColumnTranslator columnTranslator; +import jakarta.persistence.Id; +import jakarta.persistence.Transient; +import java.lang.reflect.Field; +import java.util.Arrays; +import java.util.Comparator; +import java.util.stream.Collectors; +import persistence.sql.AbstractQueryTranslator; +import persistence.sql.ddl.TableQueryBuilder; - private final ColumnValueTranslator columnValueTranslator; +public class InsertQueryTranslator extends AbstractQueryTranslator { + private final TableQueryBuilder tableQueryBuilder; - private final TableTranslator tableTranslator; - - public InsertQueryTranslator(ColumnTranslator columnTranslator, - ColumnValueTranslator columnValueTranslator, TableTranslator tableTranslator) { - this.columnTranslator = columnTranslator; - this.columnValueTranslator = columnValueTranslator; - this.tableTranslator = tableTranslator; + public InsertQueryTranslator(TableQueryBuilder tableQueryBuilder) { + this.tableQueryBuilder = tableQueryBuilder; } public String getInsertQuery(Object entity) { @@ -22,9 +23,37 @@ public String getInsertQuery(Object entity) { return String.format( "INSERT INTO %s (%s) VALUES (%s)", - tableTranslator.getTableNameFrom(entityClass), - columnTranslator.getColumnNamesClauseWithoutPrimaryKey(entityClass), - columnValueTranslator.getColumnValueClause(entity) + tableQueryBuilder.getTableNameFrom(entityClass), + getColumnNamesWithoutPrimaryKey(entityClass), + getColumnValuesQuery(entity) ); } + + private String getColumnValuesQuery(Object entity) { + Class clazz = entity.getClass(); + return Arrays.stream(clazz.getDeclaredFields()) + .filter(field -> !field.isAnnotationPresent(Transient.class)) + .filter(field -> !field.isAnnotationPresent(Id.class)) + .sorted(Comparator.comparing(field -> field.isAnnotationPresent(Id.class) ? 0 : 1)) + .map(field -> getColumnValueFromEntity(entity, field)) + .collect(Collectors.joining(COLUMN_DEFINITION_DELIMITER)); + } + + private String getColumnNamesWithoutPrimaryKey(Class entityClass) { + return getColumnFieldStream(entityClass) + .filter(field -> !field.isAnnotationPresent(Id.class)) + .map(this::getColumnNameFrom) + .collect(Collectors.joining(COLUMN_DEFINITION_DELIMITER)); + } + + private String getColumnValueFromEntity(Object entity, Field field) { + try { + field.setAccessible(true); + Object columnValue = field.get(entity); + + return getColumnValueFromObject(columnValue); + } catch (IllegalAccessException e) { + throw new IllegalStateException(e); + } + } } diff --git a/src/main/java/persistence/sql/dml/SelectQueryTranslator.java b/src/main/java/persistence/sql/dml/SelectQueryTranslator.java index 54146d292..d00eab3a8 100644 --- a/src/main/java/persistence/sql/dml/SelectQueryTranslator.java +++ b/src/main/java/persistence/sql/dml/SelectQueryTranslator.java @@ -1,48 +1,74 @@ package persistence.sql.dml; -import persistence.sql.ddl.ColumnTranslator; -import persistence.sql.ddl.TableTranslator; +import static persistence.sql.ddl.common.StringConstants.COLUMN_DEFINITION_DELIMITER; +import static persistence.sql.ddl.common.StringConstants.PRIMARY_KEY_NOT_FOUND; -public class SelectQueryTranslator { - private final ColumnTranslator columnTranslator; +import jakarta.persistence.Id; +import java.lang.reflect.Field; +import java.util.Arrays; +import java.util.stream.Collectors; +import persistence.sql.AbstractQueryTranslator; +import persistence.sql.ddl.TableQueryBuilder; - private final ColumnValueTranslator columnValueTranslator; - - private final TableTranslator tableTranslator; +public class SelectQueryTranslator extends AbstractQueryTranslator { + private final TableQueryBuilder tableQueryBuilder; public SelectQueryTranslator( - ColumnTranslator columnTranslator, - ColumnValueTranslator columnValueTranslator, - TableTranslator tableTranslator + TableQueryBuilder tableQueryBuilder ) { - this.columnTranslator = columnTranslator; - this.columnValueTranslator = columnValueTranslator; - this.tableTranslator = tableTranslator; + this.tableQueryBuilder = tableQueryBuilder; } public String getSelectAllQuery(Class entityClass) { return String.format( "SELECT %s FROM %s", - columnTranslator.getColumnNamesClause(entityClass), - tableTranslator.getTableNameFrom(entityClass) + getColumnNamesClause(entityClass), + tableQueryBuilder.getTableNameFrom(entityClass) ); } public String getSelectByIdQuery(Class entityClass, Object id) { return String.format( "SELECT %s FROM %s WHERE %s = %s", - columnTranslator.getColumnNamesClause(entityClass), - tableTranslator.getTableNameFrom(entityClass), - columnTranslator.getPrimaryKeyColumnName(entityClass), - columnValueTranslator.getPrimaryKeyValueClauseFromEntityClassAndId(entityClass, id) + getColumnNamesClause(entityClass), + tableQueryBuilder.getTableNameFrom(entityClass), + getPrimaryKeyColumnName(entityClass), + getPrimaryKeyValueQueryFromEntityClassAndId(entityClass, id) ); } public String getSelectCountQuery(Class entityClass) { return String.format( "SELECT COUNT(%s) FROM %s", - columnTranslator.getPrimaryKeyColumnName(entityClass), - tableTranslator.getTableNameFrom(entityClass) + getPrimaryKeyColumnName(entityClass), + tableQueryBuilder.getTableNameFrom(entityClass) ); } + + private String getColumnNamesClause(Class entityClass) { + return getColumnFieldStream(entityClass) + .map(this::getColumnNameFrom) + .collect(Collectors.joining(COLUMN_DEFINITION_DELIMITER)); + } + + private String getPrimaryKeyColumnName(Class entityClass) { + return Arrays.stream(entityClass.getDeclaredFields()) + .filter(field -> field.isAnnotationPresent(Id.class)) + .findFirst() + .map(this::getColumnNameFrom) + .orElseThrow(() -> new IllegalStateException(PRIMARY_KEY_NOT_FOUND)); + } + + private String getPrimaryKeyValueQueryFromEntityClassAndId(Class entityClass, Object id) { + Field primaryKeyField = Arrays.stream(entityClass.getDeclaredFields()) + .filter(field -> field.isAnnotationPresent(Id.class)) + .findFirst() + .orElseThrow(() -> new IllegalStateException(PRIMARY_KEY_NOT_FOUND)); + + if (!primaryKeyField.getType().equals(id.getClass())) { + throw new IllegalStateException("Primary key type mismatch"); + } + + return getColumnValueFromObject(id); + } } diff --git a/src/test/java/persistence/entity/impl/EntityManagerImplTest.java b/src/test/java/persistence/entity/impl/EntityManagerImplTest.java index 7a7f99091..d884da91b 100644 --- a/src/test/java/persistence/entity/impl/EntityManagerImplTest.java +++ b/src/test/java/persistence/entity/impl/EntityManagerImplTest.java @@ -55,9 +55,9 @@ void setUp() throws SQLException { entityManager = new EntityManagerImpl(jdbcTemplate); - QueryTranslator queryTranslator = new QueryTranslator(); + QueryTranslator queryBuilder = new QueryTranslator(); - jdbcTemplate.execute(queryTranslator.getCreateTableQuery(Person.class)); + jdbcTemplate.execute(queryBuilder.getCreateTableQuery(Person.class)); } @AfterEach @@ -129,27 +129,27 @@ void remove(Person givenPerson) throws SQLException { private void initializeTable() throws SQLException { JdbcTemplate jdbcTemplate = getJdbcTemplate(); - QueryTranslator queryTranslator = new QueryTranslator(); + QueryTranslator queryBuilder = new QueryTranslator(); for (Person person : idToPersonMap.values()) { - jdbcTemplate.execute(queryTranslator.getInsertQuery(person)); + jdbcTemplate.execute(queryBuilder.getInsertQuery(person)); } } private void dropTable() throws SQLException { JdbcTemplate jdbcTemplate = getJdbcTemplate(); - QueryTranslator queryTranslator = new QueryTranslator(); + QueryTranslator queryBuilder = new QueryTranslator(); - jdbcTemplate.execute(queryTranslator.getDropTableQuery(Person.class)); + jdbcTemplate.execute(queryBuilder.getDropTableQuery(Person.class)); } private Integer selectCountOfTable() throws SQLException { JdbcTemplate jdbcTemplate = getJdbcTemplate(); - QueryTranslator queryTranslator = new QueryTranslator(); + QueryTranslator queryBuilder = new QueryTranslator(); - return jdbcTemplate.queryForObject(queryTranslator.getSelectCountQuery(Person.class), + return jdbcTemplate.queryForObject(queryBuilder.getSelectCountQuery(Person.class), resultSet -> resultSet.getInt(1)); } } diff --git a/src/test/java/persistence/sql/ddl/query/QueryTranslator1Test.java b/src/test/java/persistence/sql/ddl/query/QueryBuilder1Test.java similarity index 81% rename from src/test/java/persistence/sql/ddl/query/QueryTranslator1Test.java rename to src/test/java/persistence/sql/ddl/query/QueryBuilder1Test.java index 0d449a3f0..c7afc7366 100644 --- a/src/test/java/persistence/sql/ddl/query/QueryTranslator1Test.java +++ b/src/test/java/persistence/sql/ddl/query/QueryBuilder1Test.java @@ -12,17 +12,17 @@ import persistence.sql.ddl.entity.Person1; @DisplayName("1단계 요구사항 - @Entity, @Id 어노테이션을 바탕으로 create 쿼리 만들어보기") -class QueryTranslator1Test { - private static final Logger log = org.slf4j.LoggerFactory.getLogger(QueryTranslator2Test.class); +class QueryBuilder1Test { + private static final Logger log = org.slf4j.LoggerFactory.getLogger(QueryBuilder2Test.class); private final Class entityClass = Person1.class; - private final QueryTranslator queryTranslator = new QueryTranslator(); + private final QueryTranslator queryBuilder = new QueryTranslator(); @Test @DisplayName("@Entity, @Id 어노테이션을 바탕으로 create 쿼리 만들어보기") void createDDL() { - String ddl = queryTranslator.getCreateTableQuery(entityClass); + String ddl = queryBuilder.getCreateTableQuery(entityClass); log.debug("DDL: {}", ddl); @@ -33,7 +33,7 @@ void createDDL() { @Test @DisplayName("@Entity, @Id 어노테이션을 바탕으로 drop 쿼리 만들어보기") void buildDropQuery() { - String dropQuery = queryTranslator.getDropTableQuery(entityClass); + String dropQuery = queryBuilder.getDropTableQuery(entityClass); log.debug("Drop query: {}", dropQuery); @@ -43,7 +43,7 @@ void buildDropQuery() { @Test @DisplayName("클래스 정보를 바탕으로 테이블명 가져오기") void getTableNameByClassName() { - String tableName = queryTranslator.getTableNameFrom(entityClass); + String tableName = queryBuilder.getTableNameFrom(entityClass); log.debug("Table name: {}", tableName); @@ -54,7 +54,7 @@ void getTableNameByClassName() { @Test @DisplayName("클래스 정보를 바탕으로 컬럼 선언문 가져오기") void getColumnDefinitionStatement() { - String columnDefinitionStatement = queryTranslator.getColumnDefinitionsFrom(entityClass); + String columnDefinitionStatement = queryBuilder.getColumnDefinitionsFrom(entityClass); log.debug("Column definition statement: {}", columnDefinitionStatement); @@ -73,7 +73,7 @@ void getColumnDefinitionStatementFromField( ) throws NoSuchFieldException { Field field = entityClass.getDeclaredField(fieldName); - String actualColumnDefinitionStatement = queryTranslator.getColumnDefinitionFrom(field); + String actualColumnDefinitionStatement = queryBuilder.getColumnDefinitionFrom(field); assertThat(actualColumnDefinitionStatement).isEqualTo(expectedColumnDefinitionStatement); } diff --git a/src/test/java/persistence/sql/ddl/query/QueryTranslator2Test.java b/src/test/java/persistence/sql/ddl/query/QueryBuilder2Test.java similarity index 82% rename from src/test/java/persistence/sql/ddl/query/QueryTranslator2Test.java rename to src/test/java/persistence/sql/ddl/query/QueryBuilder2Test.java index 54d26ee24..43e22ac46 100644 --- a/src/test/java/persistence/sql/ddl/query/QueryTranslator2Test.java +++ b/src/test/java/persistence/sql/ddl/query/QueryBuilder2Test.java @@ -12,18 +12,18 @@ import persistence.sql.ddl.entity.Person2; @DisplayName("2단계 요구사항 - @Entity, @Id, @Column 어노테이션을 바탕으로 create 쿼리 만들어보기") -class QueryTranslator2Test { +class QueryBuilder2Test { - private static final Logger log = org.slf4j.LoggerFactory.getLogger(QueryTranslator2Test.class); + private static final Logger log = org.slf4j.LoggerFactory.getLogger(QueryBuilder2Test.class); private final Class entityClass = Person2.class; - private final QueryTranslator queryTranslator = new QueryTranslator(); + private final QueryTranslator queryBuilder = new QueryTranslator(); @Test @DisplayName("@Entity, @Id, @Column 어노테이션을 바탕으로 create 쿼리 만들어보기") void createDDL() { - String ddl = queryTranslator.getCreateTableQuery(entityClass); + String ddl = queryBuilder.getCreateTableQuery(entityClass); log.debug("DDL: {}", ddl); @@ -34,7 +34,7 @@ void createDDL() { @Test @DisplayName("@Entity, @Id, @Column 어노테이션을 바탕으로 drop 쿼리 만들어보기") void buildDropQuery() { - String dropQuery = queryTranslator.getDropTableQuery(entityClass); + String dropQuery = queryBuilder.getDropTableQuery(entityClass); log.debug("Drop query: {}", dropQuery); @@ -44,7 +44,7 @@ void buildDropQuery() { @Test @DisplayName("클래스 정보를 바탕으로 테이블명 가져오기") void getTableNameByClassName() { - String tableName = queryTranslator.getTableNameFrom(entityClass); + String tableName = queryBuilder.getTableNameFrom(entityClass); log.debug("Table name: {}", tableName); @@ -54,7 +54,7 @@ void getTableNameByClassName() { @Test @DisplayName("클래스 정보와 @Id, @Column 어노테이션을 바탕으로 컬럼 선언문 가져오기") void getColumnDefinitionStatement() { - String columnDefinitionStatement = queryTranslator.getColumnDefinitionsFrom(entityClass); + String columnDefinitionStatement = queryBuilder.getColumnDefinitionsFrom(entityClass); log.debug("Column definition statement: {}", columnDefinitionStatement); @@ -74,7 +74,7 @@ void getColumnDefinitionStatementFromField( ) throws NoSuchFieldException { Field field = entityClass.getDeclaredField(fieldName); - String actualColumnDefinitionStatement = queryTranslator.getColumnDefinitionFrom(field); + String actualColumnDefinitionStatement = queryBuilder.getColumnDefinitionFrom(field); assertThat(actualColumnDefinitionStatement).isEqualTo(expectedColumnDefinitionStatement); } diff --git a/src/test/java/persistence/sql/ddl/query/QueryTranslator3Test.java b/src/test/java/persistence/sql/ddl/query/QueryBuilder3Test.java similarity index 83% rename from src/test/java/persistence/sql/ddl/query/QueryTranslator3Test.java rename to src/test/java/persistence/sql/ddl/query/QueryBuilder3Test.java index 16f8eadfa..e64d5560d 100644 --- a/src/test/java/persistence/sql/ddl/query/QueryTranslator3Test.java +++ b/src/test/java/persistence/sql/ddl/query/QueryBuilder3Test.java @@ -12,18 +12,18 @@ import persistence.sql.ddl.entity.Person3; @DisplayName("3단계 요구사항 - @Entity, @Table, @Id, @Column, @Transient 어노테이션을 바탕으로 create 쿼리 만들어보기") -class QueryTranslator3Test { +class QueryBuilder3Test { - private static final Logger log = org.slf4j.LoggerFactory.getLogger(QueryTranslator3Test.class); + private static final Logger log = org.slf4j.LoggerFactory.getLogger(QueryBuilder3Test.class); private final Class entityClass = Person3.class; - private final QueryTranslator queryTranslator = new QueryTranslator(); + private final QueryTranslator queryBuilder = new QueryTranslator(); @Test @DisplayName("@Entity, @Table, @Id, @Column, @Transient 어노테이션을 바탕으로 create 쿼리 만들어보기") void createDDL() { - String ddl = queryTranslator.getCreateTableQuery(entityClass); + String ddl = queryBuilder.getCreateTableQuery(entityClass); log.debug("DDL: {}", ddl); @@ -34,7 +34,7 @@ void createDDL() { @Test @DisplayName("@Entity, @Table, @Id, @Column, @Transient 어노테이션을 바탕으로 drop 쿼리 만들어보기") void buildDropQuery() { - String dropQuery = queryTranslator.getDropTableQuery(entityClass); + String dropQuery = queryBuilder.getDropTableQuery(entityClass); log.debug("Drop query: {}", dropQuery); @@ -44,7 +44,7 @@ void buildDropQuery() { @Test @DisplayName("클래스 정보와 @Table 어노테이션을 바탕으로 테이블명 가져오기") void getTableNameByClassName() { - String tableName = queryTranslator.getTableNameFrom(entityClass); + String tableName = queryBuilder.getTableNameFrom(entityClass); log.debug("Table name: {}", tableName); @@ -54,7 +54,7 @@ void getTableNameByClassName() { @Test @DisplayName("클래스 정보와 @Id, @Column, @Transient 어노테이션을 바탕으로 컬럼 선언문 가져오기") void getColumnDefinitionStatement() { - String columnDefinitionStatement = queryTranslator.getColumnDefinitionsFrom(entityClass); + String columnDefinitionStatement = queryBuilder.getColumnDefinitionsFrom(entityClass); log.debug("Column definition statement: {}", columnDefinitionStatement); @@ -74,7 +74,7 @@ void getColumnDefinitionStatementFromField( ) throws NoSuchFieldException { Field field = entityClass.getDeclaredField(fieldName); - String actualColumnDefinitionStatement = queryTranslator.getColumnDefinitionFrom(field); + String actualColumnDefinitionStatement = queryBuilder.getColumnDefinitionFrom(field); assertThat(actualColumnDefinitionStatement).isEqualTo(expectedColumnDefinitionStatement); } diff --git a/src/test/java/persistence/sql/ddl/query/QueryTranslator4Test.java b/src/test/java/persistence/sql/ddl/query/QueryBuilder4Test.java similarity index 79% rename from src/test/java/persistence/sql/ddl/query/QueryTranslator4Test.java rename to src/test/java/persistence/sql/ddl/query/QueryBuilder4Test.java index 7d6e3f6d2..7ab4ffca6 100644 --- a/src/test/java/persistence/sql/ddl/query/QueryTranslator4Test.java +++ b/src/test/java/persistence/sql/ddl/query/QueryBuilder4Test.java @@ -9,17 +9,17 @@ import persistence.sql.ddl.entity.Person4; @DisplayName("4단계 요구사항 - @Entity, @Table(schema), @Id, @Column, @Transient 어노테이션을 바탕으로 drop 쿼리 만들어보기") -class QueryTranslator4Test { - private static final Logger log = org.slf4j.LoggerFactory.getLogger(QueryTranslator4Test.class); +class QueryBuilder4Test { + private static final Logger log = org.slf4j.LoggerFactory.getLogger(QueryBuilder4Test.class); private final Class entityClass = Person4.class; - private final QueryTranslator queryTranslator = new QueryTranslator(); + private final QueryTranslator queryBuilder = new QueryTranslator(); @Test @DisplayName("@Entity, @Table(schema), @Id, @Column, @Transient 어노테이션을 바탕으로 drop 쿼리 만들어보기") void buildDropQuery() { - String dropQuery = queryTranslator.getDropTableQuery(entityClass); + String dropQuery = queryBuilder.getDropTableQuery(entityClass); log.debug("Drop query: {}", dropQuery); diff --git a/src/test/java/persistence/sql/ddl/query/QueryTranslatorTest.java b/src/test/java/persistence/sql/ddl/query/QueryBuilderTest.java similarity index 79% rename from src/test/java/persistence/sql/ddl/query/QueryTranslatorTest.java rename to src/test/java/persistence/sql/ddl/query/QueryBuilderTest.java index 0698b0693..dbbd74632 100644 --- a/src/test/java/persistence/sql/ddl/query/QueryTranslatorTest.java +++ b/src/test/java/persistence/sql/ddl/query/QueryBuilderTest.java @@ -12,17 +12,17 @@ import persistence.sql.ddl.entity.Person; import persistence.sql.ddl.entity.Person4; -class QueryTranslatorTest { - private static final Logger log = org.slf4j.LoggerFactory.getLogger(QueryTranslatorTest.class); +class QueryBuilderTest { + private static final Logger log = org.slf4j.LoggerFactory.getLogger(QueryBuilderTest.class); private final Class entityClass = Person.class; - private final QueryTranslator queryTranslator = new QueryTranslator(); + private final QueryTranslator queryBuilder = new QueryTranslator(); @Test @DisplayName("@Entity, @Table, @Id, @Column, @Transient 어노테이션을 바탕으로 create 쿼리 만들어보기") void createDDL() { - String ddl = queryTranslator.getCreateTableQuery(entityClass); + String ddl = queryBuilder.getCreateTableQuery(entityClass); log.debug("DDL: {}", ddl); @@ -33,7 +33,7 @@ void createDDL() { @Test @DisplayName("@Entity, @Table(schema), @Id, @Column, @Transient 어노테이션을 바탕으로 create 쿼리 만들어보기") void createDDLWithSchema() { - String ddl = queryTranslator.getCreateTableQuery(Person4.class); + String ddl = queryBuilder.getCreateTableQuery(Person4.class); log.debug("DDL: {}", ddl); @@ -44,7 +44,7 @@ void createDDLWithSchema() { @Test @DisplayName("@Entity, @Table, @Id, @Column, @Transient 어노테이션을 바탕으로 drop 쿼리 만들어보기") void buildDropQuery() { - String dropQuery = queryTranslator.getDropTableQuery(entityClass); + String dropQuery = queryBuilder.getDropTableQuery(entityClass); log.debug("Drop query: {}", dropQuery); @@ -54,7 +54,7 @@ void buildDropQuery() { @Test @DisplayName("@Entity, @Table(schema), @Id, @Column, @Transient 어노테이션을 바탕으로 drop 쿼리 만들어보기") void buildDropQueryWithSchema() { - String dropQuery = queryTranslator.getDropTableQuery(Person4.class); + String dropQuery = queryBuilder.getDropTableQuery(Person4.class); log.debug("Drop query: {}", dropQuery); @@ -64,7 +64,7 @@ void buildDropQueryWithSchema() { @Test @DisplayName("클래스 정보와 @Table 어노테이션을 바탕으로 테이블명 가져오기") void getTableName() { - String tableName = queryTranslator.getTableNameFrom(entityClass); + String tableName = queryBuilder.getTableNameFrom(entityClass); log.debug("Table name: {}", tableName); @@ -74,7 +74,7 @@ void getTableName() { @Test @DisplayName("클래스 정보와 @Table(schema) 어노테이션을 바탕으로 테이블명 가져오기") void getTableNameWithSchema() { - String tableName = queryTranslator.getTableNameFrom(Person4.class); + String tableName = queryBuilder.getTableNameFrom(Person4.class); log.debug("Table name: {}", tableName); @@ -84,7 +84,7 @@ void getTableNameWithSchema() { @Test @DisplayName("클래스 정보와 @Id, @Column, @Transient 어노테이션을 바탕으로 컬럼 선언문 가져오기") void getColumnDefinitionStatement() { - String columnDefinitionStatement = queryTranslator.getColumnDefinitionsFrom(entityClass); + String columnDefinitionStatement = queryBuilder.getColumnDefinitionsFrom(entityClass); log.debug("Column definition statement: {}", columnDefinitionStatement); @@ -104,7 +104,7 @@ void getColumnDefinitionStatementFromField( ) throws NoSuchFieldException { Field field = entityClass.getDeclaredField(fieldName); - String actualColumnDefinitionStatement = queryTranslator.getColumnDefinitionFrom(field); + String actualColumnDefinitionStatement = queryBuilder.getColumnDefinitionFrom(field); assertThat(actualColumnDefinitionStatement).isEqualTo(expectedColumnDefinitionStatement); } @@ -114,7 +114,7 @@ void getColumnDefinitionStatementFromField( void getInsertQuery() { Person person = new Person("홍길동", 20, "test@gamil.com"); - String insertQuery = queryTranslator.getInsertQuery(person); + String insertQuery = queryBuilder.getInsertQuery(person); assertThat(insertQuery).isEqualTo("INSERT INTO users (nick_name, old, email) VALUES ('홍길동', 20, 'test@gamil.com')"); } @@ -123,7 +123,7 @@ void getInsertQuery() { @DisplayName("요구사항 2 - 위의 정보를 바탕으로 모두 조회(findAll) 기능 구현해보기") void getSelectAllQuery() { // when - String selectAllQuery = queryTranslator.getSelectAllQuery(Person.class); + String selectAllQuery = queryBuilder.getSelectAllQuery(Person.class); // then assertThat(selectAllQuery).isEqualTo("SELECT id, nick_name, old, email FROM users"); @@ -133,7 +133,7 @@ void getSelectAllQuery() { @DisplayName("요구사항 3 - 위의 정보를 바탕으로 단건 조회(findById) 기능 구현해보기") void getSelectByIdQuery() { // when - String selectByIdQuery = queryTranslator.getSelectByIdQuery(Person.class, 1L); + String selectByIdQuery = queryBuilder.getSelectByIdQuery(Person.class, 1L); // then assertThat(selectByIdQuery).isEqualTo("SELECT id, nick_name, old, email FROM users WHERE id = 1"); @@ -143,7 +143,7 @@ void getSelectByIdQuery() { @DisplayName("요구사항 3 - 위의 정보를 바탕으로 count 쿼리 만들어보기") void getSelectCountQuery() { // when - String selectCountQuery = queryTranslator.getSelectCountQuery(Person.class); + String selectCountQuery = queryBuilder.getSelectCountQuery(Person.class); // then assertThat(selectCountQuery).isEqualTo("SELECT COUNT(id) FROM users"); @@ -157,9 +157,9 @@ void getDeleteAllQuery() { Person givenEntity = new Person(givenId, "홍길동", 20, "test@gmail.com"); // when - String deleteAllQuery = queryTranslator.getDeleteAllQuery(Person.class); - String deleteByIdQuery = queryTranslator.getDeleteByIdQuery(Person.class, givenId); - String deleteQueryFromEntity = queryTranslator.getDeleteQueryFromEntity(givenEntity); + String deleteAllQuery = queryBuilder.getDeleteAllQuery(Person.class); + String deleteByIdQuery = queryBuilder.getDeleteByIdQuery(Person.class, givenId); + String deleteQueryFromEntity = queryBuilder.getDeleteQueryFromEntity(givenEntity); // then assertThat(deleteAllQuery).isEqualTo("DELETE FROM users"); diff --git a/src/test/java/persistence/sql/dml/ColumnValueTranslatorTest.java b/src/test/java/persistence/sql/dml/ColumnValueTranslatorTest.java deleted file mode 100644 index ce362481f..000000000 --- a/src/test/java/persistence/sql/dml/ColumnValueTranslatorTest.java +++ /dev/null @@ -1,25 +0,0 @@ -package persistence.sql.dml; - -import static org.assertj.core.api.Assertions.assertThat; - -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; -import persistence.sql.ddl.entity.Person; - -class ColumnValueTranslatorTest { - - private final ColumnValueTranslator columnValueTranslator = new ColumnValueTranslator(); - - @DisplayName("엔티티 객체를 통해서 정상적으로 Column Value Clause 쿼리를 가져올 수 있다.") - @Test - void getColumnValueClause() { - // given - Person person = new Person("nick", 20, "nick@gmail.com"); - - // when - String columnClause = columnValueTranslator.getColumnValueClause(person); - - // then - assertThat(columnClause).isEqualTo("'nick', 20, 'nick@gmail.com'"); - } -} From 8ecc65829e26daee26b4388b5d472ceea5789976 Mon Sep 17 00:00:00 2001 From: socar-shinyoung Date: Mon, 11 Mar 2024 23:03:03 +0900 Subject: [PATCH 4/4] =?UTF-8?q?style:=20Translator=20->=20Builder=20?= =?UTF-8?q?=ED=81=B4=EB=9E=98=EC=8A=A4=20=EB=AA=85=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/persistence/Application.java | 10 ++--- .../entity/EntityRowMapperFactory.java | 8 ++-- .../entity/impl/EntityManagerImpl.java | 8 ++-- ...nslator.java => AbstractQueryBuilder.java} | 4 +- ...QueryTranslator.java => QueryBuilder.java} | 38 +++++++++---------- ...ranslator.java => ColumnQueryBuilder.java} | 2 +- ...ranslator.java => CreateQueryBuilder.java} | 8 ++-- ...yTranslator.java => DropQueryBuilder.java} | 4 +- ...ranslator.java => DeleteQueryBuilder.java} | 6 +-- ...ranslator.java => InsertQueryBuilder.java} | 6 +-- ...ranslator.java => SelectQueryBuilder.java} | 6 +-- .../entity/impl/EntityManagerImplTest.java | 10 ++--- .../sql/ddl/query/QueryBuilder1Test.java | 4 +- .../sql/ddl/query/QueryBuilder2Test.java | 4 +- .../sql/ddl/query/QueryBuilder3Test.java | 4 +- .../sql/ddl/query/QueryBuilder4Test.java | 4 +- .../sql/ddl/query/QueryBuilderTest.java | 4 +- 17 files changed, 65 insertions(+), 65 deletions(-) rename src/main/java/persistence/sql/{AbstractQueryTranslator.java => AbstractQueryBuilder.java} (96%) rename src/main/java/persistence/sql/{QueryTranslator.java => QueryBuilder.java} (61%) rename src/main/java/persistence/sql/ddl/{ColumnQueryTranslator.java => ColumnQueryBuilder.java} (96%) rename src/main/java/persistence/sql/ddl/{CreateQueryTranslator.java => CreateQueryBuilder.java} (90%) rename src/main/java/persistence/sql/ddl/{DropQueryTranslator.java => DropQueryBuilder.java} (76%) rename src/main/java/persistence/sql/dml/{DeleteQueryTranslator.java => DeleteQueryBuilder.java} (95%) rename src/main/java/persistence/sql/dml/{InsertQueryTranslator.java => InsertQueryBuilder.java} (91%) rename src/main/java/persistence/sql/dml/{SelectQueryTranslator.java => SelectQueryBuilder.java} (94%) diff --git a/src/main/java/persistence/Application.java b/src/main/java/persistence/Application.java index c0963c328..33b4833ea 100644 --- a/src/main/java/persistence/Application.java +++ b/src/main/java/persistence/Application.java @@ -7,7 +7,7 @@ import jdbc.RowMapper; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import persistence.sql.QueryTranslator; +import persistence.sql.QueryBuilder; import persistence.sql.ddl.entity.Person; public class Application { @@ -28,7 +28,7 @@ public static void main(String[] args) { final JdbcTemplate jdbcTemplate = new JdbcTemplate(server.getConnection()); - QueryTranslator queryBuilder = new QueryTranslator(); + QueryBuilder queryBuilder = new QueryBuilder(); jdbcTemplate.execute(queryBuilder.getCreateTableQuery(Person.class)); @@ -50,7 +50,7 @@ public static void main(String[] args) { } } - private static void querySelectById(JdbcTemplate jdbcTemplate, QueryTranslator queryBuilder) { + private static void querySelectById(JdbcTemplate jdbcTemplate, QueryBuilder queryBuilder) { Person person = jdbcTemplate.queryForObject( queryBuilder.getSelectByIdQuery(Person.class, 2L), rowMapper @@ -59,7 +59,7 @@ private static void querySelectById(JdbcTemplate jdbcTemplate, QueryTranslator q logger.info("Person: {}", person); } - private static void querySelectAll(JdbcTemplate jdbcTemplate, QueryTranslator queryBuilder) { + private static void querySelectAll(JdbcTemplate jdbcTemplate, QueryBuilder queryBuilder) { List persons = jdbcTemplate.query( queryBuilder.getSelectAllQuery(Person.class), rowMapper @@ -68,7 +68,7 @@ private static void querySelectAll(JdbcTemplate jdbcTemplate, QueryTranslator qu persons.forEach(person -> logger.info("Person: {}", person)); } - private static void executeInitializedQuery(JdbcTemplate jdbcTemplate, QueryTranslator queryBuilder) { + private static void executeInitializedQuery(JdbcTemplate jdbcTemplate, QueryBuilder queryBuilder) { List persons = List.of( new Person("John", 23, "john@gmail.com"), new Person("Smith", 33, "smith@gmail.com"), diff --git a/src/main/java/persistence/entity/EntityRowMapperFactory.java b/src/main/java/persistence/entity/EntityRowMapperFactory.java index bc330b122..7fd1ce4b3 100644 --- a/src/main/java/persistence/entity/EntityRowMapperFactory.java +++ b/src/main/java/persistence/entity/EntityRowMapperFactory.java @@ -7,7 +7,7 @@ import java.util.stream.Collectors; import jdbc.RowMapper; import persistence.exception.ReflectionRuntimeException; -import persistence.sql.ddl.ColumnQueryTranslator; +import persistence.sql.ddl.ColumnQueryBuilder; public class EntityRowMapperFactory { @@ -30,17 +30,17 @@ public static EntityRowMapperFactory getInstance() { public RowMapper getRowMapper(Class entityClass) { return resultSet -> { try { - ColumnQueryTranslator columnQueryTranslator = new ColumnQueryTranslator(); + ColumnQueryBuilder columnQueryBuilder = new ColumnQueryBuilder(); Constructor declaredConstructor = entityClass.getDeclaredConstructor(); declaredConstructor.setAccessible(true); T entity = entityClass.getDeclaredConstructor().newInstance(); - List columnFieldList = columnQueryTranslator.getColumnFieldStream(entityClass) + List columnFieldList = columnQueryBuilder.getColumnFieldStream(entityClass) .collect(Collectors.toList()); for (Field field : columnFieldList) { field.setAccessible(true); - String columnName = columnQueryTranslator.getColumnNameFrom(field); + String columnName = columnQueryBuilder.getColumnNameFrom(field); field.set(entity, resultSet.getObject(columnName)); } diff --git a/src/main/java/persistence/entity/impl/EntityManagerImpl.java b/src/main/java/persistence/entity/impl/EntityManagerImpl.java index f00b95273..319e01b86 100644 --- a/src/main/java/persistence/entity/impl/EntityManagerImpl.java +++ b/src/main/java/persistence/entity/impl/EntityManagerImpl.java @@ -3,18 +3,18 @@ import jdbc.JdbcTemplate; import persistence.entity.EntityManager; import persistence.entity.EntityRowMapperFactory; -import persistence.sql.QueryTranslator; +import persistence.sql.QueryBuilder; public class EntityManagerImpl implements EntityManager { private final JdbcTemplate jdbcTemplate; - private final QueryTranslator queryBuilder; + private final QueryBuilder queryBuilder; public EntityManagerImpl(JdbcTemplate jdbcTemplate) { - this(jdbcTemplate, new QueryTranslator()); + this(jdbcTemplate, new QueryBuilder()); } - public EntityManagerImpl(JdbcTemplate jdbcTemplate, QueryTranslator queryBuilder) { + public EntityManagerImpl(JdbcTemplate jdbcTemplate, QueryBuilder queryBuilder) { this.jdbcTemplate = jdbcTemplate; this.queryBuilder = queryBuilder; } diff --git a/src/main/java/persistence/sql/AbstractQueryTranslator.java b/src/main/java/persistence/sql/AbstractQueryBuilder.java similarity index 96% rename from src/main/java/persistence/sql/AbstractQueryTranslator.java rename to src/main/java/persistence/sql/AbstractQueryBuilder.java index 627282724..6e5e40dd3 100644 --- a/src/main/java/persistence/sql/AbstractQueryTranslator.java +++ b/src/main/java/persistence/sql/AbstractQueryBuilder.java @@ -9,9 +9,9 @@ import java.util.stream.Stream; import persistence.exception.UnsupportedClassException; -public abstract class AbstractQueryTranslator { +public abstract class AbstractQueryBuilder { - protected AbstractQueryTranslator() { + protected AbstractQueryBuilder() { } diff --git a/src/main/java/persistence/sql/QueryTranslator.java b/src/main/java/persistence/sql/QueryBuilder.java similarity index 61% rename from src/main/java/persistence/sql/QueryTranslator.java rename to src/main/java/persistence/sql/QueryBuilder.java index 4eb97dc74..79246615e 100644 --- a/src/main/java/persistence/sql/QueryTranslator.java +++ b/src/main/java/persistence/sql/QueryBuilder.java @@ -2,38 +2,38 @@ import java.lang.reflect.Field; -import persistence.sql.ddl.CreateQueryTranslator; -import persistence.sql.ddl.DropQueryTranslator; +import persistence.sql.ddl.CreateQueryBuilder; +import persistence.sql.ddl.DropQueryBuilder; import persistence.sql.ddl.TableQueryBuilder; -import persistence.sql.dml.DeleteQueryTranslator; -import persistence.sql.dml.InsertQueryTranslator; -import persistence.sql.dml.SelectQueryTranslator; +import persistence.sql.dml.DeleteQueryBuilder; +import persistence.sql.dml.InsertQueryBuilder; +import persistence.sql.dml.SelectQueryBuilder; -public class QueryTranslator extends AbstractQueryTranslator { +public class QueryBuilder extends AbstractQueryBuilder { private final TableQueryBuilder tableQueryBuilder; - private final SelectQueryTranslator selectQueryBuilder; + private final SelectQueryBuilder selectQueryBuilder; - private final DeleteQueryTranslator deleteQueryBuilder; + private final DeleteQueryBuilder deleteQueryBuilder; - private final InsertQueryTranslator insertQueryTranslator; + private final InsertQueryBuilder insertQueryTranslator; - private final DropQueryTranslator dropQueryTranslator; + private final DropQueryBuilder dropQueryBuilder; - private final CreateQueryTranslator createQueryBuilder; + private final CreateQueryBuilder createQueryBuilder; - public QueryTranslator() { + public QueryBuilder() { this(new TableQueryBuilder()); } - public QueryTranslator(TableQueryBuilder tableQueryBuilder) { + public QueryBuilder(TableQueryBuilder tableQueryBuilder) { this.tableQueryBuilder = tableQueryBuilder; - this.selectQueryBuilder = new SelectQueryTranslator(tableQueryBuilder); - this.deleteQueryBuilder = new DeleteQueryTranslator(tableQueryBuilder); - this.insertQueryTranslator = new InsertQueryTranslator(tableQueryBuilder); - this.dropQueryTranslator = new DropQueryTranslator(tableQueryBuilder); - this.createQueryBuilder = new CreateQueryTranslator(tableQueryBuilder); + this.selectQueryBuilder = new SelectQueryBuilder(tableQueryBuilder); + this.deleteQueryBuilder = new DeleteQueryBuilder(tableQueryBuilder); + this.insertQueryTranslator = new InsertQueryBuilder(tableQueryBuilder); + this.dropQueryBuilder = new DropQueryBuilder(tableQueryBuilder); + this.createQueryBuilder = new CreateQueryBuilder(tableQueryBuilder); } public String getCreateTableQuery(final Class entityClass) { @@ -41,7 +41,7 @@ public String getCreateTableQuery(final Class entityClass) { } public String getDropTableQuery(Class entityClass) { - return dropQueryTranslator.getDropTableQuery(entityClass); + return dropQueryBuilder.getDropTableQuery(entityClass); } public String getInsertQuery(Object entity) { diff --git a/src/main/java/persistence/sql/ddl/ColumnQueryTranslator.java b/src/main/java/persistence/sql/ddl/ColumnQueryBuilder.java similarity index 96% rename from src/main/java/persistence/sql/ddl/ColumnQueryTranslator.java rename to src/main/java/persistence/sql/ddl/ColumnQueryBuilder.java index c9407bc48..3f591be97 100644 --- a/src/main/java/persistence/sql/ddl/ColumnQueryTranslator.java +++ b/src/main/java/persistence/sql/ddl/ColumnQueryBuilder.java @@ -8,7 +8,7 @@ import java.util.Comparator; import java.util.stream.Stream; -public class ColumnQueryTranslator { +public class ColumnQueryBuilder { public String getColumnNameFrom(Field field) { if (!field.isAnnotationPresent(Column.class)) { diff --git a/src/main/java/persistence/sql/ddl/CreateQueryTranslator.java b/src/main/java/persistence/sql/ddl/CreateQueryBuilder.java similarity index 90% rename from src/main/java/persistence/sql/ddl/CreateQueryTranslator.java rename to src/main/java/persistence/sql/ddl/CreateQueryBuilder.java index 03bb19f63..d17085660 100644 --- a/src/main/java/persistence/sql/ddl/CreateQueryTranslator.java +++ b/src/main/java/persistence/sql/ddl/CreateQueryBuilder.java @@ -5,21 +5,21 @@ import java.lang.reflect.Field; import java.util.stream.Collectors; import java.util.stream.Stream; -import persistence.sql.AbstractQueryTranslator; +import persistence.sql.AbstractQueryBuilder; import persistence.sql.ddl.common.StringConstants; import persistence.sql.ddl.constraints.strategy.ConstraintsStrategy; import persistence.sql.ddl.constraints.strategy.DefaultConstraintsStrategy; import persistence.sql.ddl.type.DataTypeMapping; import persistence.sql.ddl.type.impl.DefaultDataTypeMapping; -public class CreateQueryTranslator extends AbstractQueryTranslator { +public class CreateQueryBuilder extends AbstractQueryBuilder { private final TableQueryBuilder tableQueryBuilder; private final DataTypeMapping dataTypeMapping; private final ConstraintsStrategy constraintsStrategy; - public CreateQueryTranslator(TableQueryBuilder tableQueryBuilder) { + public CreateQueryBuilder(TableQueryBuilder tableQueryBuilder) { this( tableQueryBuilder, new DefaultDataTypeMapping(), @@ -27,7 +27,7 @@ public CreateQueryTranslator(TableQueryBuilder tableQueryBuilder) { ); } - public CreateQueryTranslator( + public CreateQueryBuilder( TableQueryBuilder tableQueryBuilder, DataTypeMapping dataTypeMapping, ConstraintsStrategy constraintsStrategy diff --git a/src/main/java/persistence/sql/ddl/DropQueryTranslator.java b/src/main/java/persistence/sql/ddl/DropQueryBuilder.java similarity index 76% rename from src/main/java/persistence/sql/ddl/DropQueryTranslator.java rename to src/main/java/persistence/sql/ddl/DropQueryBuilder.java index fb28f0b2e..455a82fe6 100644 --- a/src/main/java/persistence/sql/ddl/DropQueryTranslator.java +++ b/src/main/java/persistence/sql/ddl/DropQueryBuilder.java @@ -1,9 +1,9 @@ package persistence.sql.ddl; -public class DropQueryTranslator { +public class DropQueryBuilder { private final TableQueryBuilder tableQueryBuilder; - public DropQueryTranslator(TableQueryBuilder tableQueryBuilder) { + public DropQueryBuilder(TableQueryBuilder tableQueryBuilder) { this.tableQueryBuilder = tableQueryBuilder; } diff --git a/src/main/java/persistence/sql/dml/DeleteQueryTranslator.java b/src/main/java/persistence/sql/dml/DeleteQueryBuilder.java similarity index 95% rename from src/main/java/persistence/sql/dml/DeleteQueryTranslator.java rename to src/main/java/persistence/sql/dml/DeleteQueryBuilder.java index 846c7466a..5acdcc057 100644 --- a/src/main/java/persistence/sql/dml/DeleteQueryTranslator.java +++ b/src/main/java/persistence/sql/dml/DeleteQueryBuilder.java @@ -5,13 +5,13 @@ import jakarta.persistence.Id; import java.lang.reflect.Field; import java.util.Arrays; -import persistence.sql.AbstractQueryTranslator; +import persistence.sql.AbstractQueryBuilder; import persistence.sql.ddl.TableQueryBuilder; -public class DeleteQueryTranslator extends AbstractQueryTranslator { +public class DeleteQueryBuilder extends AbstractQueryBuilder { private final TableQueryBuilder tableQueryBuilder; - public DeleteQueryTranslator( + public DeleteQueryBuilder( TableQueryBuilder tableQueryBuilder ) { this.tableQueryBuilder = tableQueryBuilder; diff --git a/src/main/java/persistence/sql/dml/InsertQueryTranslator.java b/src/main/java/persistence/sql/dml/InsertQueryBuilder.java similarity index 91% rename from src/main/java/persistence/sql/dml/InsertQueryTranslator.java rename to src/main/java/persistence/sql/dml/InsertQueryBuilder.java index c891b54de..967278170 100644 --- a/src/main/java/persistence/sql/dml/InsertQueryTranslator.java +++ b/src/main/java/persistence/sql/dml/InsertQueryBuilder.java @@ -8,13 +8,13 @@ import java.util.Arrays; import java.util.Comparator; import java.util.stream.Collectors; -import persistence.sql.AbstractQueryTranslator; +import persistence.sql.AbstractQueryBuilder; import persistence.sql.ddl.TableQueryBuilder; -public class InsertQueryTranslator extends AbstractQueryTranslator { +public class InsertQueryBuilder extends AbstractQueryBuilder { private final TableQueryBuilder tableQueryBuilder; - public InsertQueryTranslator(TableQueryBuilder tableQueryBuilder) { + public InsertQueryBuilder(TableQueryBuilder tableQueryBuilder) { this.tableQueryBuilder = tableQueryBuilder; } diff --git a/src/main/java/persistence/sql/dml/SelectQueryTranslator.java b/src/main/java/persistence/sql/dml/SelectQueryBuilder.java similarity index 94% rename from src/main/java/persistence/sql/dml/SelectQueryTranslator.java rename to src/main/java/persistence/sql/dml/SelectQueryBuilder.java index d00eab3a8..36267af59 100644 --- a/src/main/java/persistence/sql/dml/SelectQueryTranslator.java +++ b/src/main/java/persistence/sql/dml/SelectQueryBuilder.java @@ -7,13 +7,13 @@ import java.lang.reflect.Field; import java.util.Arrays; import java.util.stream.Collectors; -import persistence.sql.AbstractQueryTranslator; +import persistence.sql.AbstractQueryBuilder; import persistence.sql.ddl.TableQueryBuilder; -public class SelectQueryTranslator extends AbstractQueryTranslator { +public class SelectQueryBuilder extends AbstractQueryBuilder { private final TableQueryBuilder tableQueryBuilder; - public SelectQueryTranslator( + public SelectQueryBuilder( TableQueryBuilder tableQueryBuilder ) { this.tableQueryBuilder = tableQueryBuilder; diff --git a/src/test/java/persistence/entity/impl/EntityManagerImplTest.java b/src/test/java/persistence/entity/impl/EntityManagerImplTest.java index d884da91b..15d6d69a6 100644 --- a/src/test/java/persistence/entity/impl/EntityManagerImplTest.java +++ b/src/test/java/persistence/entity/impl/EntityManagerImplTest.java @@ -23,7 +23,7 @@ import org.junit.jupiter.params.provider.MethodSource; import org.junit.jupiter.params.provider.ValueSource; import persistence.entity.EntityManager; -import persistence.sql.QueryTranslator; +import persistence.sql.QueryBuilder; import persistence.sql.ddl.entity.Person; class EntityManagerImplTest { @@ -55,7 +55,7 @@ void setUp() throws SQLException { entityManager = new EntityManagerImpl(jdbcTemplate); - QueryTranslator queryBuilder = new QueryTranslator(); + QueryBuilder queryBuilder = new QueryBuilder(); jdbcTemplate.execute(queryBuilder.getCreateTableQuery(Person.class)); } @@ -129,7 +129,7 @@ void remove(Person givenPerson) throws SQLException { private void initializeTable() throws SQLException { JdbcTemplate jdbcTemplate = getJdbcTemplate(); - QueryTranslator queryBuilder = new QueryTranslator(); + QueryBuilder queryBuilder = new QueryBuilder(); for (Person person : idToPersonMap.values()) { jdbcTemplate.execute(queryBuilder.getInsertQuery(person)); @@ -139,7 +139,7 @@ private void initializeTable() throws SQLException { private void dropTable() throws SQLException { JdbcTemplate jdbcTemplate = getJdbcTemplate(); - QueryTranslator queryBuilder = new QueryTranslator(); + QueryBuilder queryBuilder = new QueryBuilder(); jdbcTemplate.execute(queryBuilder.getDropTableQuery(Person.class)); } @@ -147,7 +147,7 @@ private void dropTable() throws SQLException { private Integer selectCountOfTable() throws SQLException { JdbcTemplate jdbcTemplate = getJdbcTemplate(); - QueryTranslator queryBuilder = new QueryTranslator(); + QueryBuilder queryBuilder = new QueryBuilder(); return jdbcTemplate.queryForObject(queryBuilder.getSelectCountQuery(Person.class), resultSet -> resultSet.getInt(1)); diff --git a/src/test/java/persistence/sql/ddl/query/QueryBuilder1Test.java b/src/test/java/persistence/sql/ddl/query/QueryBuilder1Test.java index c7afc7366..bd65f83dc 100644 --- a/src/test/java/persistence/sql/ddl/query/QueryBuilder1Test.java +++ b/src/test/java/persistence/sql/ddl/query/QueryBuilder1Test.java @@ -8,7 +8,7 @@ import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.CsvSource; import org.slf4j.Logger; -import persistence.sql.QueryTranslator; +import persistence.sql.QueryBuilder; import persistence.sql.ddl.entity.Person1; @DisplayName("1단계 요구사항 - @Entity, @Id 어노테이션을 바탕으로 create 쿼리 만들어보기") @@ -17,7 +17,7 @@ class QueryBuilder1Test { private final Class entityClass = Person1.class; - private final QueryTranslator queryBuilder = new QueryTranslator(); + private final QueryBuilder queryBuilder = new QueryBuilder(); @Test @DisplayName("@Entity, @Id 어노테이션을 바탕으로 create 쿼리 만들어보기") diff --git a/src/test/java/persistence/sql/ddl/query/QueryBuilder2Test.java b/src/test/java/persistence/sql/ddl/query/QueryBuilder2Test.java index 43e22ac46..846b667e3 100644 --- a/src/test/java/persistence/sql/ddl/query/QueryBuilder2Test.java +++ b/src/test/java/persistence/sql/ddl/query/QueryBuilder2Test.java @@ -8,7 +8,7 @@ import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.CsvSource; import org.slf4j.Logger; -import persistence.sql.QueryTranslator; +import persistence.sql.QueryBuilder; import persistence.sql.ddl.entity.Person2; @DisplayName("2단계 요구사항 - @Entity, @Id, @Column 어노테이션을 바탕으로 create 쿼리 만들어보기") @@ -18,7 +18,7 @@ class QueryBuilder2Test { private final Class entityClass = Person2.class; - private final QueryTranslator queryBuilder = new QueryTranslator(); + private final QueryBuilder queryBuilder = new QueryBuilder(); @Test @DisplayName("@Entity, @Id, @Column 어노테이션을 바탕으로 create 쿼리 만들어보기") diff --git a/src/test/java/persistence/sql/ddl/query/QueryBuilder3Test.java b/src/test/java/persistence/sql/ddl/query/QueryBuilder3Test.java index e64d5560d..d5e06361d 100644 --- a/src/test/java/persistence/sql/ddl/query/QueryBuilder3Test.java +++ b/src/test/java/persistence/sql/ddl/query/QueryBuilder3Test.java @@ -8,7 +8,7 @@ import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.CsvSource; import org.slf4j.Logger; -import persistence.sql.QueryTranslator; +import persistence.sql.QueryBuilder; import persistence.sql.ddl.entity.Person3; @DisplayName("3단계 요구사항 - @Entity, @Table, @Id, @Column, @Transient 어노테이션을 바탕으로 create 쿼리 만들어보기") @@ -18,7 +18,7 @@ class QueryBuilder3Test { private final Class entityClass = Person3.class; - private final QueryTranslator queryBuilder = new QueryTranslator(); + private final QueryBuilder queryBuilder = new QueryBuilder(); @Test @DisplayName("@Entity, @Table, @Id, @Column, @Transient 어노테이션을 바탕으로 create 쿼리 만들어보기") diff --git a/src/test/java/persistence/sql/ddl/query/QueryBuilder4Test.java b/src/test/java/persistence/sql/ddl/query/QueryBuilder4Test.java index 7ab4ffca6..896edc1cc 100644 --- a/src/test/java/persistence/sql/ddl/query/QueryBuilder4Test.java +++ b/src/test/java/persistence/sql/ddl/query/QueryBuilder4Test.java @@ -5,7 +5,7 @@ import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import org.slf4j.Logger; -import persistence.sql.QueryTranslator; +import persistence.sql.QueryBuilder; import persistence.sql.ddl.entity.Person4; @DisplayName("4단계 요구사항 - @Entity, @Table(schema), @Id, @Column, @Transient 어노테이션을 바탕으로 drop 쿼리 만들어보기") @@ -14,7 +14,7 @@ class QueryBuilder4Test { private final Class entityClass = Person4.class; - private final QueryTranslator queryBuilder = new QueryTranslator(); + private final QueryBuilder queryBuilder = new QueryBuilder(); @Test @DisplayName("@Entity, @Table(schema), @Id, @Column, @Transient 어노테이션을 바탕으로 drop 쿼리 만들어보기") diff --git a/src/test/java/persistence/sql/ddl/query/QueryBuilderTest.java b/src/test/java/persistence/sql/ddl/query/QueryBuilderTest.java index dbbd74632..a113ac22f 100644 --- a/src/test/java/persistence/sql/ddl/query/QueryBuilderTest.java +++ b/src/test/java/persistence/sql/ddl/query/QueryBuilderTest.java @@ -8,7 +8,7 @@ import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.CsvSource; import org.slf4j.Logger; -import persistence.sql.QueryTranslator; +import persistence.sql.QueryBuilder; import persistence.sql.ddl.entity.Person; import persistence.sql.ddl.entity.Person4; @@ -17,7 +17,7 @@ class QueryBuilderTest { private final Class entityClass = Person.class; - private final QueryTranslator queryBuilder = new QueryTranslator(); + private final QueryBuilder queryBuilder = new QueryBuilder(); @Test @DisplayName("@Entity, @Table, @Id, @Column, @Transient 어노테이션을 바탕으로 create 쿼리 만들어보기")