728x90

Admin 페이지에서 작동하는 부분중에, Comment 에 대한 부분에서 Reporting 된 처리를 하는 것은 정상적으로 작동했지만, Posting 에 대해서는 정상적으로 작동하지 않는 사태가 벌어졌다.

 

Log 를 살펴본 결과, SQL statement Error 로 보고 있는데, Update 구문에서 Entity 를 정상적으로 인식하지 못하고 있다.

 

예를 들어보면

UPDATE report_posting rp SET rp.report_status = 2 Where rp.relation.posting.id = xxxxxx

인 부분에서 앞에 표시한 부분을 정상적으로 인식하지 못하고 있다.

 

일단 이 부분에서 Error Code 기반으로 추적해보자면, 예약어나 SQL 문을 잘못 썼거나 하는 등의 상황에서 발생한다고 하는데, 아무리 봐도 구문상 틀린건 잘 보이지 않는다.

 

그래서 이걸 Native Query 로 바꿔볼까 하다가, 그러면 JPA 의 맛을 잃어버리니까 또 고민중이다.

확실한건 로그 기반으로 추적해서 봣을 때에, Entity 에서 약간의 다른 점이 있다면 

 

report_posting 의 경우는 Enum 기반의 posting_type 필드를 가지고 있다는 것이고

report_comment 의 경우는 posting_type 따위는 개나줘버리긴 했는데 사실 그게 문제가 아니라

 

만약 네이밍이 문제가 될려면 네이밍 부분을 잡아서 찍어줘야 하는데 뭐가 문제인지 고민중이다.

728x90

https://www.youtube.com/watch?v=IiZZAu2Qtp0 

 

해당 Youtube 에서는 기초적인 Elastic Search 의 공사에 대해서 설명하고 있다.

 그러니까 기본적으로 하는 공사들에는 몇 몇가지가 있는데

 

일단 가장 첫 번째로 하는 것은

ELS 를 추상화한 클래스를 상속받아서 ELS에 대하여 Config 를 설정하는 별도의 Class를 만드는 것

(이 부분이 굉장히 중요하다 할 수 있을 것 같다.)

 

만약 데이터베이스를 사용하는 와중에 아래와 같은 가정이 있다고 가정해보면

 

1. AWS Aurora 를 사용하는 상태

2. 더욱 빠른 검색을 위해서 ElasticSearch 를 추가적으로 구현해야 하는 상태라면

 

JPA 에서는 MySQL 에 대한 package 를 별도로 지정해줘야 할 것이고, ELS 를 따르는 package 를 별도로 지정해줘야 할 것이다. 

 

그리고 나서 일반적으로 이루어지는 연계 사항들을 작성하게 되는데

Document Annotation과 함께 Class 내부의 Properties 를 정의하고, indicies 를 정의하여 인덱스화하는 것

 

그리고 나서 Person Class 가 정의되었다면, 그 Class 의 Properties 들을 활용하여 저장하는 Repository 에 대한 정의

그리고 Repository 에서 구현된 Method 를 호출하여 사용하는 Service

그리고 나서 REST 형식을 이용해 Service 에서 정의된 함수들을 호출하여 사용하는 Controller 를 정의한다.

(당연히 REST 니까 여기서는 GET, PUT, Delete Mapping 등이 전부 작용할 수 있다.)

 

728x90

환경설정 (Maven)

1) h2 DateBase 설치 및 시작
2) Maven 프로젝트 생성
3) pom.xml에 라이브러리 추가
4) presistence.xml 생성

1. h2 DB 설치 & 시작


  • 실행
    : h2.sh 파일을 실행하려면 chmod 755 h2.sh 수행해야 함

  • DB 생성 (최초 1회만 해주면 된다)
    : 경로가 ~/test 이니까 홈에 test.mv.db가 생성된다
    (안되면 url뒤에 키값을 확인해보자)

  • DB 들어가기
    : 최초 생성 이후에는 tcp로 파일에 접근

2. Maven 프로젝트 생성

  • Maven 선택 및 Java 버전 선택

3. pom.xml에 라이브러리 추가

4. persistence.xml 생성

  • persistence.xml란 ?
    : JPA를 사용하기 위해 참조되는 파일로 위치가 참조 정해져 있음
    (반드시 main/java/resource/META-INF/persistence.xml)
  • persistence-unit -> EntityManagerFactory 이름
  • hibernate.dialect 에 사용할 DBDialect를 변경할 수 있음
    ex) MySQLDialect 
  • JPA에 대한 옵션을 추가할 수 있음

