-
Notifications
You must be signed in to change notification settings - Fork 71
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
2단계 - QueryBuilder DDL #225
base: parkseoldev
Are you sure you want to change the base?
Changes from all commits
9bf0e73
c50b16f
9f407e4
a596a58
d641d79
41e45ce
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
package domain; | ||
|
||
import jakarta.persistence.Column; | ||
import jakarta.persistence.Entity; | ||
import jakarta.persistence.GeneratedValue; | ||
import jakarta.persistence.GenerationType; | ||
import jakarta.persistence.Id; | ||
import jakarta.persistence.Table; | ||
import jakarta.persistence.Transient; | ||
|
||
@Table(name = "users") | ||
@Entity | ||
public class Person { | ||
|
||
@Id | ||
@GeneratedValue(strategy = GenerationType.IDENTITY) | ||
private Long id; | ||
|
||
@Column(name = "nick_name") | ||
private String name; | ||
|
||
@Column(name = "old") | ||
private Integer age; | ||
|
||
@Column(nullable = false) | ||
private String email; | ||
|
||
@Transient | ||
private Integer index; | ||
} |
Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
@@ -0,0 +1,135 @@ | ||||||||||||||||||||||||||
package persistence.sql.ddl; | ||||||||||||||||||||||||||
|
||||||||||||||||||||||||||
import java.io.Serializable; | ||||||||||||||||||||||||||
import java.lang.reflect.InvocationTargetException; | ||||||||||||||||||||||||||
import java.util.Arrays; | ||||||||||||||||||||||||||
import java.util.List; | ||||||||||||||||||||||||||
import java.util.Map; | ||||||||||||||||||||||||||
import java.lang.reflect.Field; | ||||||||||||||||||||||||||
|
||||||||||||||||||||||||||
import domain.Person; | ||||||||||||||||||||||||||
import jakarta.persistence.Column; | ||||||||||||||||||||||||||
import jakarta.persistence.GeneratedValue; | ||||||||||||||||||||||||||
import jakarta.persistence.Table; | ||||||||||||||||||||||||||
import jakarta.persistence.Transient; | ||||||||||||||||||||||||||
|
||||||||||||||||||||||||||
public class CreateQueryBuilder { | ||||||||||||||||||||||||||
Map<? extends Class<? extends Serializable>, String> javaClassTypeToDbTypes = Map.of( | ||||||||||||||||||||||||||
Long.class, "BIGINT", | ||||||||||||||||||||||||||
String.class, "VARCHAR", | ||||||||||||||||||||||||||
Integer.class, "BIGINT" | ||||||||||||||||||||||||||
); | ||||||||||||||||||||||||||
|
||||||||||||||||||||||||||
public String getCreateTableSql() throws | ||||||||||||||||||||||||||
NoSuchMethodException, | ||||||||||||||||||||||||||
InvocationTargetException, | ||||||||||||||||||||||||||
InstantiationException, | ||||||||||||||||||||||||||
IllegalAccessException { | ||||||||||||||||||||||||||
|
||||||||||||||||||||||||||
Class<Person> personClass = Person.class; | ||||||||||||||||||||||||||
|
||||||||||||||||||||||||||
Person person = personClass.getConstructor().newInstance(); | ||||||||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 사용되지 않는 변수를 제거해주시면 좋을 것 같아요! 🙏 |
||||||||||||||||||||||||||
|
||||||||||||||||||||||||||
// 목표 출력의 목표를 스트링으로 적는다 | ||||||||||||||||||||||||||
/* | ||||||||||||||||||||||||||
CREATE TABLE person ( | ||||||||||||||||||||||||||
id INT AUTO_INCREMENT PRIMARY KEY, | ||||||||||||||||||||||||||
name VARCHAR(50), | ||||||||||||||||||||||||||
age INT, | ||||||||||||||||||||||||||
email VARCHAR(50) NOT NULL, | ||||||||||||||||||||||||||
index INT | ||||||||||||||||||||||||||
); | ||||||||||||||||||||||||||
*/ | ||||||||||||||||||||||||||
// 메서드 분리 (3) | ||||||||||||||||||||||||||
Field idField = Arrays.stream(getDeclaredFields(personClass)) | ||||||||||||||||||||||||||
.filter(x -> x.isAnnotationPresent(GeneratedValue.class)) | ||||||||||||||||||||||||||
.findFirst().get(); | ||||||||||||||||||||||||||
|
||||||||||||||||||||||||||
String idFieldName = idField.getName(); | ||||||||||||||||||||||||||
|
||||||||||||||||||||||||||
String idType = javaClassTypeToDbTypes.get(idField.getType()); | ||||||||||||||||||||||||||
|
||||||||||||||||||||||||||
String generatedValue = generateValue(); | ||||||||||||||||||||||||||
|
||||||||||||||||||||||||||
String primaryKey = getPrimaryKey(); | ||||||||||||||||||||||||||
|
||||||||||||||||||||||||||
String idCombi = String.format("%s %s %s %s,", idFieldName, idType, generatedValue, primaryKey); | ||||||||||||||||||||||||||
|
||||||||||||||||||||||||||
// name VARCHAR(50), | ||||||||||||||||||||||||||
Field nameField = Arrays.stream(getDeclaredFields(personClass)) | ||||||||||||||||||||||||||
.filter(x -> x.isAnnotationPresent(Column.class)).findFirst().get(); | ||||||||||||||||||||||||||
|
||||||||||||||||||||||||||
String name = nameField.getName(); | ||||||||||||||||||||||||||
|
||||||||||||||||||||||||||
String nameType = javaClassTypeToDbTypes.get(nameField.getType()); | ||||||||||||||||||||||||||
|
||||||||||||||||||||||||||
String nameCombi = String.format("%s %s,", name, nameType); | ||||||||||||||||||||||||||
|
||||||||||||||||||||||||||
// age INT, | ||||||||||||||||||||||||||
Field ageField = Arrays.stream(getDeclaredFields(personClass)) | ||||||||||||||||||||||||||
.filter(x -> x.isAnnotationPresent(Column.class)) | ||||||||||||||||||||||||||
.filter(x -> x.getAnnotation(Column.class).name().equals("old")) | ||||||||||||||||||||||||||
.findFirst().get(); | ||||||||||||||||||||||||||
String age = ageField.getName(); | ||||||||||||||||||||||||||
String ageType = javaClassTypeToDbTypes.get(ageField.getType()); | ||||||||||||||||||||||||||
|
||||||||||||||||||||||||||
String ageCombi = String.format("%s %s,", age, ageType); | ||||||||||||||||||||||||||
|
||||||||||||||||||||||||||
// email VARCHAR(50) NOT NULL, | ||||||||||||||||||||||||||
Field emailField = Arrays.stream(getDeclaredFields(personClass)) | ||||||||||||||||||||||||||
.filter(x -> x.isAnnotationPresent(Column.class)) | ||||||||||||||||||||||||||
.filter(x -> !x.getAnnotation(Column.class).nullable()) | ||||||||||||||||||||||||||
.findFirst().get(); | ||||||||||||||||||||||||||
String email = emailField.getName(); | ||||||||||||||||||||||||||
String emailType = javaClassTypeToDbTypes.get(emailField.getType()); | ||||||||||||||||||||||||||
boolean isNullable = emailField.getAnnotation(Column.class).nullable(); | ||||||||||||||||||||||||||
|
||||||||||||||||||||||||||
String emialNullable = isNull(isNullable); | ||||||||||||||||||||||||||
|
||||||||||||||||||||||||||
String emailCombi = String.format("%s %s %s", email, emailType, emialNullable); | ||||||||||||||||||||||||||
Comment on lines
+78
to
+89
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 구현해주신 여러 필드로 쿼리를 만들때 모두 아래와 같은 동일한 과정을 거치고 있는데요!
|
||||||||||||||||||||||||||
|
||||||||||||||||||||||||||
// index INT | ||||||||||||||||||||||||||
Field indexField = Arrays.stream(getDeclaredFields(personClass)) | ||||||||||||||||||||||||||
.filter(x -> x.isAnnotationPresent(Transient.class)) | ||||||||||||||||||||||||||
.findFirst().get(); | ||||||||||||||||||||||||||
String indexCombi = ""; | ||||||||||||||||||||||||||
|
||||||||||||||||||||||||||
String tableName = personClass.getSimpleName(); | ||||||||||||||||||||||||||
|
||||||||||||||||||||||||||
// List<? extends Class<?>> fieldTypes = Arrays.stream(getDeclaredFields(personClass)).map(Field::getType).toList(); | ||||||||||||||||||||||||||
// | ||||||||||||||||||||||||||
// List<String> fieldNames = Arrays.stream(getDeclaredFields(personClass)).map(Field::getName).toList(); | ||||||||||||||||||||||||||
|
||||||||||||||||||||||||||
String createTableSql = String.format("create table %s(%s %s %s %s %s)", | ||||||||||||||||||||||||||
tableName, | ||||||||||||||||||||||||||
idCombi, | ||||||||||||||||||||||||||
nameCombi, | ||||||||||||||||||||||||||
ageCombi, | ||||||||||||||||||||||||||
emailCombi, | ||||||||||||||||||||||||||
indexCombi | ||||||||||||||||||||||||||
); | ||||||||||||||||||||||||||
|
||||||||||||||||||||||||||
return createTableSql; | ||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||
|
||||||||||||||||||||||||||
private String getPrimaryKey() { | ||||||||||||||||||||||||||
|
||||||||||||||||||||||||||
return "PRIMARY KEY"; | ||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||
|
||||||||||||||||||||||||||
private static Field[] getDeclaredFields(Class<Person> personClass) { | ||||||||||||||||||||||||||
return personClass.getDeclaredFields(); | ||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||
|
||||||||||||||||||||||||||
// DB에서 가져와야겠다 ai를 // | ||||||||||||||||||||||||||
private static String generateValue() { | ||||||||||||||||||||||||||
return "AUTO_INCREMENT"; | ||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||
Comment on lines
+124
to
+127
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 데이터베이스 마다 해당 기능에 대한 쿼리가 다를 것이라고 생각하고 고민해주신 것 같아요! 👍 👍 다만 지금은 하나의 DB 라고 생각하고 구현 범위를 좁혀서 개발해보시는 것을 추천드립니다! 그렇다면 해당 문자열은 아래 처럼 상수로 만들어 사용할 수도 있겠네요!
getPrimaryKey()도 동일한 피드백입니다! 😄 |
||||||||||||||||||||||||||
|
||||||||||||||||||||||||||
private static String isNull(boolean isNullable) { | ||||||||||||||||||||||||||
if (!isNullable) { | ||||||||||||||||||||||||||
return "NOT NULL"; | ||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||
return ""; | ||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||
Comment on lines
+129
to
+134
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. static을 제거하고 사용해도 좋을 것 같아요! getDeclaredFields() 도 동일한 피드백입니다!
Suggested change
|
||||||||||||||||||||||||||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
package persistence.sql.ddl; | ||
|
||
import domain.Person; | ||
|
||
public class DropQueryBuilder { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
public String getDropTableSql() { | ||
Class<Person> personClass = Person.class; | ||
|
||
String tableName = personClass.getSimpleName(); | ||
// DROP TABLE Person | ||
String dropTableSql = String.format("drop table %s", tableName); | ||
|
||
return dropTableSql; | ||
} | ||
|
||
|
||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
package persistence.sql.ddl; | ||
|
||
import static org.junit.jupiter.api.Assertions.*; | ||
|
||
import java.lang.reflect.InvocationTargetException; | ||
|
||
import org.junit.jupiter.api.Test; | ||
|
||
class CreateQueryBuilderTest { | ||
@Test | ||
void createDDL() throws | ||
InvocationTargetException, | ||
NoSuchMethodException, | ||
InstantiationException, | ||
IllegalAccessException { | ||
CreateQueryBuilder createQueryBuilder = new CreateQueryBuilder(); | ||
String createTableSql = createQueryBuilder.getCreateTableSql(); | ||
|
||
assertEquals(createTableSql, "CREATE TABLE person (id INT AUTO_INCREMENT PRIMARY KEY, name VARCHAR(50) NOT NULL, age INT)"); | ||
} | ||
Comment on lines
+10
to
+20
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 사소하지만 테스트 시에는 아래와 같이 예외의 상위 클래스인 Exception을 사용하면 잘 정리할 수 있습니다!
그리고
|
||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
지금은 해당 쿼리를 만드는 메서드의 기능이
Person
클래스에 한정되어있는데요!파라미터로 클래스를 받아서 다른 클래스에 대해서도 기능이 동작하도록 개선해보는건 어떨까요!?