지금은 간단하게 시험용 api를 만드는 중이다.
@RestController
@RequestMapping("/photo")
@Slf4j
@RequiredArgsConstructor
public class PhotoController {
private final PhotoService photoService;
private final String fileDir = "upload-storage";
@PostMapping("/upload/{userId}")
public PhotoList uploadFile(@PathVariable("userId") String userId,
@RequestBody MultipartFile file) throws IOException {
log.info("multipartFile={}", file);
if(file.isEmpty()) throw new IllegalArgumentException();
String fullPath = fileDir +file.getOriginalFilename();
log.info("파일 저장 fullPath ={}", fullPath);
file.transferTo(new File(fullPath));
return photoService.save(userId, fullPath);
}
@GetMapping("/list")
public List<PhotoList> photoList(){
return photoService.list();
}
@DeleteMapping("/delete/{photoNo}")
public void deletePhoto(@PathVariable("photoNo") Long photoNo,
@RequestParam("userId") String userId) {
photoService.delete(photoNo, userId);
}
@GetMapping("/like/{photoNo}")
public void likePhoto(@PathVariable("photoNo") Long photoNo){
photoService.like(photoNo);
}
@Service
@RequiredArgsConstructor
@Transactional(readOnly = true)
public class PhotoService {
private final PhotoListRepository photoListRepository;
private final UserRepository userRepository;
@Transactional
public PhotoList save(String userId,String filePath) {
User user = userRepository.findByUserStrId(userId);
return photoListRepository.save(new PhotoList(user, filePath));
}
public List<PhotoList> list() {
return photoListRepository.findAll();
}
@Transactional
public void delete(Long photoNo, String userId) {
PhotoList photo = photoListRepository.findById(photoNo).orElseThrow(IllegalArgumentException::new);
User user = userRepository.findByUserStrId(userId);
System.out.println("user.getId(): " + user.getId());
System.out.println("photo.getUser().getId(): " + photo.getUser().getId());
if(user.getId() != photo.getUser().getId()) throw new IllegalArgumentException();
photoListRepository.delete(photo);
}
@Transactional
public void like(Long photoNo) {
photoListRepository.addCount(photoNo);
}
like 메소드 같은 경우 원래 더티체킹으로 만들려고 했으나 자꾸 count 변경 감지가 안 돼서 그냥 querydsl repository에 쿼리를 작성했다.
public interface PhotoListRepository extends JpaRepository<PhotoList, Long>, PhotoCustomRepository {
}
---------------------------------------------
public interface PhotoCustomRepository {
public void addCount(Long photoNo);
}
----------------------------------------------
@RequiredArgsConstructor
public class PhotoCustomRepositoryImpl implements PhotoCustomRepository{
private final JPAQueryFactory queryFactory;
@Override
public void addCount(Long photoNo) {
queryFactory
.update(photoList)
.set(photoList.likes ,photoList.likes.add(1)).where(photoList.id.eq(photoNo))
.execute();
}
}
@Entity
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@Getter
public class PhotoList {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "photo_id")
private Long id;
@JsonIgnore
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "user_no")
private User user;
private String image;
public void setImage(String image) {
this.image = image;
}
@Column(columnDefinition = "integer default 0")
private Integer likes;
// 해당 부분 없애기
public void addLikesCount(){
this.likes = likes++;
}
@JsonIgnore
@Column(name="upload_date", columnDefinition = "TIMESTAMP DEFAULT CURRENT_TIMESTAMP")
@CreationTimestamp
private LocalDateTime uploadDate;
@JsonIgnore
@Column(name ="modify_date")
@UpdateTimestamp
private LocalDateTime modifyDate;
@Column(columnDefinition = "boolean default false")
private boolean deleted;
public PhotoList(User user, String image) {
this.likes = 0;
this.user = user;
this.image = image;
}
}
columnDefinition을 설정했음에도 불구하고 insert 할 때마다 likes가 자꾸 null로 들어가서 쉬운방법으로 생성자에 0을 할당하는 방법을 택했다. 근데 이런 방법은 마음에 안 들어서 더 검색하고 고민해봐야 할 듯 하다.
아직 완전한 api를 작성한 것은 아니지만 몇몇 api를 작성할 때 이런 고민이 들었다. jpa 더티체킹을 사용할까 아니면 그냥 querydsl로 작성해서 사용할까? 오늘 like() 메소드 같은 경우도 그렇지만 어제 다른 시험 api들을 작성할 때도 이런 고민이 드는 경우가 더러 있었다. 사용하려는 데이터가 흐름상으로 볼 때 영속성 엔티티일지 준영속엔티티일지 생각해보고 코드를 작성하는 쪽으로 해야겠다는 기준을 세우긴 했는데 다른 조건들도 고려해야 할 수 있다보니 그냥 속 편하게 둘 중에 하나로만 쓰고 싶은 생각이 든다.😭😭😭