diff --git a/build.gradle b/build.gradle index 24fff23..a88fa49 100644 --- a/build.gradle +++ b/build.gradle @@ -24,6 +24,7 @@ repositories { dependencies { implementation 'org.springframework.boot:spring-boot-starter-data-jpa' implementation 'org.springframework.boot:spring-boot-starter-web' + implementation 'org.springframework.boot:spring-boot-starter-validation' compileOnly 'org.projectlombok:lombok' developmentOnly 'org.springframework.boot:spring-boot-devtools' runtimeOnly 'com.h2database:h2' diff --git a/src/main/java/com/example/jehunonboarding/controller/JobPostingController.java b/src/main/java/com/example/jehunonboarding/controller/JobPostingController.java index 295c058..c390ba0 100644 --- a/src/main/java/com/example/jehunonboarding/controller/JobPostingController.java +++ b/src/main/java/com/example/jehunonboarding/controller/JobPostingController.java @@ -3,16 +3,27 @@ import com.example.jehunonboarding.controller.request.*; import com.example.jehunonboarding.controller.response.CommonResponse; import com.example.jehunonboarding.controller.response.JobPostingFindDetailResponse; -import com.example.jehunonboarding.controller.response.JobPostingSearchResponse; +import com.example.jehunonboarding.controller.response.JobPostingsSearchResponse; +import com.example.jehunonboarding.domain.JobPosting; +import com.example.jehunonboarding.domain.JobPostingService; +import jakarta.validation.Valid; +import lombok.RequiredArgsConstructor; +import org.springframework.data.domain.Pageable; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.*; +import java.util.List; + @RestController +@RequiredArgsConstructor public class JobPostingController { + private final JobPostingService jobPostingService; + @PostMapping("/v1/job-postings") - public ResponseEntity register(@RequestBody JobPostingRegisterRequest request) { + public ResponseEntity register(@Valid @RequestBody JobPostingRegisterRequest request) { + jobPostingService.register(request.toDomain()); return new ResponseEntity(new CommonResponse(true), HttpStatus.OK); } @@ -27,8 +38,9 @@ public ResponseEntity remove(@PathVariable int jobPostingId) { } @GetMapping("/v1/job-postings") - public ResponseEntity search(String keyword) { - return new ResponseEntity(new JobPostingSearchResponse(), HttpStatus.OK); + public ResponseEntity search(String keyword, Pageable pageable) { + List jobPostings = jobPostingService.search(pageable, keyword); + return new ResponseEntity(new JobPostingsSearchResponse(jobPostings), HttpStatus.OK); } @GetMapping("/v1/job-postings/{jobPostingId}") diff --git a/src/main/java/com/example/jehunonboarding/controller/request/JobPostingRegisterRequest.java b/src/main/java/com/example/jehunonboarding/controller/request/JobPostingRegisterRequest.java index e9472d5..fef1168 100644 --- a/src/main/java/com/example/jehunonboarding/controller/request/JobPostingRegisterRequest.java +++ b/src/main/java/com/example/jehunonboarding/controller/request/JobPostingRegisterRequest.java @@ -1,15 +1,23 @@ package com.example.jehunonboarding.controller.request; +import com.example.jehunonboarding.domain.JobPostingRegisterInfo; +import jakarta.validation.constraints.NotNull; import lombok.Data; @Data public class JobPostingRegisterRequest { + @NotNull private int companyId; - private String companyName; - private String nation; - private String region; + @NotNull private String jobPosition; + @NotNull private long jobCompensation; + @NotNull private String description; + @NotNull private String skill; + + public JobPostingRegisterInfo toDomain() { + return new JobPostingRegisterInfo(companyId, jobPosition, jobCompensation, description, skill); + } } diff --git a/src/main/java/com/example/jehunonboarding/controller/response/JobPostingsSearchResponse.java b/src/main/java/com/example/jehunonboarding/controller/response/JobPostingsSearchResponse.java new file mode 100644 index 0000000..15b9ca4 --- /dev/null +++ b/src/main/java/com/example/jehunonboarding/controller/response/JobPostingsSearchResponse.java @@ -0,0 +1,41 @@ +package com.example.jehunonboarding.controller.response; + +import com.example.jehunonboarding.domain.JobPosting; +import lombok.Data; + +import java.util.List; +import java.util.stream.Collectors; + +@Data +public class JobPostingsSearchResponse { + private List items; + + public JobPostingsSearchResponse(List jobPostings) { + this.items = jobPostings.stream() + .map(JobPostingResponse::new) + .collect(Collectors.toList()); + } + + @Data + static class JobPostingResponse { + private int companyId; + private String companyName; + private String nation; + private String region; + private String jobPosition; + private long jobCompensation; + private String skill; + + public JobPostingResponse(JobPosting jobPosting) { + this.companyId = jobPosting.getCompanyId(); + this.companyName = jobPosting.getCompanyName(); + this.nation = jobPosting.getNation(); + this.region = jobPosting.getRegion(); + this.jobPosition = jobPosting.getJobPosition(); + this.jobCompensation = jobPosting.getJobCompensation(); + this.skill = jobPosting.getSkill(); + } + } +} + + diff --git a/src/main/java/com/example/jehunonboarding/domain/Company.java b/src/main/java/com/example/jehunonboarding/domain/Company.java new file mode 100644 index 0000000..8e8786f --- /dev/null +++ b/src/main/java/com/example/jehunonboarding/domain/Company.java @@ -0,0 +1,20 @@ +package com.example.jehunonboarding.domain; + +import jakarta.persistence.*; + +@Entity +@Table(name = "company") +public class Company { + @Id + @GeneratedValue + private int id; + + @Column(nullable = false) + private String companyName; + + @Column(nullable = false) + private String nation; + + @Column(nullable = false) + private String region; +} diff --git a/src/main/java/com/example/jehunonboarding/controller/response/JobPostingSearchResponse.java b/src/main/java/com/example/jehunonboarding/domain/JobPosting.java similarity index 52% rename from src/main/java/com/example/jehunonboarding/controller/response/JobPostingSearchResponse.java rename to src/main/java/com/example/jehunonboarding/domain/JobPosting.java index bb79be6..1473a8a 100644 --- a/src/main/java/com/example/jehunonboarding/controller/response/JobPostingSearchResponse.java +++ b/src/main/java/com/example/jehunonboarding/domain/JobPosting.java @@ -1,14 +1,17 @@ -package com.example.jehunonboarding.controller.response; +package com.example.jehunonboarding.domain; -import lombok.Data; +import lombok.AllArgsConstructor; +import lombok.Getter; -@Data -public class JobPostingSearchResponse { +@Getter +@AllArgsConstructor +public class JobPosting { private int companyId; private String companyName; private String nation; private String region; private String jobPosition; private long jobCompensation; + private String description; private String skill; } diff --git a/src/main/java/com/example/jehunonboarding/domain/JobPostingEntity.java b/src/main/java/com/example/jehunonboarding/domain/JobPostingEntity.java new file mode 100644 index 0000000..23f97ab --- /dev/null +++ b/src/main/java/com/example/jehunonboarding/domain/JobPostingEntity.java @@ -0,0 +1,37 @@ +package com.example.jehunonboarding.domain; + +import jakarta.persistence.*; +import lombok.NoArgsConstructor; + +@Entity +@Table(name = "job_posting") +@NoArgsConstructor +public class JobPostingEntity { + @Id + @GeneratedValue + @Column(nullable = false) + private Long id; + + @Column(nullable = false) + private int companyId; + + @Column(nullable = false) + private String jobPosition; + + @Column(nullable = false) + private long jobCompensation; + + @Column(nullable = false) + private String description; + + @Column(nullable = false) + private String skill; + + public JobPostingEntity(int companyId, String jobPosition, long jobCompensation, String description, String skill) { + this.companyId = companyId; + this.jobPosition = jobPosition; + this.jobCompensation = jobCompensation; + this.description = description; + this.skill = skill; + } +} diff --git a/src/main/java/com/example/jehunonboarding/domain/JobPostingRegisterInfo.java b/src/main/java/com/example/jehunonboarding/domain/JobPostingRegisterInfo.java new file mode 100644 index 0000000..40068ef --- /dev/null +++ b/src/main/java/com/example/jehunonboarding/domain/JobPostingRegisterInfo.java @@ -0,0 +1,14 @@ +package com.example.jehunonboarding.domain; + +import lombok.AllArgsConstructor; +import lombok.Getter; + +@Getter +@AllArgsConstructor +public class JobPostingRegisterInfo { + private int companyId; + private String jobPosition; + private long jobCompensation; + private String description; + private String skill; +} diff --git a/src/main/java/com/example/jehunonboarding/domain/JobPostingService.java b/src/main/java/com/example/jehunonboarding/domain/JobPostingService.java new file mode 100644 index 0000000..acd4215 --- /dev/null +++ b/src/main/java/com/example/jehunonboarding/domain/JobPostingService.java @@ -0,0 +1,36 @@ +package com.example.jehunonboarding.domain; + +import com.example.jehunonboarding.repository.CompanyRepository; +import com.example.jehunonboarding.repository.JobPostingRepository; +import lombok.RequiredArgsConstructor; +import org.springframework.data.domain.Pageable; +import org.springframework.stereotype.Service; + +import java.util.List; + +@Service +@RequiredArgsConstructor +public class JobPostingService { + + private final JobPostingRepository jobPostingRepository; + private final CompanyRepository companyRepository; + + public void register(JobPostingRegisterInfo registerInfo) { + companyRepository.findById(registerInfo.getCompanyId()) + .orElseThrow(() -> new IllegalArgumentException("존재하지 않는 회사입니다.")); + + jobPostingRepository.save( + new JobPostingEntity( + registerInfo.getCompanyId(), + registerInfo.getJobPosition(), + registerInfo.getJobCompensation(), + registerInfo.getDescription(), + registerInfo.getSkill() + ) + ); + } + + public List search(Pageable pageable, String keyword) { + return jobPostingRepository.findByKeyword(pageable, keyword); + } +} diff --git a/src/main/java/com/example/jehunonboarding/repository/CompanyRepository.java b/src/main/java/com/example/jehunonboarding/repository/CompanyRepository.java new file mode 100644 index 0000000..ad1263e --- /dev/null +++ b/src/main/java/com/example/jehunonboarding/repository/CompanyRepository.java @@ -0,0 +1,7 @@ +package com.example.jehunonboarding.repository; + +import com.example.jehunonboarding.domain.Company; +import org.springframework.data.jpa.repository.JpaRepository; + +public interface CompanyRepository extends JpaRepository { +} diff --git a/src/main/java/com/example/jehunonboarding/repository/JobPostingRepository.java b/src/main/java/com/example/jehunonboarding/repository/JobPostingRepository.java new file mode 100644 index 0000000..425692b --- /dev/null +++ b/src/main/java/com/example/jehunonboarding/repository/JobPostingRepository.java @@ -0,0 +1,15 @@ +package com.example.jehunonboarding.repository; + +import com.example.jehunonboarding.domain.JobPosting; +import com.example.jehunonboarding.domain.JobPostingEntity; +import org.springframework.data.domain.Pageable; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Query; + +import java.util.List; + +public interface JobPostingRepository extends JpaRepository { + + @Query("SELECT new com.example.jehunonboarding.domain.JobPosting(c.id, c.companyName, c.nation, c.region, jp.jobPosition, jp.jobCompensation, jp.description, jp.skill) FROM JobPostingEntity jp INNER JOIN Company c ON jp.companyId = c.id WHERE jp.jobPosition LIKE %:keyword% OR c.companyName LIKE %:keyword%") + List findByKeyword(Pageable pageable, String keyword); +} diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties deleted file mode 100644 index 8b13789..0000000 --- a/src/main/resources/application.properties +++ /dev/null @@ -1 +0,0 @@ - diff --git a/src/main/resources/application.yaml b/src/main/resources/application.yaml new file mode 100644 index 0000000..9c181a3 --- /dev/null +++ b/src/main/resources/application.yaml @@ -0,0 +1,17 @@ +spring: + datasource: + url: jdbc:h2:mem:testdb + username: sa + password: + generate-unique-name: false + jpa: + defer-datasource-initialization: true + properties: + hibernate: + format_sql: true + show_sql: true + ddl-auto: create + database-platform: org.hibernate.dialect.H2Dialect + h2: + console: + enabled: true diff --git a/src/main/resources/data.sql b/src/main/resources/data.sql new file mode 100644 index 0000000..58cba22 --- /dev/null +++ b/src/main/resources/data.sql @@ -0,0 +1 @@ +INSERT INTO company (id, company_name, nation, region) VALUES (1, '제훈테크', '한국', '서울');