JPA 구동방식 & 사용


  • EntityManagerFactory를 가져오기
  • EntityManager 꺼내기
  • Transaction을 시작
  • 쿼리 내용을 수행
  • Transaction 종료
  • EntityManager  EntityManagerFactory닫기

JPQL ?

  • Table이 아닌 객체를 중심으로 하는 객체 지향 쿼리
  • 검색을 할 때도 테이블 이 아닌 Entity 객체를 대상으로 검색
  • SQL 문법과 유사
  • SQL을 추상화해서 특정 DB SQL에 의존하지 않음
728x90

https://developers.kakao.com/docs/latest/ko/daum-search/dev-guide#search-book

 

Kakao Developers

카카오 API를 활용하여 다양한 어플리케이션을 개발해보세요. 카카오 로그인, 메시지 보내기, 친구 API, 인공지능 API 등을 제공합니다.

developers.kakao.com

이걸 써보려고 한다.

 

일단 시작전에 postman으로 api를 실행해보겠다.

Auth에서 저렇게 설정하고 send 해보면

 

잘 나온다. 이제 이걸 적용하는게 문제다.

 

이런저런 구글링을 하니까 RestTemplate라는걸 사용하면 스프링에서 Rest Api를 호출할 수 있나보다.

https://spring.io/guides/gs/consuming-rest/

 

Consuming a RESTful Web Service

this guide is designed to get you productive as quickly as possible and using the latest Spring project releases and techniques as recommended by the Spring team

spring.io

뭔소리여

 

https://hyeonyeee.tistory.com/34

 

RestTemplate 를 이용하여 API Get 하기

1. RestTemplate이란? Spring 3.0부터 지원하며 스프링에서 http 통신에 유용하게 쓸수 있도록 제공해주는 템플릿이다. 즉, API 통신해서 가져 올수 있도록 도와준다. 2. 예시코드 @GetMapping("/test") public Re..

hyeonyeee.tistory.com

https://recordsoflife.tistory.com/360

 

RestTemplate 사용방법(예제)

Java 에코 시스템에서 몇 년간의 경험이 있고 그 경험을 커뮤니티와 공유하고 (물론 작업에 대한 대가를받는 데) 관심이 있다면 "Write for Us"페이지를 참조하십시오 . 건배, Eugen 1. 개요 이 튜토리얼

recordsoflife.tistory.com

이런 저런 블로그를 찾아봤고...

 

package jpa.myunjuk.common;

import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.util.UriComponentsBuilder;

import java.util.Map;

@RestController
public class KakaoApi {

    private final String url = "https://dapi.kakao.com/v3/search/book";
    private final String key = "rest api key";

    @GetMapping("/kakao")
    public Map callApi(@RequestParam String query){
        RestTemplate restTemplate = new RestTemplate();
        HttpHeaders httpHeaders = new HttpHeaders();
        httpHeaders.set("Authorization", "KakaoAK "+key);
        UriComponentsBuilder builder = UriComponentsBuilder.fromHttpUrl(url).queryParam("query", query);
        HttpEntity<String> entity = new HttpEntity<>(httpHeaders);

        return restTemplate.exchange(builder.toUriString(), HttpMethod.GET, entity, Map.class).getBody();
    }
}

여기까지 했다. 설명은 이따가 하기로 하고...

 

잘 나오긴 하는데 한글이 깨진다.

 

 

악 됐다!

 

https://cultist-tp.tistory.com/entry/Spring-RestTemplate-%EA%B0%9D%EC%B2%B4-%EC%82%AC%EC%9A%A9%EC%8B%9C-url%EC%97%90-%ED%8C%8C%EB%9D%BC%EB%AF%B8%ED%84%B0-%EC%A0%84%EB%8B%AC-%EB%B0%A9%EB%B2%95

 

Spring RestTemplate 객체 사용시, url에 파라미터 전달 방법

참조 : http://stackoverflow.com/questions/15774475/how-to-send-a-getforobject-request-with-parameters-spring-mvc RestTemplate 객체를 사용하여 url 주소를 호출과 동시에 파라미터를 전달 해줄 경우 Uri..

cultist-tp.tistory.com

여기 보고 해결했다.

 

package jpa.myunjuk.common;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.*;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.util.UriComponentsBuilder;

