Compare commits
3 Commits
839901d663
...
5c4df5a19a
| Author | SHA1 | Date | |
|---|---|---|---|
| 5c4df5a19a | |||
| ec281bf354 | |||
| 9cd5ff309f |
@@ -152,7 +152,10 @@ api-app # 메인 실행 모듈
|
|||||||
│ │ │ ├── DabeeoDetectionApiApplication.java
|
│ │ │ ├── DabeeoDetectionApiApplication.java
|
||||||
│ │ │
|
│ │ │
|
||||||
│ │ │ ├── config # 설정 파일
|
│ │ │ ├── config # 설정 파일
|
||||||
│ │ │ ├── core # core service (Repository 비즈니스 서비스)
|
│ │ │ ├── db
|
||||||
|
│ │ │ │ ├── core # core service (Repository 비즈니스 서비스)
|
||||||
|
│ │ │ │ └── repository # Repository (DB 인터페이스/구현)
|
||||||
|
│ │ │ ├── core
|
||||||
│ │ │ ├── domain # 도메인
|
│ │ │ ├── domain # 도메인
|
||||||
│ │ │ │ ├── imagery # 영상 데이터 관리
|
│ │ │ │ ├── imagery # 영상 데이터 관리
|
||||||
│ │ │ │ ├── labeling # 라벨링 툴
|
│ │ │ │ ├── labeling # 라벨링 툴
|
||||||
@@ -161,10 +164,7 @@ api-app # 메인 실행 모듈
|
|||||||
│ │ │ │ ├── inference # 추론관리
|
│ │ │ │ ├── inference # 추론관리
|
||||||
│ │ │ │ ├── system # 시스템관리
|
│ │ │ │ ├── system # 시스템관리
|
||||||
│ │ │ │ └── log # 로그관리
|
│ │ │ │ └── log # 로그관리
|
||||||
│ │ │
|
|
||||||
│ │ │ ├── entity # 공용 JPA 엔티티 (DB 공통 사용)
|
│ │ │ ├── entity # 공용 JPA 엔티티 (DB 공통 사용)
|
||||||
│ │ │ │
|
|
||||||
│ │ │ └── repository # 공용 Repository (DB 공통 인터페이스/구현)
|
|
||||||
│ │ │
|
│ │ │
|
||||||
│ │ └── resources # 설정 및 리소스 파일
|
│ │ └── resources # 설정 및 리소스 파일
|
||||||
│ │ ├── application.yml
|
│ │ ├── application.yml
|
||||||
@@ -174,7 +174,6 @@ api-app # 메인 실행 모듈
|
|||||||
│ └── build.gradle
|
│ └── build.gradle
|
||||||
│
|
│
|
||||||
├── infrastructure-db-postgres # Postgres 전용 설정/확장
|
├── infrastructure-db-postgres # Postgres 전용 설정/확장
|
||||||
│ ├── repository # Repository impl 구현
|
|
||||||
│ └── build.gradle
|
│ └── build.gradle
|
||||||
│
|
│
|
||||||
├── build.gradle
|
├── build.gradle
|
||||||
@@ -215,20 +214,19 @@ DB 관련 로직은 별도의 모듈(infrastructure-db-postgres)로 분리되어
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
### 🔄 처리 흐름
|
### 🔄 Database 교체
|
||||||
|
|
||||||
Controller → Service → Repository → DB
|
- `api-app/build.gradle`에서 DB 모듈 의존성 변경
|
||||||
|
(`infrastructure-db-postgres` → `infrastructure-db-oracle`)
|
||||||
|
|
||||||
---
|
- `application.yml` 또는 DB별 설정 파일(`application-postgres.yml`, `application-oracle.yml`)에서
|
||||||
|
데이터베이스 연결 정보 변경
|
||||||
|
|
||||||
### 💡 설계 포인트
|
- 실행 시 profile을 통해 DB 선택
|
||||||
|
|
||||||
- API 모듈은 DB 기술에 직접 의존하지 않음
|
```bash
|
||||||
- DB 관련 코드는 별도 모듈에서 관리
|
# PostgreSQL
|
||||||
- DB 변경 시 API 코드 수정 최소화
|
--spring.profiles.active=postgres
|
||||||
|
|
||||||
---
|
# Oracle
|
||||||
|
--spring.profiles.active=oracle
|
||||||
## 🔥 한 줄 요약
|
|
||||||
|
|
||||||
DB 기술 변경에 유연하게 대응하기 위해 persistence 레이어를 모듈로 분리했습니다.
|
|
||||||
|
|||||||
@@ -1,37 +1,41 @@
|
|||||||
plugins {
|
plugins {
|
||||||
id 'org.springframework.boot'
|
id 'org.springframework.boot'
|
||||||
id 'io.spring.dependency-management'
|
|
||||||
id 'java'
|
id 'java'
|
||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
|
// DB 변경시 변경
|
||||||
runtimeOnly 'com.h2database:h2'
|
|
||||||
|
|
||||||
// postgres
|
|
||||||
implementation project(':infrastructure-db-postgres')
|
implementation project(':infrastructure-db-postgres')
|
||||||
|
|
||||||
|
// DB (테스트용)
|
||||||
|
runtimeOnly 'com.h2database:h2'
|
||||||
|
|
||||||
|
// Spring
|
||||||
implementation 'org.springframework.boot:spring-boot-starter-web'
|
implementation 'org.springframework.boot:spring-boot-starter-web'
|
||||||
implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
|
implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
|
||||||
|
|
||||||
|
// OpenAPI
|
||||||
implementation 'org.springdoc:springdoc-openapi-starter-webmvc-ui:2.5.0'
|
implementation 'org.springdoc:springdoc-openapi-starter-webmvc-ui:2.5.0'
|
||||||
|
|
||||||
|
// QueryDSL
|
||||||
implementation "com.querydsl:querydsl-jpa:5.0.0:jakarta"
|
implementation "com.querydsl:querydsl-jpa:5.0.0:jakarta"
|
||||||
|
|
||||||
|
// Lombok
|
||||||
compileOnly 'org.projectlombok:lombok'
|
compileOnly 'org.projectlombok:lombok'
|
||||||
|
annotationProcessor 'org.projectlombok:lombok'
|
||||||
|
|
||||||
|
// Devtools
|
||||||
developmentOnly 'org.springframework.boot:spring-boot-devtools'
|
developmentOnly 'org.springframework.boot:spring-boot-devtools'
|
||||||
|
|
||||||
annotationProcessor 'org.projectlombok:lombok'
|
// QueryDSL APT
|
||||||
annotationProcessor "com.querydsl:querydsl-apt:5.0.0:jakarta"
|
annotationProcessor "com.querydsl:querydsl-apt:5.0.0:jakarta"
|
||||||
annotationProcessor "jakarta.annotation:jakarta.annotation-api"
|
annotationProcessor "jakarta.annotation:jakarta.annotation-api"
|
||||||
annotationProcessor "jakarta.persistence:jakarta.persistence-api"
|
annotationProcessor "jakarta.persistence:jakarta.persistence-api"
|
||||||
|
|
||||||
|
// Test
|
||||||
testImplementation 'org.springframework.boot:spring-boot-starter-test'
|
testImplementation 'org.springframework.boot:spring-boot-starter-test'
|
||||||
}
|
}
|
||||||
|
|
||||||
tasks.named('test') {
|
|
||||||
useJUnitPlatform()
|
|
||||||
}
|
|
||||||
|
|
||||||
bootJar {
|
bootJar {
|
||||||
archiveFileName = 'ROOT.jar'
|
archiveFileName = 'ROOT.jar'
|
||||||
}
|
}
|
||||||
@@ -2,6 +2,9 @@ package com.cd.detection;
|
|||||||
|
|
||||||
import org.springframework.boot.SpringApplication;
|
import org.springframework.boot.SpringApplication;
|
||||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||||
|
import org.springframework.boot.autoconfigure.domain.EntityScan;
|
||||||
|
import org.springframework.context.annotation.ComponentScan;
|
||||||
|
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
|
||||||
|
|
||||||
@SpringBootApplication
|
@SpringBootApplication
|
||||||
public class DabeeoDetectionApiApplication {
|
public class DabeeoDetectionApiApplication {
|
||||||
|
|||||||
@@ -0,0 +1,40 @@
|
|||||||
|
package com.cd.detection.config.api;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonInclude;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.ToString;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
@ToString
|
||||||
|
@JsonInclude(JsonInclude.Include.NON_NULL)
|
||||||
|
public class ApiResponseDto<T> {
|
||||||
|
|
||||||
|
private final T data;
|
||||||
|
private final Error error;
|
||||||
|
|
||||||
|
private ApiResponseDto(T data, Error error) {
|
||||||
|
this.data = data;
|
||||||
|
this.error = error;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 성공
|
||||||
|
public static <T> ApiResponseDto<T> ok(T data) {
|
||||||
|
return new ApiResponseDto<>(data, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 실패
|
||||||
|
public static <T> ApiResponseDto<T> fail(String code, String message) {
|
||||||
|
return new ApiResponseDto<>(null, new Error(code, message));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
public static class Error {
|
||||||
|
private final String code;
|
||||||
|
private final String message;
|
||||||
|
|
||||||
|
public Error(String code, String message) {
|
||||||
|
this.code = code;
|
||||||
|
this.message = message;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,68 @@
|
|||||||
|
package com.cd.detection.db.core;
|
||||||
|
|
||||||
|
import com.cd.detection.db.repository.zoo.AnimalRepository;
|
||||||
|
import com.cd.detection.domain.zoo.dto.AnimalDto;
|
||||||
|
import com.cd.detection.domain.zoo.dto.AnimalDto.AddRequest;
|
||||||
|
import com.cd.detection.domain.zoo.dto.AnimalDto.ModifyRequest;
|
||||||
|
import com.cd.detection.domain.zoo.dto.AnimalDto.SearchListRequest;
|
||||||
|
import com.cd.detection.entity.AnimalEntity;
|
||||||
|
import com.cd.detection.entity.ZooEntity;
|
||||||
|
import jakarta.persistence.EntityNotFoundException;
|
||||||
|
import java.util.List;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import org.springframework.data.domain.Page;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
|
|
||||||
|
@Service
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
public class AnimalCoreService {
|
||||||
|
private final AnimalRepository animalRepository;
|
||||||
|
|
||||||
|
@Transactional
|
||||||
|
public void saveZoo(AddRequest dto) {
|
||||||
|
ZooEntity zoo = new ZooEntity();
|
||||||
|
zoo.setZooId(dto.getZooId()); // FK만 세팅
|
||||||
|
|
||||||
|
AnimalEntity animalEntity = new AnimalEntity();
|
||||||
|
animalEntity.setZoo(zoo);
|
||||||
|
animalEntity.setAnimalName(dto.getAnimalName());
|
||||||
|
animalEntity.setSpecies(dto.getSpecies());
|
||||||
|
animalEntity.setAge(dto.getAge());
|
||||||
|
|
||||||
|
animalRepository.save(animalEntity);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Transactional
|
||||||
|
public void updateZoo(ModifyRequest dto) {
|
||||||
|
AnimalEntity animalEntity = animalRepository.findById(dto.getAnimalId()).orElseThrow(() -> new EntityNotFoundException("Animal Id: " + dto.getAnimalId()));
|
||||||
|
|
||||||
|
animalEntity.setAnimalName(dto.getAnimalName());
|
||||||
|
animalEntity.setSpecies(dto.getSpecies());
|
||||||
|
animalEntity.setUseYn(dto.getUseYn());
|
||||||
|
animalRepository.save(animalEntity);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Transactional
|
||||||
|
public void deleteZoo(ModifyRequest dto) {
|
||||||
|
AnimalEntity animalEntity = animalRepository.findById(dto.getAnimalId()).orElseThrow(() -> new EntityNotFoundException("Animal Id: " + dto.getAnimalId()));
|
||||||
|
|
||||||
|
animalEntity.setDelYn(dto.getDelYn());
|
||||||
|
animalRepository.save(animalEntity);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Page<AnimalDto.Basic> getAnimals(SearchListRequest searchListRequest) {
|
||||||
|
Page<AnimalEntity> animals = animalRepository.findAllAnimals(searchListRequest);
|
||||||
|
|
||||||
|
return animals.map(a -> {
|
||||||
|
AnimalDto.Basic res = new AnimalDto.Basic();
|
||||||
|
res.setAnimalId(a.getAnimalId());
|
||||||
|
res.setAnimalName(a.getAnimalName());
|
||||||
|
res.setSpecies(a.getSpecies());
|
||||||
|
res.setAge(a.getAge() != null ? a.getAge().toString() : null);
|
||||||
|
res.setDelYn(a.getDelYn());
|
||||||
|
res.setUseYn(a.getUseYn());
|
||||||
|
return res;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,74 @@
|
|||||||
|
package com.cd.detection.db.core;
|
||||||
|
|
||||||
|
import com.cd.detection.db.repository.zoo.ZooRepository;
|
||||||
|
import com.cd.detection.domain.zoo.dto.ZooDto.AddRequest;
|
||||||
|
import com.cd.detection.domain.zoo.dto.ZooDto.AnimalRes;
|
||||||
|
import com.cd.detection.domain.zoo.dto.ZooDto.ModifyRequest;
|
||||||
|
import com.cd.detection.domain.zoo.dto.ZooDto.SearchListRequest;
|
||||||
|
import com.cd.detection.domain.zoo.dto.ZooDto.ZooWithAnimalsRes;
|
||||||
|
import com.cd.detection.entity.ZooEntity;
|
||||||
|
import jakarta.persistence.EntityNotFoundException;
|
||||||
|
import java.util.List;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import org.springframework.data.domain.Page;
|
||||||
|
import org.springframework.data.domain.PageImpl;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
|
|
||||||
|
@Service
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
public class ZooCoreService {
|
||||||
|
private final ZooRepository zooRepository;
|
||||||
|
|
||||||
|
@Transactional
|
||||||
|
public void saveZoo(AddRequest dto) {
|
||||||
|
ZooEntity zooEntity = new ZooEntity();
|
||||||
|
zooEntity.setZooName(dto.getZooName());
|
||||||
|
zooEntity.setDescription(dto.getDescription());
|
||||||
|
|
||||||
|
zooRepository.save(zooEntity);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Transactional
|
||||||
|
public void updateZoo(ModifyRequest dto) {
|
||||||
|
ZooEntity zooEntity = zooRepository.findById(dto.getId()).orElseThrow(() -> new EntityNotFoundException("Zoo Id: " + dto.getId()));
|
||||||
|
|
||||||
|
zooEntity.setZooName(dto.getZooName());
|
||||||
|
zooEntity.setDescription(dto.getDescription());
|
||||||
|
zooEntity.setUseYn(dto.getUseYn());
|
||||||
|
zooRepository.save(zooEntity);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Transactional
|
||||||
|
public void deleteZoo(ModifyRequest dto) {
|
||||||
|
ZooEntity zooEntity = zooRepository.findById(dto.getId()).orElseThrow(() -> new EntityNotFoundException("Zoo Id: " + dto.getId()));
|
||||||
|
|
||||||
|
zooEntity.setDelYn(dto.getDelYn());
|
||||||
|
zooRepository.save(zooEntity);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Page<ZooWithAnimalsRes> getZooWithAnimals(SearchListRequest searchListRequest) {
|
||||||
|
Page<ZooEntity> zoo = zooRepository.findAllWithAnimals(searchListRequest);
|
||||||
|
|
||||||
|
return zoo.map(z -> {
|
||||||
|
ZooWithAnimalsRes res = new ZooWithAnimalsRes();
|
||||||
|
res.setZooId(z.getZooId());
|
||||||
|
res.setZooName(z.getZooName());
|
||||||
|
res.setDescription(z.getDescription());
|
||||||
|
|
||||||
|
List<AnimalRes> animals = z.getAnimals().stream()
|
||||||
|
.map(a -> {
|
||||||
|
AnimalRes ar = new AnimalRes();
|
||||||
|
ar.setAnimalId(a.getAnimalId());
|
||||||
|
ar.setAnimalName(a.getAnimalName());
|
||||||
|
ar.setSpecies(a.getSpecies());
|
||||||
|
ar.setAge(a.getAge());
|
||||||
|
return ar;
|
||||||
|
})
|
||||||
|
.toList();
|
||||||
|
|
||||||
|
res.setAnimals(animals);
|
||||||
|
return res;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
package com.cd.detection.db.repository.zoo;
|
||||||
|
|
||||||
|
import com.cd.detection.entity.AnimalEntity;
|
||||||
|
import org.springframework.data.jpa.repository.JpaRepository;
|
||||||
|
|
||||||
|
public interface AnimalRepository extends JpaRepository<AnimalEntity, Long>, AnimalRepositoryCustom {
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
package com.cd.detection.db.repository.zoo;
|
||||||
|
|
||||||
|
import com.cd.detection.domain.zoo.dto.AnimalDto;
|
||||||
|
import com.cd.detection.entity.AnimalEntity;
|
||||||
|
import java.util.List;
|
||||||
|
import org.springframework.data.domain.Page;
|
||||||
|
|
||||||
|
public interface AnimalRepositoryCustom {
|
||||||
|
Page<AnimalEntity> findAllAnimals(AnimalDto.SearchListRequest dto);
|
||||||
|
}
|
||||||
@@ -0,0 +1,46 @@
|
|||||||
|
package com.cd.detection.db.repository.zoo;
|
||||||
|
|
||||||
|
import com.cd.detection.domain.zoo.dto.AnimalDto.SearchListRequest;
|
||||||
|
import com.cd.detection.entity.AnimalEntity;
|
||||||
|
import com.cd.detection.entity.QAnimalEntity;
|
||||||
|
import com.cd.detection.entity.QZooEntity;
|
||||||
|
import com.cd.detection.entity.ZooEntity;
|
||||||
|
import com.querydsl.jpa.impl.JPAQueryFactory;
|
||||||
|
import java.util.List;
|
||||||
|
import org.springframework.data.domain.Page;
|
||||||
|
import org.springframework.data.domain.PageImpl;
|
||||||
|
import org.springframework.data.domain.Pageable;
|
||||||
|
import org.springframework.stereotype.Repository;
|
||||||
|
|
||||||
|
@Repository
|
||||||
|
public class AnimalRepositoryImpl implements AnimalRepositoryCustom {
|
||||||
|
private final JPAQueryFactory queryFactory;
|
||||||
|
|
||||||
|
public AnimalRepositoryImpl(JPAQueryFactory queryFactory) {
|
||||||
|
this.queryFactory = queryFactory;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Page<AnimalEntity> findAllAnimals(SearchListRequest searchListRequest) {
|
||||||
|
Pageable pageable = searchListRequest.toPageable();
|
||||||
|
QAnimalEntity animal = QAnimalEntity.animalEntity;
|
||||||
|
|
||||||
|
// content 조회
|
||||||
|
List<AnimalEntity> content = queryFactory
|
||||||
|
.selectFrom(animal)
|
||||||
|
.where(animal.delYn.eq(false))
|
||||||
|
.distinct()
|
||||||
|
.offset(pageable.getOffset())
|
||||||
|
.limit(pageable.getPageSize())
|
||||||
|
.fetch();
|
||||||
|
|
||||||
|
// count 조회 (fetchJoin 제거)
|
||||||
|
Long total = queryFactory
|
||||||
|
.select(animal.count())
|
||||||
|
.from(animal)
|
||||||
|
.where(animal.delYn.eq(false))
|
||||||
|
.fetchOne();
|
||||||
|
|
||||||
|
return new PageImpl<>(content, pageable, total == null ? 0L : total);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
package com.cd.detection.db.repository.zoo;
|
||||||
|
|
||||||
|
import com.cd.detection.entity.ZooEntity;
|
||||||
|
import org.springframework.data.jpa.repository.JpaRepository;
|
||||||
|
|
||||||
|
public interface ZooRepository extends JpaRepository<ZooEntity, Long>, ZooRepositoryCustom {
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
package com.cd.detection.db.repository.zoo;
|
||||||
|
|
||||||
|
import com.cd.detection.domain.zoo.dto.ZooDto.SearchListRequest;
|
||||||
|
import com.cd.detection.entity.ZooEntity;
|
||||||
|
import java.util.List;
|
||||||
|
import org.springframework.data.domain.Page;
|
||||||
|
import org.springframework.data.domain.PageImpl;
|
||||||
|
|
||||||
|
public interface ZooRepositoryCustom {
|
||||||
|
Page<ZooEntity> findAllWithAnimals(SearchListRequest searchListRequest);
|
||||||
|
}
|
||||||
@@ -0,0 +1,45 @@
|
|||||||
|
package com.cd.detection.db.repository.zoo;
|
||||||
|
|
||||||
|
import com.cd.detection.domain.zoo.dto.ZooDto.SearchListRequest;
|
||||||
|
import com.cd.detection.entity.QZooEntity;
|
||||||
|
import com.cd.detection.entity.ZooEntity;
|
||||||
|
import com.querydsl.jpa.impl.JPAQueryFactory;
|
||||||
|
import java.util.List;
|
||||||
|
import org.springframework.data.domain.PageImpl;
|
||||||
|
import org.springframework.data.domain.Pageable;
|
||||||
|
import org.springframework.stereotype.Repository;
|
||||||
|
|
||||||
|
@Repository
|
||||||
|
public class ZooRepositoryImpl implements ZooRepositoryCustom {
|
||||||
|
|
||||||
|
private final JPAQueryFactory queryFactory;
|
||||||
|
|
||||||
|
public ZooRepositoryImpl(JPAQueryFactory queryFactory) {
|
||||||
|
this.queryFactory = queryFactory;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public PageImpl<ZooEntity> findAllWithAnimals(SearchListRequest searchListRequest) {
|
||||||
|
Pageable pageable = searchListRequest.toPageable();
|
||||||
|
QZooEntity zoo = QZooEntity.zooEntity;
|
||||||
|
|
||||||
|
// content 조회
|
||||||
|
List<ZooEntity> content = queryFactory
|
||||||
|
.selectFrom(zoo)
|
||||||
|
.leftJoin(zoo.animals).fetchJoin()
|
||||||
|
.where(zoo.delYn.eq(false))
|
||||||
|
.distinct()
|
||||||
|
.offset(pageable.getOffset())
|
||||||
|
.limit(pageable.getPageSize())
|
||||||
|
.fetch();
|
||||||
|
|
||||||
|
// count 조회 (fetchJoin 제거)
|
||||||
|
Long total = queryFactory
|
||||||
|
.select(zoo.count())
|
||||||
|
.from(zoo)
|
||||||
|
.where(zoo.delYn.eq(false))
|
||||||
|
.fetchOne();
|
||||||
|
|
||||||
|
return new PageImpl<>(content, pageable, total == null ? 0L : total);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,125 @@
|
|||||||
|
package com.cd.detection.domain.zoo;
|
||||||
|
|
||||||
|
import com.cd.detection.config.api.ApiResponseDto;
|
||||||
|
import com.cd.detection.domain.zoo.dto.AnimalDto;
|
||||||
|
import com.cd.detection.domain.zoo.service.AnimalService;
|
||||||
|
import io.swagger.v3.oas.annotations.Operation;
|
||||||
|
import io.swagger.v3.oas.annotations.Parameter;
|
||||||
|
import io.swagger.v3.oas.annotations.media.Content;
|
||||||
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
|
import io.swagger.v3.oas.annotations.responses.ApiResponse;
|
||||||
|
import io.swagger.v3.oas.annotations.responses.ApiResponses;
|
||||||
|
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import org.springframework.data.domain.Page;
|
||||||
|
import org.springframework.http.ResponseEntity;
|
||||||
|
import org.springframework.web.bind.annotation.DeleteMapping;
|
||||||
|
import org.springframework.web.bind.annotation.GetMapping;
|
||||||
|
import org.springframework.web.bind.annotation.PostMapping;
|
||||||
|
import org.springframework.web.bind.annotation.PutMapping;
|
||||||
|
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;
|
||||||
|
|
||||||
|
@Tag(name = "동물", description = "동물 API")
|
||||||
|
@RestController
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
@RequestMapping("/api/animal")
|
||||||
|
public class AnimalController {
|
||||||
|
|
||||||
|
private final AnimalService animalService;
|
||||||
|
|
||||||
|
@Operation(summary = "동물 목록", description = "동물 목록 ")
|
||||||
|
@ApiResponses(
|
||||||
|
value = {
|
||||||
|
@ApiResponse(
|
||||||
|
responseCode = "200",
|
||||||
|
description = "검색 성공",
|
||||||
|
content =
|
||||||
|
@Content(
|
||||||
|
mediaType = "application/json",
|
||||||
|
schema = @Schema(implementation = Page.class))),
|
||||||
|
@ApiResponse(responseCode = "400", description = "잘못된 검색 조건", content = @Content),
|
||||||
|
@ApiResponse(responseCode = "500", description = "서버 오류", content = @Content)
|
||||||
|
})
|
||||||
|
@GetMapping("/list")
|
||||||
|
public ApiResponseDto<Page<AnimalDto.Basic>> getZooWithAnimals(
|
||||||
|
@Parameter(description = "페이지 번호 (0부터 시작)", example = "0")
|
||||||
|
@RequestParam(defaultValue = "0")
|
||||||
|
int page,
|
||||||
|
@Parameter(description = "페이지 크기", example = "20")
|
||||||
|
@RequestParam(defaultValue = "20")
|
||||||
|
int size) {
|
||||||
|
|
||||||
|
AnimalDto.SearchListRequest searchListRequest = new AnimalDto.SearchListRequest();
|
||||||
|
searchListRequest.setPage(page);
|
||||||
|
searchListRequest.setSize(size);
|
||||||
|
return ApiResponseDto.ok(animalService.getAnimals(searchListRequest));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Operation(summary = "동물 등록", description = "동물 등록 ")
|
||||||
|
@ApiResponses(
|
||||||
|
value = {
|
||||||
|
@ApiResponse(
|
||||||
|
responseCode = "200",
|
||||||
|
description = "등록 성공",
|
||||||
|
content = @Content(
|
||||||
|
mediaType = "text/plain",
|
||||||
|
schema = @Schema(type = "string", example = "success")
|
||||||
|
)),
|
||||||
|
@ApiResponse(responseCode = "400", description = "잘못된 검색 조건", content = @Content),
|
||||||
|
@ApiResponse(responseCode = "500", description = "서버 오류", content = @Content)
|
||||||
|
})
|
||||||
|
@PostMapping
|
||||||
|
public ApiResponseDto<String> saveAnimal(
|
||||||
|
@io.swagger.v3.oas.annotations.parameters.RequestBody(
|
||||||
|
content = @Content(
|
||||||
|
schema = @Schema(implementation = AnimalDto.AddRequest.class)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
@RequestBody AnimalDto.AddRequest dto) {
|
||||||
|
animalService.saveAnimal(dto);
|
||||||
|
return ApiResponseDto.ok("success");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Operation(summary = "동물 수정", description = "동물 수정 ")
|
||||||
|
@ApiResponses(
|
||||||
|
value = {
|
||||||
|
@ApiResponse(
|
||||||
|
responseCode = "200",
|
||||||
|
description = "수정 성공",
|
||||||
|
content =
|
||||||
|
@Content(
|
||||||
|
mediaType = "application/json",
|
||||||
|
schema = @Schema(implementation = String.class))),
|
||||||
|
@ApiResponse(responseCode = "400", description = "잘못된 검색 조건", content = @Content),
|
||||||
|
@ApiResponse(responseCode = "500", description = "서버 오류", content = @Content)
|
||||||
|
})
|
||||||
|
@PutMapping
|
||||||
|
public ApiResponseDto<String> updateAnimal(@RequestBody AnimalDto.ModifyRequest dto) {
|
||||||
|
animalService.updateAnimal(dto);
|
||||||
|
return ApiResponseDto.ok("success");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Operation(summary = "동물 삭제", description = "동물 삭제 ")
|
||||||
|
@ApiResponses(
|
||||||
|
value = {
|
||||||
|
@ApiResponse(
|
||||||
|
responseCode = "200",
|
||||||
|
description = "삭제 성공",
|
||||||
|
content =
|
||||||
|
@Content(
|
||||||
|
mediaType = "application/json",
|
||||||
|
schema = @Schema(implementation = String.class))),
|
||||||
|
@ApiResponse(responseCode = "400", description = "잘못된 검색 조건", content = @Content),
|
||||||
|
@ApiResponse(responseCode = "500", description = "서버 오류", content = @Content)
|
||||||
|
})
|
||||||
|
@DeleteMapping
|
||||||
|
public ApiResponseDto<String> deleteAnimal(@RequestBody AnimalDto.ModifyRequest dto) {
|
||||||
|
animalService.deleteAnimal(dto);
|
||||||
|
return ApiResponseDto.ok("success");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,121 @@
|
|||||||
|
package com.cd.detection.domain.zoo;
|
||||||
|
|
||||||
|
import com.cd.detection.config.api.ApiResponseDto;
|
||||||
|
import com.cd.detection.domain.zoo.dto.ZooDto;
|
||||||
|
import com.cd.detection.domain.zoo.dto.ZooDto.SearchListRequest;
|
||||||
|
import com.cd.detection.domain.zoo.dto.ZooDto.ZooWithAnimalsRes;
|
||||||
|
import com.cd.detection.domain.zoo.service.ZooService;
|
||||||
|
import io.swagger.v3.oas.annotations.Operation;
|
||||||
|
import io.swagger.v3.oas.annotations.Parameter;
|
||||||
|
import io.swagger.v3.oas.annotations.media.Content;
|
||||||
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
|
import io.swagger.v3.oas.annotations.responses.ApiResponse;
|
||||||
|
import io.swagger.v3.oas.annotations.responses.ApiResponses;
|
||||||
|
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import org.springframework.data.domain.Page;
|
||||||
|
import org.springframework.http.ResponseEntity;
|
||||||
|
import org.springframework.web.bind.annotation.DeleteMapping;
|
||||||
|
import org.springframework.web.bind.annotation.GetMapping;
|
||||||
|
import org.springframework.web.bind.annotation.PostMapping;
|
||||||
|
import org.springframework.web.bind.annotation.PutMapping;
|
||||||
|
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;
|
||||||
|
|
||||||
|
@Tag(name = "동물원", description = "동물원 API")
|
||||||
|
@RestController
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
@RequestMapping("/api/zoo")
|
||||||
|
public class ZooController {
|
||||||
|
|
||||||
|
private final ZooService zooService;
|
||||||
|
|
||||||
|
@Operation(summary = "동물원 목록", description = "동물원 목록 ")
|
||||||
|
@ApiResponses(
|
||||||
|
value = {
|
||||||
|
@ApiResponse(
|
||||||
|
responseCode = "200",
|
||||||
|
description = "검색 성공",
|
||||||
|
content =
|
||||||
|
@Content(
|
||||||
|
mediaType = "application/json",
|
||||||
|
schema = @Schema(implementation = Page.class))),
|
||||||
|
@ApiResponse(responseCode = "400", description = "잘못된 검색 조건", content = @Content),
|
||||||
|
@ApiResponse(responseCode = "500", description = "서버 오류", content = @Content)
|
||||||
|
})
|
||||||
|
@GetMapping("/list")
|
||||||
|
public ApiResponseDto<Page<ZooWithAnimalsRes>> getZooWithAnimals(
|
||||||
|
@Parameter(description = "페이지 번호 (0부터 시작)", example = "0")
|
||||||
|
@RequestParam(defaultValue = "0")
|
||||||
|
int page,
|
||||||
|
@Parameter(description = "페이지 크기", example = "20")
|
||||||
|
@RequestParam(defaultValue = "20")
|
||||||
|
int size) {
|
||||||
|
|
||||||
|
SearchListRequest searchListRequest = new SearchListRequest();
|
||||||
|
searchListRequest.setPage(page);
|
||||||
|
searchListRequest.setSize(size);
|
||||||
|
return ApiResponseDto.ok(zooService.getZooWithAnimals(searchListRequest));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Operation(summary = "동물원 등록", description = "동물원 등록 ")
|
||||||
|
@ApiResponses(
|
||||||
|
value = {
|
||||||
|
@ApiResponse(
|
||||||
|
responseCode = "200",
|
||||||
|
description = "등록 성공",
|
||||||
|
content =
|
||||||
|
@Content(
|
||||||
|
mediaType = "application/json",
|
||||||
|
schema = @Schema(implementation = String.class))),
|
||||||
|
@ApiResponse(responseCode = "400", description = "잘못된 검색 조건", content = @Content),
|
||||||
|
@ApiResponse(responseCode = "500", description = "서버 오류", content = @Content)
|
||||||
|
})
|
||||||
|
@PostMapping
|
||||||
|
public ApiResponseDto<String> saveZoo(@RequestBody ZooDto.AddRequest dto) {
|
||||||
|
zooService.saveZoo(dto);
|
||||||
|
return ApiResponseDto.ok("success");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Operation(summary = "동물원 수정", description = "동물원 수정 ")
|
||||||
|
@ApiResponses(
|
||||||
|
value = {
|
||||||
|
@ApiResponse(
|
||||||
|
responseCode = "200",
|
||||||
|
description = "수정 성공",
|
||||||
|
content =
|
||||||
|
@Content(
|
||||||
|
mediaType = "application/json",
|
||||||
|
schema = @Schema(implementation = String.class))),
|
||||||
|
@ApiResponse(responseCode = "400", description = "잘못된 검색 조건", content = @Content),
|
||||||
|
@ApiResponse(responseCode = "500", description = "서버 오류", content = @Content)
|
||||||
|
})
|
||||||
|
@PutMapping
|
||||||
|
public ApiResponseDto<String> updateZoo(@RequestBody ZooDto.ModifyRequest dto) {
|
||||||
|
zooService.updateZoo(dto);
|
||||||
|
return ApiResponseDto.ok("success");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Operation(summary = "동물원 삭제", description = "동물원 삭제 ")
|
||||||
|
@ApiResponses(
|
||||||
|
value = {
|
||||||
|
@ApiResponse(
|
||||||
|
responseCode = "200",
|
||||||
|
description = "삭제 성공",
|
||||||
|
content =
|
||||||
|
@Content(
|
||||||
|
mediaType = "application/json",
|
||||||
|
schema = @Schema(implementation = String.class))),
|
||||||
|
@ApiResponse(responseCode = "400", description = "잘못된 검색 조건", content = @Content),
|
||||||
|
@ApiResponse(responseCode = "500", description = "서버 오류", content = @Content)
|
||||||
|
})
|
||||||
|
@DeleteMapping
|
||||||
|
public ApiResponseDto<String> deleteZoo(@RequestBody ZooDto.ModifyRequest dto) {
|
||||||
|
zooService.deleteZoo(dto);
|
||||||
|
return ApiResponseDto.ok("success");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,78 @@
|
|||||||
|
package com.cd.detection.domain.zoo.dto;
|
||||||
|
|
||||||
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
import lombok.Setter;
|
||||||
|
import org.springframework.data.domain.PageRequest;
|
||||||
|
import org.springframework.data.domain.Pageable;
|
||||||
|
|
||||||
|
public class AnimalDto {
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
@NoArgsConstructor
|
||||||
|
@AllArgsConstructor
|
||||||
|
public static class SearchListRequest {
|
||||||
|
// 페이징 파라미터
|
||||||
|
private int page = 0;
|
||||||
|
private int size = 20;
|
||||||
|
|
||||||
|
public Pageable toPageable() {
|
||||||
|
return PageRequest.of(page, size);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
public static class AddRequest {
|
||||||
|
|
||||||
|
@Schema(description = "동물원 id")
|
||||||
|
private Long zooId;
|
||||||
|
@Schema(description = "동물명")
|
||||||
|
private String animalName;
|
||||||
|
@Schema(description = "종")
|
||||||
|
private String species;
|
||||||
|
@Schema(description = "나이")
|
||||||
|
private Integer age;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
public static class ModifyRequest {
|
||||||
|
|
||||||
|
@Schema(description = "동물 id")
|
||||||
|
private Long animalId;
|
||||||
|
@Schema(description = "동물명")
|
||||||
|
private String animalName;
|
||||||
|
@Schema(description = "종")
|
||||||
|
private String species;
|
||||||
|
@Schema(description = "나이")
|
||||||
|
private String age;
|
||||||
|
@Schema(description = "삭제여부")
|
||||||
|
private Boolean delYn;
|
||||||
|
@Schema(description = "사용여부")
|
||||||
|
private Boolean useYn;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
public static class Basic {
|
||||||
|
|
||||||
|
@Schema(description = "동물 id")
|
||||||
|
private Long animalId;
|
||||||
|
@Schema(description = "동물명")
|
||||||
|
private String animalName;
|
||||||
|
@Schema(description = "종")
|
||||||
|
private String species;
|
||||||
|
@Schema(description = "나이")
|
||||||
|
private String age;
|
||||||
|
@Schema(description = "삭제여부")
|
||||||
|
private Boolean delYn;
|
||||||
|
@Schema(description = "사용여부")
|
||||||
|
private Boolean useYn;
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,66 @@
|
|||||||
|
package com.cd.detection.domain.zoo.dto;
|
||||||
|
|
||||||
|
import java.time.LocalDate;
|
||||||
|
import java.util.List;
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
import lombok.Setter;
|
||||||
|
import org.springframework.data.domain.PageRequest;
|
||||||
|
import org.springframework.data.domain.Pageable;
|
||||||
|
|
||||||
|
public class ZooDto {
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
@NoArgsConstructor
|
||||||
|
@AllArgsConstructor
|
||||||
|
public static class SearchListRequest {
|
||||||
|
// 페이징 파라미터
|
||||||
|
private int page = 0;
|
||||||
|
private int size = 20;
|
||||||
|
|
||||||
|
public Pageable toPageable() {
|
||||||
|
return PageRequest.of(page, size);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
public static class AddRequest {
|
||||||
|
|
||||||
|
private String zooName;
|
||||||
|
private String description;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
public static class ModifyRequest {
|
||||||
|
|
||||||
|
private Long id;
|
||||||
|
private String zooName;
|
||||||
|
private String description;
|
||||||
|
private Boolean useYn;
|
||||||
|
private Boolean delYn;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
public static class ZooWithAnimalsRes {
|
||||||
|
|
||||||
|
private Long zooId; // 동물원 ID
|
||||||
|
private String zooName; // 동물원 이름
|
||||||
|
private String description; // 설명
|
||||||
|
|
||||||
|
private List<AnimalRes> animals;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
public static class AnimalRes {
|
||||||
|
private Long animalId;
|
||||||
|
private String animalName;
|
||||||
|
private String species;
|
||||||
|
private Integer age;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,32 @@
|
|||||||
|
package com.cd.detection.domain.zoo.service;
|
||||||
|
|
||||||
|
import com.cd.detection.db.core.AnimalCoreService;
|
||||||
|
import com.cd.detection.domain.zoo.dto.AnimalDto;
|
||||||
|
import com.cd.detection.domain.zoo.dto.AnimalDto.Basic;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import org.springframework.data.domain.Page;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
@Service
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
public class AnimalService {
|
||||||
|
|
||||||
|
private final AnimalCoreService animalCoreService;
|
||||||
|
|
||||||
|
public Page<Basic> getAnimals(AnimalDto.SearchListRequest searchListRequest) {
|
||||||
|
return animalCoreService.getAnimals(searchListRequest);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void saveAnimal(AnimalDto.AddRequest dto) {
|
||||||
|
animalCoreService.saveZoo(dto);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void updateAnimal(AnimalDto.ModifyRequest dto) {
|
||||||
|
animalCoreService.updateZoo(dto);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void deleteAnimal(AnimalDto.ModifyRequest dto) {
|
||||||
|
animalCoreService.deleteZoo(dto);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,37 @@
|
|||||||
|
package com.cd.detection.domain.zoo.service;
|
||||||
|
|
||||||
|
import com.cd.detection.db.core.ZooCoreService;
|
||||||
|
import com.cd.detection.domain.zoo.dto.ZooDto.AddRequest;
|
||||||
|
import com.cd.detection.domain.zoo.dto.ZooDto.ModifyRequest;
|
||||||
|
import com.cd.detection.domain.zoo.dto.ZooDto.SearchListRequest;
|
||||||
|
import com.cd.detection.domain.zoo.dto.ZooDto.ZooWithAnimalsRes;
|
||||||
|
import java.util.List;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import org.springframework.data.domain.Page;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
@Service
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
public class ZooService {
|
||||||
|
private final ZooCoreService zooCoreService;
|
||||||
|
|
||||||
|
// 동물원, 동물 조회
|
||||||
|
public Page<ZooWithAnimalsRes> getZooWithAnimals(SearchListRequest searchListRequest) {
|
||||||
|
return zooCoreService.getZooWithAnimals(searchListRequest);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 동물원 저장
|
||||||
|
public void saveZoo(AddRequest dto) {
|
||||||
|
zooCoreService.saveZoo(dto);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 동물원 수정
|
||||||
|
public void updateZoo(ModifyRequest dto) {
|
||||||
|
zooCoreService.updateZoo(dto);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 동물원 삭제
|
||||||
|
public void deleteZoo(ModifyRequest dto) {
|
||||||
|
zooCoreService.deleteZoo(dto);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,56 @@
|
|||||||
|
package com.cd.detection.entity;
|
||||||
|
|
||||||
|
import jakarta.persistence.*;
|
||||||
|
import java.time.ZonedDateTime;
|
||||||
|
import lombok.*;
|
||||||
|
import org.hibernate.annotations.Comment;
|
||||||
|
|
||||||
|
@Entity
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
@Table(name = "tb_animal")
|
||||||
|
@Comment("동물 정보")
|
||||||
|
public class AnimalEntity {
|
||||||
|
|
||||||
|
@Id
|
||||||
|
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||||
|
@Column(name = "animal_id")
|
||||||
|
@Comment("동물 ID")
|
||||||
|
private Long animalId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 동물원 엔티티 (FK)
|
||||||
|
*/
|
||||||
|
@ManyToOne(fetch = FetchType.LAZY)
|
||||||
|
@JoinColumn(name = "zoo_id", nullable = false)
|
||||||
|
@Comment("동물원 ID (FK)")
|
||||||
|
private ZooEntity zoo;
|
||||||
|
|
||||||
|
@Column(name = "animal_name", nullable = false)
|
||||||
|
@Comment("동물 이름")
|
||||||
|
private String animalName;
|
||||||
|
|
||||||
|
@Column(name = "species")
|
||||||
|
@Comment("종")
|
||||||
|
private String species;
|
||||||
|
|
||||||
|
@Column(name = "age")
|
||||||
|
@Comment("나이")
|
||||||
|
private Integer age;
|
||||||
|
|
||||||
|
@Column(name = "use_yn", nullable = false)
|
||||||
|
@Comment("사용 여부")
|
||||||
|
private Boolean useYn = true;
|
||||||
|
|
||||||
|
@Column(name = "del_yn", nullable = false)
|
||||||
|
@Comment("삭제 여부")
|
||||||
|
private Boolean delYn = false;
|
||||||
|
|
||||||
|
@Column(name = "created_dttm", nullable = false)
|
||||||
|
@Comment("생성 일시")
|
||||||
|
private ZonedDateTime createdDttm = ZonedDateTime.now();
|
||||||
|
|
||||||
|
@Column(name = "updated_dttm", nullable = false)
|
||||||
|
@Comment("수정 일시")
|
||||||
|
private ZonedDateTime updatedDttm = ZonedDateTime.now();
|
||||||
|
}
|
||||||
@@ -0,0 +1,62 @@
|
|||||||
|
package com.cd.detection.entity;
|
||||||
|
|
||||||
|
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.OneToMany;
|
||||||
|
import jakarta.persistence.Table;
|
||||||
|
import java.time.ZonedDateTime;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.UUID;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.Setter;
|
||||||
|
import org.hibernate.annotations.Comment;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
@Entity
|
||||||
|
@Table(name = "tb_zoo")
|
||||||
|
public class ZooEntity {
|
||||||
|
|
||||||
|
@Id
|
||||||
|
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||||
|
@Column(name = "zoo_id")
|
||||||
|
@Comment("동물원 ID")
|
||||||
|
private Long zooId;
|
||||||
|
|
||||||
|
@OneToMany(mappedBy = "zoo", fetch = FetchType.LAZY)
|
||||||
|
private List<AnimalEntity> animals = new ArrayList<>();
|
||||||
|
|
||||||
|
@Column(name = "zoo_name", nullable = false, length = 200)
|
||||||
|
@Comment("동물원 이름")
|
||||||
|
private String zooName;
|
||||||
|
|
||||||
|
@Column(name = "description")
|
||||||
|
@Comment("설명")
|
||||||
|
private String description;
|
||||||
|
|
||||||
|
@Column(name = "use_yn", nullable = false)
|
||||||
|
@Comment("사용 여부")
|
||||||
|
private Boolean useYn = true;
|
||||||
|
|
||||||
|
@Column(name = "del_yn", nullable = false)
|
||||||
|
@Comment("삭제 여부")
|
||||||
|
private Boolean delYn = false;
|
||||||
|
|
||||||
|
@Column(name = "created_dttm", nullable = false, updatable = false)
|
||||||
|
@Comment("생성 일시")
|
||||||
|
private ZonedDateTime createdDttm = ZonedDateTime.now();
|
||||||
|
|
||||||
|
@Column(name = "updated_dttm", nullable = false)
|
||||||
|
@Comment("수정 일시")
|
||||||
|
private ZonedDateTime updatedDttm = ZonedDateTime.now();
|
||||||
|
|
||||||
|
public void addAnimal(AnimalEntity animal) {
|
||||||
|
animals.add(animal);
|
||||||
|
animal.setZoo(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,26 +1,30 @@
|
|||||||
plugins {
|
plugins {
|
||||||
id 'java'
|
|
||||||
id 'io.spring.dependency-management' version '1.1.7' apply false
|
|
||||||
id 'org.springframework.boot' version '3.5.7' apply false
|
id 'org.springframework.boot' version '3.5.7' apply false
|
||||||
|
id 'io.spring.dependency-management' version '1.1.7' apply false
|
||||||
}
|
}
|
||||||
|
|
||||||
group = 'com.cd.detection'
|
allprojects {
|
||||||
version = '0.0.1-SNAPSHOT'
|
group = 'com.cd.detection'
|
||||||
|
version = '0.0.1-SNAPSHOT'
|
||||||
java {
|
|
||||||
toolchain {
|
|
||||||
languageVersion = JavaLanguageVersion.of(21)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
repositories {
|
|
||||||
mavenCentral()
|
|
||||||
}
|
|
||||||
|
|
||||||
subprojects {
|
|
||||||
apply plugin: 'java'
|
|
||||||
|
|
||||||
repositories {
|
repositories {
|
||||||
mavenCentral()
|
mavenCentral()
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
subprojects {
|
||||||
|
apply plugin: 'java'
|
||||||
|
apply plugin: 'io.spring.dependency-management'
|
||||||
|
|
||||||
|
java {
|
||||||
|
toolchain {
|
||||||
|
languageVersion = JavaLanguageVersion.of(21)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
dependencyManagement {
|
||||||
|
imports {
|
||||||
|
mavenBom "org.springframework.boot:spring-boot-dependencies:3.5.7"
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -3,6 +3,6 @@ plugins {
|
|||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
|
// DB 드라이버
|
||||||
runtimeOnly 'org.postgresql:postgresql'
|
implementation 'org.postgresql:postgresql:42.7.3'
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user