feat: implement course creation API

This commit is contained in:
약풍 2025-03-08 16:50:58 +09:00
parent 2aa53f929d
commit d12b51ce2e
8 changed files with 160 additions and 0 deletions

View file

@ -35,6 +35,7 @@ dependencies {
// Workaround for AOT issue (https://github.com/spring-projects/spring-framework/pull/33949) -->
implementation 'io.projectreactor:reactor-core'
compileOnly 'org.projectlombok:lombok'
implementation 'org.springframework.boot:spring-boot-starter-cache'
implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
implementation 'org.springframework.boot:spring-boot-starter-thymeleaf'
@ -58,6 +59,8 @@ dependencies {
testImplementation 'org.testcontainers:mysql'
checkstyle "io.spring.javaformat:spring-javaformat-checkstyle:${springJavaformatCheckstyleVersion}"
checkstyle "com.puppycrawl.tools:checkstyle:${checkstyleVersion}"
annotationProcessor 'org.projectlombok:lombok'
}
tasks.named('test') {

View file

@ -0,0 +1,31 @@
package org.springframework.samples.petclinic.course;
import jakarta.persistence.Entity;
import jakarta.persistence.EnumType;
import jakarta.persistence.Enumerated;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import jakarta.persistence.JoinColumn;
import jakarta.persistence.ManyToOne;
import jakarta.persistence.Table;
import lombok.Getter;
import lombok.Setter;
import org.springframework.samples.petclinic.model.BaseEntity;
import org.springframework.samples.petclinic.vet.Vet;
@Getter
@Setter
@Entity
@Table(name = "courses")
public class Course extends BaseEntity {
private String name;
private String description;
// : 초급, 중급, 고급
private String difficulty;
@ManyToOne
@JoinColumn(name = "vet_id")
private Vet instructor;
}

View file

@ -0,0 +1,30 @@
package org.springframework.samples.petclinic.course;
import lombok.RequiredArgsConstructor;
import org.springframework.http.ResponseEntity;
import org.springframework.samples.petclinic.course.dto.CreateCourseRequest;
import org.springframework.samples.petclinic.vet.Vet;
import org.springframework.samples.petclinic.vet.VetRepository;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequiredArgsConstructor
@RequestMapping("/courses")
public class CourseController {
private final CourseService courseService;
@PostMapping()
public ResponseEntity<Integer> createCourse(@RequestBody CreateCourseRequest request) {
System.out.println(request);
Course course = courseService.createCourse(request.getName(), request.getDescription(), request.getDescription(), request.getVetId());
return ResponseEntity.ok(course.getId());
}
}

View file

@ -0,0 +1,6 @@
package org.springframework.samples.petclinic.course;
import org.springframework.data.jpa.repository.JpaRepository;
public interface CourseRepository extends JpaRepository<Course, Integer> {
}

View file

@ -0,0 +1,41 @@
package org.springframework.samples.petclinic.course;
import lombok.NoArgsConstructor;
import lombok.RequiredArgsConstructor;
import org.springframework.samples.petclinic.vet.Vet;
import org.springframework.samples.petclinic.vet.VetRepository;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.Collection;
@Service
@Transactional(readOnly = true)
@RequiredArgsConstructor
public class CourseService {
private final CourseRepository courseRepository;
private final VetRepository vetRepository;
@Transactional()
public Course createCourse(String name, String description, String difficulty, Integer vetId) {
Collection<Vet> all = vetRepository.findAll();
all.forEach(course -> {
System.out.println(course.getId());
});
Vet instructor = vetRepository.findById(vetId)
.orElseThrow(() -> new RuntimeException("Vet not found"));
Course course = new Course();
course.setName(name);
course.setDescription(description);
course.setDifficulty(difficulty);
course.setInstructor(instructor);
courseRepository.save(course);
return course;
}
}

View file

@ -0,0 +1,31 @@
package org.springframework.samples.petclinic.course.dto;
import lombok.Getter;
@Getter()
public class CreateCourseRequest {
private String name;
private String description;
private String difficulty;
private Integer vetId;
public CreateCourseRequest() {
}
public CreateCourseRequest(String name, String description, String difficulty, Integer vetId) {
this.name = name;
this.description = description;
this.difficulty = difficulty;
this.vetId = vetId;
}
@Override
public String toString() {
return "CreateCourseRequest{" +
"name='" + name + '\'' +
", description='" + description + '\'' +
", difficulty='" + difficulty + '\'' +
", vetId=" + vetId +
'}';
}
}

View file

@ -23,6 +23,7 @@ import org.springframework.data.repository.Repository;
import org.springframework.transaction.annotation.Transactional;
import java.util.Collection;
import java.util.Optional;
/**
* Repository class for <code>Vet</code> domain objects All method names are compliant
@ -37,6 +38,13 @@ import java.util.Collection;
*/
public interface VetRepository extends Repository<Vet, Integer> {
/**
* Retrieve a <code>Vet</code> from the data store.
* @return a <code>Optional</code> of <code>Vet</code>
*/
@Transactional(readOnly = true)
Optional<Vet> findById(Integer id) throws DataAccessException;
/**
* Retrieve all <code>Vet</code>s from the data store.
* @return a <code>Collection</code> of <code>Vet</code>s

View file

@ -62,3 +62,13 @@ CREATE TABLE visits (
);
ALTER TABLE visits ADD CONSTRAINT fk_visits_pets FOREIGN KEY (pet_id) REFERENCES pets (id);
CREATE INDEX visits_pet_id ON visits (pet_id);
CREATE TABLE courses (
id INTEGER GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,
name VARCHAR(255),
description VARCHAR(1000),
difficulty VARCHAR(255),
vet_id INTEGER
);
CREATE INDEX courses_vet_id ON courses (vet_id);