import java.net.URI;
import java.nio.charset.StandardCharsets;
import java.util.Map;

@RestController
public class KakaoApi {

    @Value("${kakao.key}")
    private String key;
    private String url = "https://dapi.kakao.com/v3/search/book";

    @GetMapping("/kakao")
    public Map callApi(@RequestParam String query) {
        RestTemplate restTemplate = new RestTemplate();
        HttpHeaders httpHeaders = new HttpHeaders();
        httpHeaders.set("Authorization", "KakaoAK " + key); //Authorization 설정
        HttpEntity<String> httpEntity = new HttpEntity<>(httpHeaders); //엔티티로 만들기
        URI targetUrl = UriComponentsBuilder
                .fromUriString(url) //기본 url
                .queryParam("query", query) //인자
                .build()
                .encode(StandardCharsets.UTF_8) //인코딩
                .toUri();

        //GetForObject는 헤더를 정의할 수 없음
        ResponseEntity<Map> result = restTemplate.exchange(targetUrl, HttpMethod.GET, httpEntity, Map.class);
        return result.getBody(); //내용 반환
    }
}

에러 핸들링을 안해서 코드가 짧다. 해야지...해야 하는데...

아무튼 대충 설명하면

 

    @Value("${kakao.key}")
    private String key;
    private String url = "https://dapi.kakao.com/v3/search/book";

일단 검색해본 결과 괜찮다곤 했는데, 키를 노출하는게 영 찝찝해서 application.yml에 api key를 보관했다.

 

application.yml

kakao:
  key: key 내용

이런식으로 하고 저렇게 value 어노테이션으로 호출하면 된다.

 

    @GetMapping("/kakao")
    public Map callApi(@RequestParam String query) {
        RestTemplate restTemplate = new RestTemplate();
        HttpHeaders httpHeaders = new HttpHeaders();
        httpHeaders.set("Authorization", "KakaoAK " + key); //Authorization 설정
        HttpEntity<String> httpEntity = new HttpEntity<>(httpHeaders); //엔티티로 만들기
        URI targetUrl = UriComponentsBuilder
                .fromUriString(url) //기본 url
                .queryParam("query", query) //인자
                .build()
                .encode(StandardCharsets.UTF_8) //인코딩
                .toUri();

        //GetForObject는 헤더를 정의할 수 없음
        ResponseEntity<Map> result = restTemplate.exchange(targetUrl, HttpMethod.GET, httpEntity, Map.class);
        return result.getBody(); //내용 반환
    }

그리고 여긴 실제로 구현할 땐 Service로 바꾸겠지만 일단 테스트라 API로 만들어서 바로 호출했다.

 

        RestTemplate restTemplate = new RestTemplate();
        HttpHeaders httpHeaders = new HttpHeaders();

RestTemplate는 기본이고, HttpHeaders는 Authorization 때문에 추가했다.

 

 

        httpHeaders.set("Authorization", "KakaoAK " + key); //Authorization 설정
        HttpEntity<String> httpEntity = new HttpEntity<>(httpHeaders); //엔티티로 만들기

저기 써있는데로 헤더에 인증 정보를 입력하고, 엔티티로 만들어 준다. post 호출일 때는 엔티티에 body도 넘긴다고 한 것 같다.

 

        URI targetUrl = UriComponentsBuilder
                .fromUriString(url) //기본 url
                .queryParam("query", query) //인자
                .build()
                .encode(StandardCharsets.UTF_8) //인코딩
                .toUri();

그리고 요청을 보낼 uri를 만든다. 개발가이드 보면 인자는 query로 넘겨야 한다. 그래서 그렇게 넘긴 것이다.

UTF-8로 인코딩하면 한글이 깨지지 않는다.

 

        //GetForObject는 헤더를 정의할 수 없음
        ResponseEntity<Map> result = restTemplate.exchange(targetUrl, HttpMethod.GET, httpEntity, Map.class);
        return result.getBody(); //내용 반환

마지막으로 exchange 메소드를 이용해서 호출하면 된다. 

getHeader()를 하면 헤더 정보가 나오고 getBody()를 하면 내용이 반환되는가보다.

 

인텔리제이피셜 넘겨야하는 인자는 위와 같다.

 

아무튼 잘 나온다!

 

하지만 여기서 끝난게 아니고 이 결과를 담을 Dto도 만들어야 하고 뭐 암튼 이것저것 할 것들이 많다.

+ Recent posts