Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

[DDING-83] Form 및 FormField 엔터티 세팅 #229

Merged
merged 8 commits into from
Jan 29, 2025
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package ddingdong.ddingdongBE.common.converter;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import jakarta.persistence.AttributeConverter;
import jakarta.persistence.Converter;
import java.util.List;

@Converter
public class StringListConverter implements AttributeConverter<List<String>, String> {

private final ObjectMapper mapper = new ObjectMapper();

@Override
public String convertToDatabaseColumn(List<String> dataList) {
try {
return mapper.writeValueAsString(dataList);
} catch (JsonProcessingException e) {
throw new RuntimeException(e);
}
}

@Override
public List<String> convertToEntityAttribute(String data) {
try {
return mapper.readValue(data, List.class);
} catch (JsonProcessingException e) {
Comment on lines +26 to +27
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

List 타입 안정성 개선 필요

mapper.readValue(data, List.class)는 raw type을 사용하고 있어 타입 안정성이 보장되지 않습니다.

다음과 같이 TypeReference를 사용하여 타입 안정성을 보장하는 것이 좋습니다:

-            return mapper.readValue(data, List.class);
+            return mapper.readValue(data, new TypeReference<List<String>>() {});
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
return mapper.readValue(data, List.class);
} catch (JsonProcessingException e) {
return mapper.readValue(data, new TypeReference<List<String>>() {});
} catch (JsonProcessingException e) {

throw new RuntimeException(e);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package ddingdong.ddingdongBE.domain.form.entity;

public enum FieldType {
CHECK_BOX,
RADIO,
TEXT,
LONG_TEXT,
FILE
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
package ddingdong.ddingdongBE.domain.form.entity;

import ddingdong.ddingdongBE.domain.club.entity.Club;
import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.FetchType;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import jakarta.persistence.ManyToOne;
import java.time.LocalDate;
import lombok.AccessLevel;
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;

@Entity
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@Getter
public class Form {

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;

@Column(nullable = false)
private String title;

private String description;

@Column(nullable = false)
private LocalDate startDate;

@Column(nullable = false)
private LocalDate endDate;

@Column(nullable = false)
private boolean hasInterview;

@ManyToOne(fetch = FetchType.LAZY)
private Club club;

Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

감사 필드 및 날짜 유효성 검증 추가 필요

  1. SQL 스키마와 일치하도록 감사 필드를 추가해주세요:
+    @Column(nullable = false, updatable = false)
+    private LocalDateTime createdAt;
+
+    @Column(nullable = false)
+    private LocalDateTime updatedAt;
  1. startDateendDate보다 이전인지 검증하는 로직이 필요합니다. 다음과 같은 검증 메서드 추가를 고려해주세요:
private void validateDates() {
    if (startDate.isAfter(endDate)) {
        throw new IllegalArgumentException("시작일은 종료일보다 이후일 수 없습니다.");
    }
}

@Builder
private Form(String title, String description, Club club) {
this.title = title;
this.description = description;
this.club = club;
}

}
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

필수 필드가 빌더에서 누락됨

다음 필수 필드들이 빌더에 포함되어 있지 않습니다:

  • startDate (nullable = false)
  • endDate (nullable = false)
  • hasInterview (nullable = false)
 @Builder
-private Form(String title, String description, Club club) {
+private Form(String title, String description, LocalDate startDate, LocalDate endDate, boolean hasInterview, Club club) {
     this.title = title;
     this.description = description;
+    this.startDate = startDate;
+    this.endDate = endDate;
+    this.hasInterview = hasInterview;
     this.club = club;
+    validateDates();
 }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
@Builder
private Form(String title, String description, Club club) {
this.title = title;
this.description = description;
this.club = club;
}
}
@Builder
private Form(String title, String description, LocalDate startDate, LocalDate endDate, boolean hasInterview, Club club) {
this.title = title;
this.description = description;
this.startDate = startDate;
this.endDate = endDate;
this.hasInterview = hasInterview;
this.club = club;
validateDates();
}
}

Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
package ddingdong.ddingdongBE.domain.form.entity;

import ddingdong.ddingdongBE.common.converter.StringListConverter;
import jakarta.persistence.Column;
import jakarta.persistence.Convert;
import jakarta.persistence.Entity;
import jakarta.persistence.EnumType;
import jakarta.persistence.Enumerated;
import jakarta.persistence.FetchType;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import jakarta.persistence.ManyToOne;
import java.util.List;
import lombok.AccessLevel;
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;

@Entity
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@Getter
public class FormField {

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;

@Column(nullable = false)
private String question;

@Column(nullable = false)
private boolean required;

@Column(nullable = false)
private int order;
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

예약어 사용 주의

order는 SQL의 예약어입니다. 이로 인해 예기치 않은 문제가 발생할 수 있습니다.

필드명을 orderNumber 또는 sequence로 변경하는 것을 권장합니다:

    @Column(nullable = false)
-   private int order;
+   private int orderNumber;
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
@Column(nullable = false)
private int order;
@Column(nullable = false)
private int orderNumber;


@Column(nullable = false)
private String section;

@Convert(converter = StringListConverter.class)
private List<String> options;

@Enumerated(EnumType.STRING)
@Column(nullable = false)
private FieldType fieldType;

@ManyToOne(fetch = FetchType.LAZY)
private Form form;

@Builder
private FormField(String question, FieldType fieldType, boolean required, int order, String section,
List<String> options, Form form) {
this.question = question;
this.fieldType = fieldType;
this.required = required;
this.order = order;
this.section = section;
this.options = options;
this.form = form;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package ddingdong.ddingdongBE.domain.form.repository;

import ddingdong.ddingdongBE.domain.form.entity.FormField;
import org.springframework.data.jpa.repository.JpaRepository;

public interface FormFieldRepository extends JpaRepository<FormField, Long> {

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package ddingdong.ddingdongBE.domain.form.repository;

import ddingdong.ddingdongBE.domain.form.entity.Form;
import org.springframework.data.jpa.repository.JpaRepository;

public interface FormRepository extends JpaRepository<Form, Long> {

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
CREATE TABLE form
(
id BIGINT NOT NULL AUTO_INCREMENT PRIMARY KEY,
title VARCHAR(255) NOT NULL,
description VARCHAR(255),
start_date DATE NOT NULL,
end_date DATE NOT NULL,
has_interview BOOLEAN NOT NULL,
club_id BIGINT,
CONSTRAINT fk_form_club FOREIGN KEY (club_id) REFERENCES club (id) ON DELETE CASCADE
);

CREATE TABLE form_field
(
id BIGINT NOT NULL AUTO_INCREMENT PRIMARY KEY,
question VARCHAR(255) NOT NULL,
field_type VARCHAR(50) NOT NULL,
required BOOLEAN NOT NULL,
`order` INT NOT NULL,
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

SQL 예약어 사용 수정 필요

order는 SQL 예약어이므로 백틱으로 감싸더라도 사용을 피하는 것이 좋습니다.

-    `order`    INT          NOT NULL,
+    order_number    INT          NOT NULL,
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
`order` INT NOT NULL,
order_number INT NOT NULL,

Copy link
Collaborator

Choose a reason for hiding this comment

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

코드래빗 ai 말대로 이 부분만 수정해주시면 된다고 생각합니다!

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

수정했습니다~!

section VARCHAR(255) NOT NULL,
options TEXT,
form_id BIGINT,
CONSTRAINT fk_form_field_form FOREIGN KEY (form_id) REFERENCES form (id) ON DELETE CASCADE
);