Image이름으로 model과 repository를 만든다.
Model은
private int id;
private String caption; // 오늘 나 너무 피곤해 !!
private String postImageUrl; // 사진을 전송받아서 그 사진을 서버에 특정 폴더에 저장 - DB에 그 저장된 경로를 insert
가 들어가야 하고 User는 @ManyToOne이다. 한 사람이 여러 사진을 올릴 수 있으나 여러사람이 하나의 사진을 올리진 않기 때문
@AuthenticationPrincipal : 유저 정보를 받음
image 컨트롤러에선 업로드 후 다시 첫 화면으로 돌아가야한다.
UUID : 유일성이 보장되는 범용 고유 식별자. 사진을 저장할 때 이름이 덮어씌워지는것을 막기위해 구분
@Value("${file.path}") : yml에 넣은 경로
<form class="upload-form" action="/image" method="post" enctype="multipart/form-data">
enctype="multipart/form-data" : 여러타입의(사진 + 글)을 묶어서 전송
upload안에 jpg가 .class, 정적파일들을 Target안에 배포(deploy)될 때 시간이 걸림. 그래서 jpg가 사진이 등록되기도 전에 화면이 먼저 실행이 될 수도 있음. 그렇게 되면 액박이 뜸
포토그램 외부에 upload파일이 있으면 jpg등의 파일이 움직일 필요가 없기에 배포 시간이 필요 없음. 하여 액박이 안뜸
이미지 dto에 entity만들고 service에서 entity받는다.
예외 핸들러에 예외처리
컨트롤러에서 날려줄 문장
controller에서 엔티티로 보내고
service에서 예외처리해주고
exception 따로 만들고
exceptionhandler에서 메세지 보내고
유저dao엔 OneToMany 이미지dao엔 ManyToOne
유저 프로필에 이미지를 보내줄건데 이미지만 보내면 유저정보하고 구독자등의 정보들을 보내지 못함 그러므로 양방향 매핑을 해야함
private List< Image > images : 양방향 매핑을 위해 User안에 넣어줌
@OneToMany(mappedBy = "user", fetch = FetchType.LAZY)
mappedBy = "user" : 나는 연관관계의 주인이 아니다. 그러므로 테이블에 칼럼을 만들지마. User를 Select할 때 해당 User에 id로 등록된 image들을 다 가져와
fetch = FetchType.LAZY : User를 Select할 떄 해당 User에 id로 등록된 image들을 가져오지마 - 대신 getImages() 함수의 Image들이 호출될 때 가져와 !!
++ Eager = User를 Select할 때 해당 User id로 등록된 image들을 전부 Join해서 가져와 !!
yml파일에 파일 경로가 적혀있는데 WebMvcConfigurer를 이용해 web을 설정하여 addResourceHandlers로 낚아챈다.
@Value("${file.path}")
private String uploadFolder;
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
WebMvcConfigurer.super.addResourceHandlers(registry);
// file:///C:/workspace/photogram_springboot/upload/
// /upload/ 이런 형태를 낚아채서 값을 C:/workspace/photogram_springboot/upload/ 로 바꿔버림
registry
.addResourceHandler("/upload/**") // jsp페이지에서 /upload/** 이런 주소 패턴이 나오면 발동
.addResourceLocations("file:///"+uploadFolder)
.setCachePeriod(60*10*6) // 60초 * 10* 6
.resourceChain(true)
.addResolver(new PathResourceResolver());
}
/upload/ 이런 형태를 낚아채서 값을 C:/workspace/photogram_springboot/upload/ 로 바꿔버림
무한 참조 조심 user -> Image -> user -> ...
System.out.print(imageEntity) --> 무한루프로 출력하게 됨. 하여 쓰고 주석처리 하기. toString()도 마찬가지
service에서 controller 로 돌아올때 세션이 종료되어 lazy 로딩 불가능 해지면서 controller에서 image를 불러오지 못하게 됨.
yml파일에 open-in-view: 를 true로 하면 뷰단까지 세션을 오픈 하는 기능. 세션종료가 컨트롤에서 일어나게 하겠다.
service에 @Transactional을 걸어줘야 한다.
service에서 일이 실패 했을 때 롤백 시켜버리기 위해 @Transactional을 걸어둔다. 예를 들어 송금서비스 구현할때 송금한 사람은 완료했는데 받은 사람이 실패했을 경우 송금한 사람한테 돌려주어야(롤백) 하기 때문에 하나의 트랜잭션(일의 최소단위)으로 관리 해야한다.
영속성 컨텍스트는 controller과 service 사이에서 변경감지 해줘야 한다. @Transactional(readOnly = true)로 해주면 영속성 컨텍스트가 변경감지(더티체킹)를 하지 않아 일을 적게 한다.
Images를 호출할 때(JPA 무한참조)가 문제
@JsonIgnoreProperties({"user"}) : User에서 응답할 때 Image 내부에서 파싱할 때 user는 json으로 파싱하지 하지 않겠다.
${user.images.size()}
UserProfileDto를 만들어서 주인 페이지인지 확인한다. 주인 페이지일때 사진등록 버튼, 아니면 구독하기 버튼창을 띄운다.
dto.setImageCount(userEntity.getImages().size());