Skip to content

Commit

Permalink
JPA Native Query 팔로우 구현 및 예외처리
Browse files Browse the repository at this point in the history
  • Loading branch information
youjungHwang committed Dec 11, 2022
1 parent 9429444 commit fc5b9c4
Show file tree
Hide file tree
Showing 11 changed files with 168 additions and 9 deletions.
2 changes: 2 additions & 0 deletions src/main/java/com/photo/Application.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.data.jpa.repository.config.EnableJpaAuditing;

@EnableJpaAuditing
@SpringBootApplication
public class Application {

Expand Down
2 changes: 1 addition & 1 deletion src/main/java/com/photo/config/SecurityConfig.java
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable();

http.authorizeRequests()
.antMatchers("/","/user/**", "/image/**", "/subscribe/**","/comment/**").authenticated()
.antMatchers("/","/user/**", "/image/**", "/follow/**","/comment/**","/api/**").authenticated()
.anyRequest().permitAll()
.and()
.formLogin()
Expand Down
23 changes: 23 additions & 0 deletions src/main/java/com/photo/domain/BaseTimeEntity.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package com.photo.domain;

import lombok.Getter;
import org.springframework.data.annotation.CreatedDate;
import org.springframework.data.annotation.LastModifiedDate;
import org.springframework.data.jpa.domain.support.AuditingEntityListener;

import javax.persistence.EntityListeners;
import javax.persistence.MappedSuperclass;
import java.time.LocalDateTime;

@Getter
@MappedSuperclass
@EntityListeners(AuditingEntityListener.class)
public abstract class BaseTimeEntity {

@CreatedDate
private LocalDateTime createdDate;

@LastModifiedDate
private LocalDateTime modifiedDate;

}
35 changes: 35 additions & 0 deletions src/main/java/com/photo/domain/follow/Follow.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
package com.photo.domain.follow;

import com.photo.domain.BaseTimeEntity;
import com.photo.domain.user.User;
import lombok.*;

import javax.persistence.*;



@NoArgsConstructor
@Getter
@Entity
@Table(
uniqueConstraints = {
@UniqueConstraint(
name = "follow_uk",
columnNames = {"fromUserId", "toUserId"}
)
}
)
public class Follow extends BaseTimeEntity {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private int id;

@ManyToOne
@JoinColumn(name = "fromUserId")
private User fromUser;

@ManyToOne
@JoinColumn(name = "toUserId")
private User toUser;

}
18 changes: 18 additions & 0 deletions src/main/java/com/photo/domain/follow/FollowRepository.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package com.photo.domain.follow;

import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Modifying;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;

public interface FollowRepository extends JpaRepository<Follow, Integer> {

@Modifying
@Query(value = "INSERT INTO follow(fromUserId,toUserId,createdDate) VALUES(:fromUserId,:toUserId,now())", nativeQuery = true)
void cFollow(@Param(value = "fromUserId") Integer fromUserId, @Param(value = "toUserId") Integer toUserId);

@Modifying
@Query(value = "DELETE FROM follow WHERE fromUserId =:fromUserId AND toUserId =:toUserId", nativeQuery = true)
void cUnFollow(@Param(value = "fromUserId") Integer fromUserId, @Param(value = "toUserId") Integer toUserId);

}
9 changes: 2 additions & 7 deletions src/main/java/com/photo/domain/user/User.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.photo.domain.user;

import com.photo.domain.BaseTimeEntity;
import lombok.*;

import javax.persistence.*;
Expand All @@ -10,7 +11,7 @@
@NoArgsConstructor
@Data
@Entity
public class User {
public class User extends BaseTimeEntity {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private int id;
Expand All @@ -32,11 +33,5 @@ public class User {
private String profileImageUrl;
private String role;

private LocalDateTime createDate;

@PrePersist
public void createDate() {
this.createDate = LocalDateTime.now();
}

}
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.photo.handler;

import com.photo.handler.exception.CustomApiException;
import com.photo.handler.exception.CustomValidationApiException;
import com.photo.handler.exception.CustomValidationException;
import com.photo.util.Popup;
Expand All @@ -24,4 +25,9 @@ public String validationException(CustomValidationException e){
public ResponseEntity<?> validationApiException(CustomValidationApiException e){
return new ResponseEntity<>(new ResDto<>(-1,e.getMessage(),e.getErrors()), HttpStatus.BAD_REQUEST);
}

@ExceptionHandler(CustomApiException.class)
public ResponseEntity<?> apiException(CustomApiException e){
return new ResponseEntity<>(new ResDto<>(-1,e.getMessage(),null), HttpStatus.BAD_REQUEST);
}
}
19 changes: 19 additions & 0 deletions src/main/java/com/photo/handler/exception/CustomApiException.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package com.photo.handler.exception;

import lombok.Getter;
import lombok.NoArgsConstructor;

import java.util.Map;

@Getter
@NoArgsConstructor
public class CustomApiException extends RuntimeException {
private static final long serialVersionUID = 1L;

private String message;
private Map<String, String> errors;

public CustomApiException(String message) {
this.message = message;
}
}
29 changes: 29 additions & 0 deletions src/main/java/com/photo/service/FollowService.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package com.photo.service;

import com.photo.domain.follow.FollowRepository;
import com.photo.handler.exception.CustomApiException;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

@RequiredArgsConstructor
@Service
public class FollowService {

private final FollowRepository followRepository;


@Transactional
public void follow(int fromUserId, int toUserId) {
try{
followRepository.cFollow(fromUserId,toUserId);
}catch (Exception e) {
throw new CustomApiException("이미 팔로우 하고 있는 유저입니다.");
}
}

@Transactional
public void unFollow(int fromUserId, int toUserId) {
followRepository.cUnFollow(fromUserId,toUserId);
}
}
32 changes: 32 additions & 0 deletions src/main/java/com/photo/web/api/FollowApiController.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package com.photo.web.api;

import com.photo.config.auth.CustomUserDetails;
import com.photo.service.FollowService;
import com.photo.web.dto.ResDto;
import lombok.RequiredArgsConstructor;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.security.core.annotation.AuthenticationPrincipal;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RestController;

@RequiredArgsConstructor
@RestController
public class FollowApiController {

private final FollowService followService;

@PostMapping("/api/follow/{toUserId}")
public ResponseEntity<?> follow(@AuthenticationPrincipal CustomUserDetails customUserDetails, @PathVariable int toUserId) {
followService.follow(customUserDetails.getUser().getId(),toUserId);
return new ResponseEntity<>(new ResDto<>(1,"팔로우 성공", null), HttpStatus.OK);
}

@DeleteMapping("/api/follow/{toUserId}")
public ResponseEntity<?> unFollow(@AuthenticationPrincipal CustomUserDetails customUserDetails, @PathVariable int toUserId) {
followService.unFollow(customUserDetails.getUser().getId(), toUserId);
return new ResponseEntity<>(new ResDto<>(1,"언팔로우 성공", null), HttpStatus.OK);
}
}
2 changes: 1 addition & 1 deletion src/main/resources/application.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ spring:
jpa:
show-sql: true
hibernate:
ddl-auto: update # create update
ddl-auto: update # create update none
naming:
implicit-strategy: org.hibernate.boot.model.naming.ImplicitNamingStrategyLegacyJpaImpl
physical-strategy: org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl
Expand Down

0 comments on commit fc5b9c4

Please sign in to comment.