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

Feature/admin concert place #2

Merged
merged 10 commits into from
Oct 2, 2024
Original file line number Diff line number Diff line change
Expand Up @@ -16,15 +16,15 @@ public class ExceptionAdvice {
public ResponseEntity<ResponseDto<String>> customException(CustomException exception) {
ResponseDto<String> responseDto = new ResponseDto<>(exception.getStatus().toString(),
exception.getMessage());
log.warn("CustomRuntimeException 발생 : code: {}, message: {}", responseDto.getCode(), responseDto.getBody());
log.error("CustomRuntimeException 발생 : code: {}, message: {}", responseDto.getCode(), responseDto.getBody());
return new ResponseEntity<>(responseDto, exception.getStatus());
}

@ExceptionHandler(MethodArgumentNotValidException.class)
public ResponseEntity<ResponseDto<String>> customException(MethodArgumentNotValidException exception) {
HttpStatus badRequest = HttpStatus.BAD_REQUEST;
ResponseDto<String> responseDto = new ResponseDto<>(badRequest.toString(), "요청 값이 잘 못 됐습니다");
log.warn("MethodArgumentNotValidException 발생 : message: {}", exception.getMessage());
log.error("MethodArgumentNotValidException 발생 : message: {}", exception.getMessage());
return new ResponseEntity<>(responseDto, badRequest);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,8 @@ public Place toModel() {
return Place.builder()
.name(name)
.address(address)
.identifier(identifier)
.last(true)
.seats(seats.stream().map(SeatRequest::toModel).toList())
.build();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

import java.util.List;

import co.kr.ticketing.adminconcert.place.domain.model.PlaceVersion;
import co.kr.ticketing.adminconcert.place.domain.model.Place;
import lombok.Builder;

@Builder
Expand All @@ -15,16 +15,16 @@ public record PlaceResponse(
String identifier,
String name
) {
public static PlaceResponse from(PlaceVersion version) {
public static PlaceResponse from(Place place) {
return PlaceResponse.builder()
.id(version.getPlace().getId())
.identifier(version.getIdentifier())
.name(version.getPlace().getName())
.id(place.getId())
.identifier(place.getIdentifier())
.name(place.getName())
.build();
}
}

public static GetPlaceResponse from(List<PlaceVersion> places) {
public static GetPlaceResponse from(List<Place> places) {
return GetPlaceResponse.builder()
.places(places.stream().map(PlaceResponse::from).toList())
.build();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,13 @@
import java.util.ArrayList;
import java.util.List;

import org.hibernate.annotations.ColumnDefault;
import org.hibernate.annotations.DynamicInsert;
import org.springframework.data.annotation.CreatedDate;
import org.springframework.data.annotation.LastModifiedDate;
import org.springframework.data.jpa.domain.support.AuditingEntityListener;

import co.kr.ticketing.adminconcert.place.domain.IdentifierGenerator;
import jakarta.persistence.CascadeType;
import jakarta.persistence.Column;
import jakarta.persistence.Entity;
Expand All @@ -17,12 +20,20 @@
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import jakarta.persistence.OneToMany;
import jakarta.persistence.Table;
import jakarta.persistence.UniqueConstraint;
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;

@Entity
@Getter
@Table(uniqueConstraints = {
@UniqueConstraint(name = "placeVersionUnique",
columnNames = {"identifier", "version"}
)
})
@DynamicInsert
@NoArgsConstructor
@EntityListeners(AuditingEntityListener.class)
public class Place {
Expand All @@ -41,17 +52,31 @@ public class Place {
@Column(nullable = false)
private String address;

@Column(nullable = false)
private String identifier;

@Column(nullable = false)
@ColumnDefault("0")
private Long version;

@Column(nullable = false)
@ColumnDefault("false")
private boolean last;

@OneToMany(mappedBy = "place", fetch = FetchType.LAZY, cascade = CascadeType.ALL, orphanRemoval = true)
private final List<Seat> seats = new ArrayList<>();

@Builder
public Place(Long id, LocalDateTime createdAt, LocalDateTime updatedAt, String name, String address,
List<Seat> seats) {
String identifier, Long version, boolean last, List<Seat> seats) {
this.id = id;
this.createdAt = createdAt;
this.updatedAt = updatedAt;
this.name = name;
this.address = address;
this.identifier = identifier;
this.version = version;
this.last = last;
setSeats(seats);
}

Expand All @@ -69,4 +94,32 @@ public Seat getSeat(Long seatId) {
return seats.stream().filter(placeSeat -> placeSeat.getId().equals(seatId)).findAny()
.orElse(null);
}

public static Place getNewPlace(Place place, IdentifierGenerator generator) {
return Place.builder()
.name(place.getName())
.address(place.getAddress())
.identifier(generator.generate())
.version(0L)
.last(true)
.seats(List.copyOf(place.getSeats()))
.build();
}

public Place getNextPlace(Place beforePlace) {
beforePlace.last = false;

return Place.builder()
.name(name)
.address(address)
.identifier(identifier)
.version(beforePlace.getNextVersion())
.last(true)

Choose a reason for hiding this comment

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

get 에서 last 를 셋팅하는 write operation 이 같이 있는데요. 분리하면 좋을 것 같습니다.
함수는 getNextPlace 로 DB 변경이 없을 것이 기대되지만 실재로는 beforePlace 의 last 가 Update 되는 함수라 안정적이지 않아보입니다.
차라리 last 를 별도 루틴에서 셋팅하게해서 read / write 를 분리하는게 좋을것 같습니다.

.seats(List.copyOf(getSeats()))
.build();
}

public Long getNextVersion() {
return this.version + 1;
}
}

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,10 +1,16 @@
package co.kr.ticketing.adminconcert.place.repository;

import java.util.List;
import java.util.Optional;

import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;

import co.kr.ticketing.adminconcert.place.domain.model.Place;

@Repository
public interface PlaceRepository extends JpaRepository<Place, Long> {
Optional<Place> findTopByIdentifierOrderByVersionDesc(String identifier);

List<Place> findByNameContainsAndLastIsTrue(String name);
}

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,8 +1,12 @@
package co.kr.ticketing.adminconcert.place.service;

import java.util.List;

import org.springframework.dao.DataIntegrityViolationException;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import co.kr.ticketing.adminconcert.common.exception.DuplicateException;
import co.kr.ticketing.adminconcert.common.exception.ResourceNotFoundException;
import co.kr.ticketing.adminconcert.place.domain.model.Place;
import co.kr.ticketing.adminconcert.place.repository.PlaceRepository;
Expand All @@ -15,14 +19,30 @@
@FieldDefaults(level = AccessLevel.PRIVATE, makeFinal = true)
public class PlaceService {
PlaceRepository placeRepository;
UUIDGenerator uuidGenerator;

public Place getLastVersion(String identifier) {
return placeRepository.findTopByIdentifierOrderByVersionDesc(identifier)
.orElseThrow(() -> new ResourceNotFoundException("place", identifier));
}

Choose a reason for hiding this comment

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

사소한 부분이지만 나중에는 Service 레벨에서는 Entity 를 직접 다루기 보다 VO 를 사용하는 연습해보시면 좋을것 같습니다.


public Place getById(long id) {
return placeRepository.findById(id)
.orElseThrow(() -> new ResourceNotFoundException("concert place", id));
public List<Place> getLastVersionsByPlaceName(String placeName) {
return placeRepository.findByNameContainsAndLastIsTrue(placeName);
}

@Transactional
public long create(Place place) {
return placeRepository.save(Place.getNewPlace(place, uuidGenerator)).getId();
}

@Transactional
public long add(Place place) {
return placeRepository.save(place).getId();
try {
Place lastPlace = getLastVersion(place.getIdentifier());

return placeRepository.save(place.getNextPlace(lastPlace)).getId();
} catch (DataIntegrityViolationException e) {
throw new DuplicateException("정보가 수정됐습니다. 확인 후 다시 작성 해주세요");
}
}
}

This file was deleted.

Loading
Loading