Light Blue Pointer
๋ณธ๋ฌธ ๋ฐ”๋กœ๊ฐ€๊ธฐ
Developing/๊ฐœ๋ฐœ์ผ์ง€

2024-01-19,Today I Learned

by Greedy 2024. 1. 20.

๐Ÿš€๋ฆฌ๋ทฐ ํŽ˜์ด์ง€ ์ž‘์„ฑ

pastOrderList.forEach(order => {
      let menuList = order.menus.map(menu => menu.menuname).join('<br>');
      $('#my-order-info').append(`
         <div class="past-order-pack">
          <div class="past-order">
            <div>๊ฐ€๊ฒŒ ์ด๋ฆ„: ${order.store}</div>
            <div>์ˆ˜๋ น์ธ ์ด๋ฆ„: ${order.receiverName}</div>
            <div>๋ฉ”๋‰ด
              <div>${menuList}</div>
            </div>
          </div>
            <button type="button" class="btn btn-secondary" id="review-submit" onclick="createReview()">
              ๋ฆฌ๋ทฐ ๋‚จ๊ธฐ๊ธฐ
            </button>
          </div>
      `);
    });

 

๋ฆฌ๋ทฐ์— orderId๊ฐ€ ํ•„์š”ํ•˜๋‹ˆ๊นŒ ๊ทธ๊ฑฐ ๋‹ฌ์•„์คŒ

@Builder
public record OrderResponse (
    Long id,
    String store,
    String receiverName,
    List<MenuResponse> menus

){

}
<button type="button" class="btn btn-secondary" id="review-submit" order = "${order.id} onclick="createReview(this)">
function createReview(button){
    var orderId = $(button).attr("order");
    const host = 'http://' + window.location.host;
    window.location.replace(host + `/menu/${postId}`);
  }

orderId ๋„ฃ์–ด์ค€๋‹ค์Œ์— ํด๋ฆญ์‹œ์— ReviewFrontController ํ˜ธ์ถœํ•จ

@Controller
@RequiredArgsConstructor
public class ReviewFrontController {

    @GetMapping("/createreview/{orderId}")
    public String createReviewPage(
        @PathVariable(name = "orderId") Long orderId,
        Model model
    ) {
        model.addAttribute("orderId", orderId);
        return "domain/review/createreview";
    }

}

 

createreview.html ๋งŒ๋“ฆ

https://getbootstrap.kr/docs/5.0/forms/checks-radios/

 

์ฒดํฌ๋ฐ•์Šค์™€ ๋ผ๋””์˜ค๋ฒ„ํŠผ

์™„์ „ํžˆ ์ƒˆ๋กœ์›Œ ์ง„ ์ฒดํฌ ์ปดํฌ๋„ŒํŠธ๋ฅผ ์‚ฌ์šฉํ•ด ํฌ๋กœ์Šค ๋ธŒ๋ผ์šฐ์ €์™€ ํฌ๋กœ์Šค ๊ธฐ๊ธฐ๋กœ ์ผ๊ด€๋œ ์ฒดํฌ ๋ฐ•์Šค์™€ ๋ผ๋””์˜ค ๋ฒ„ํŠผ์„ ๋งŒ๋“ค ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

getbootstrap.kr

<input type="checkbox" class="btn-check" id="btn-check-outlined" autocomplete="off">
<label class="btn btn-outline-primary" for="btn-check-outlined">Single toggle</label><br>

์ด๊ฑฐ ์จ๋ด„

 

ReviewEnum ์ƒ์„ฑํ•จ

@Getter
@RequiredArgsConstructor
public enum ReviewEnum {
    //positive
    GOODMANNER("์นœ์ ˆํ•˜๊ณ  ๋งค๋„ˆ๊ฐ€ ์ข‹์•„์š”"),
    GOODTIME("์‹œ๊ฐ„ ์•ฝ์†์„ ์ž˜ ์ง€์ผœ์š”"),
    GOODCOMM("์†Œํ†ต๊ณผ ์‘๋‹ต์ด ๋นจ๋ผ์š”"),
    //negative
    BADTIME("์•ฝ์† ์‹œ๊ฐ„์— ๋‚˜ํƒ€๋‚˜์ง€ ์•Š์•˜์–ด์š”"),
    NOSHOW("์•„์˜ˆ ๋‚˜ํƒ€๋‚˜์ง€ ์•Š์•˜์–ด์š”"),
    NOMONEY("๊ฐ’์„ ์ง€๋ถˆํ•˜์ง€ ์•Š์•˜์–ด์š”"),
    BADCOMM("์†Œํ†ต๊ณผ ์‘๋‹ต์ด ๋Š๋ ค์š”"),
    BADMANNER("๋ถˆ์นœ์ ˆํ•˜๊ณ  ๋งค๋„ˆ๊ฐ€ ์ข‹์ง€ ์•Š์•„์š”");

    private final String comment;
}
<div style="padding:10px;width:1000px; margin:auto; height:max-content">
    <div>
      <input type="checkbox" class="btn-check" id="goodmanner" autocomplete="off">
      <label class="btn btn-outline-primary" onclick="goodmanner()" for="goodmanner">์นœ์ ˆํ•˜๊ณ  ๋งค๋„ˆ๊ฐ€ ์ข‹์•„์š”</label><br>
      <input type="checkbox" class="btn-check" id="goodtime" autocomplete="off">
      <label class="btn btn-outline-primary" onclick="goodtime()" for="goodtime">์‹œ๊ฐ„ ์•ฝ์†์„ ์ž˜ ์ง€์ผœ์š”</label><br>
      <input type="checkbox" class="btn-check" id="goodcomm" autocomplete="off">
      <label class="btn btn-outline-primary" onclick="goodcomm()" for="goodcomm">์†Œํ†ต๊ณผ ์‘๋‹ต์ด ๋นจ๋ผ์š”</label><br>
      <input type="checkbox" class="btn-check" id="badtime" autocomplete="off">
      <label class="btn btn-outline-primary" onclick="badtime()" for="badtime">์•ฝ์† ์‹œ๊ฐ„์— ๋‚˜ํƒ€๋‚˜์ง€ ์•Š์•˜์–ด์š”</label><br>
      <input type="checkbox" class="btn-check" id="noshow" autocomplete="off">
      <label class="btn btn-outline-primary" onclick="noshow()" for="noshow">์•„์˜ˆ ๋‚˜ํƒ€๋‚˜์ง€ ์•Š์•˜์–ด์š”</label><br>
      <input type="checkbox" class="btn-check" id="nomoney" autocomplete="off">
      <label class="btn btn-outline-primary" onclick="nomoney()" for="nomoney">๊ฐ’์„ ์ง€๋ถˆํ•˜์ง€ ์•Š์•˜์–ด์š”</label><br>
      <input type="checkbox" class="btn-check" id="badcomm" autocomplete="off">
      <label class="btn btn-outline-primary" onclick="badcomm()" for="badcomm">์†Œํ†ต๊ณผ ์‘๋‹ต์ด ๋Š๋ ค์š”</label><br>
      <input type="checkbox" class="btn-check" id="badmanner" autocomplete="off">
      <label class="btn btn-outline-primary" onclick="badmanner()" for="badmanner">๋ถˆ์นœ์ ˆํ•˜๊ณ  ๋งค๋„ˆ๊ฐ€ ์ข‹์ง€ ์•Š์•„์š”</label><br>
      <button class="btn btn-outline-secondary" menuId=${menu.id} onclick="sendReview()"
              type="button">๋ฆฌ๋ทฐ ์ „์†ก
      </button>
    </div>
    <div id="dropaddmenu">
  </div>
</div>
function createReview(button){
    var orderId = $(button).attr("order");
    const host = 'http://' + window.location.host;
    window.location.replace(host + `/review/${orderId}`);
  }
<button id = "${post.id}" post = "${post.id}"  class="btn btn-outline-secondary" onclick="sendData(this)" type="button">์กฐํšŒ</button>
              </div>
pastOrderList.forEach(order => {
      let menuList = order.menus.map(menu => menu.menuname).join('<br>');
      $('#my-order-info').append(`
         <div class="past-order-pack">
          <div class="past-order">
            <div>๊ฐ€๊ฒŒ ์ด๋ฆ„: ${order.store}</div>
            <div>์ˆ˜๋ น์ธ ์ด๋ฆ„: ${order.receiverName}</div>
            <div>๋ฉ”๋‰ด
              <div>${menuList}</div>
            </div>
          </div>
            <button type="button" class="btn btn-secondary" id="review-submit" order = "${order.id} onclick="createReview(this)">
              ๋ฆฌ๋ทฐ ๋‚จ๊ธฐ๊ธฐ
            </button>
          </div>
      `);
    });

  })
}

function createReview(button){
  var orderId = $(button).attr("order");
  const host = 'http://' + window.location.host;
  window.location.replace(host + `/review/${orderId}`);
}

์™œ ๋ฒ„ํŠผ์ด ์•ˆ ๋ˆŒ๋ฆฌ์ง€

function createReview(button){
  var orderId = $(button).attr("order");
  const host = 'http://' + window.location.host;
  window.location.replace(host + `/createreview/${orderId}`);
}
<button type="button" class="btn btn-secondary" id="review-submit" order = "${order.id} onclick="createReview(this)">

 

 

๐Ÿšฉ๋ฌธ์ œ : createReview๊ฐ€ ์•ˆ ๋ถˆ๋ฆฌ๋Š”๋“ฏ? ์ธ์‹์ด ์•ˆ ๋จ

์™œ no usage๋กœ ๋œจ์ง€?

 

โ›ณ ๋ฌธ์ œ ํ•ด๊ฒฐ : onclick ์‚ฌ์ด์— "๋ฅผ ์ถ”๊ฐ€ํ•ด์คŒ

<button type="button" class="btn btn-secondary" id="review-submit" order="${order.id}" onclick="createReview(this)">
  ๋ฆฌ๋ทฐ ๋‚จ๊ธฐ๊ธฐ
</button>

์˜คํƒ€ ์ˆ˜์ •ํ•˜๋‹ˆ๊นŒ ๋๋‹ค!

ํŽ˜์ด์ง€๊ฐ€ ์ž˜ ๋œฌ๋‹ค

 

<div style="padding:10px;width:1000px; margin:auto; height:max-content">
    <div>
      <input type="checkbox" class="btn-check" id="goodmanner" autocomplete="off">
      <label class="btn btn-outline-primary" onclick="goodmanner(this)" for="goodmanner">์นœ์ ˆํ•˜๊ณ  ๋งค๋„ˆ๊ฐ€ ์ข‹์•„์š”</label><br>
      <input type="checkbox" class="btn-check" id="goodtime" autocomplete="off">
      <label class="btn btn-outline-primary" onclick="goodtime(this)" for="goodtime">์‹œ๊ฐ„ ์•ฝ์†์„ ์ž˜ ์ง€์ผœ์š”</label><br>
      <input type="checkbox" class="btn-check" id="goodcomm" autocomplete="off">
      <label class="btn btn-outline-primary" onclick="goodcomm(this)" for="goodcomm">์†Œํ†ต๊ณผ ์‘๋‹ต์ด ๋นจ๋ผ์š”</label><br>
      <input type="checkbox" class="btn-check" id="badtime" autocomplete="off">
      <label class="btn btn-outline-primary" onclick="badtime(this)" for="badtime">์•ฝ์† ์‹œ๊ฐ„์— ๋‚˜ํƒ€๋‚˜์ง€ ์•Š์•˜์–ด์š”</label><br>
      <input type="checkbox" class="btn-check" id="noshow" autocomplete="off">
      <label class="btn btn-outline-primary" onclick="noshow(this)" for="noshow">์•„์˜ˆ ๋‚˜ํƒ€๋‚˜์ง€ ์•Š์•˜์–ด์š”</label><br>
      <input type="checkbox" class="btn-check" id="nomoney" autocomplete="off">
      <label class="btn btn-outline-primary" onclick="nomoney(this)" for="nomoney">๊ฐ’์„ ์ง€๋ถˆํ•˜์ง€ ์•Š์•˜์–ด์š”</label><br>
      <input type="checkbox" class="btn-check" id="badcomm" autocomplete="off">
      <label class="btn btn-outline-primary" onclick="badcomm(this)" for="badcomm">์†Œํ†ต๊ณผ ์‘๋‹ต์ด ๋Š๋ ค์š”</label><br>
      <input type="checkbox" class="btn-check" id="badmanner" autocomplete="off">
      <label class="btn btn-outline-primary" onclick="badmanner(this)" for="badmanner">๋ถˆ์นœ์ ˆํ•˜๊ณ  ๋งค๋„ˆ๊ฐ€ ์ข‹์ง€ ์•Š์•„์š”</label><br>
      <button class="btn btn-outline-secondary" menuId=${menu.id} onclick="sendReview()"
              type="button">๋ฆฌ๋ทฐ ์ „์†ก
      </button>
    </div>
    <div id="dropaddmenu">
  </div>
</div>

์ด๋ ‡๊ฒŒ ํ•˜๊ณ 

var goodmanner;
  var goodtime;
  var goodcomm;
  var badtime;
  var noshow;
  var nomoney;
  var badcomm;
  var badmanner;

  function goodmanner(label){
    var checkbox = $('#' + $(label).attr('for'));

    if (checkbox.prop('checked')) {
      goodmanner = true;
    } else {
      goodmanner = false;
    }
  }
  function goodtime(label){
    var checkbox = $('#' + $(label).attr('for'));

    if (checkbox.prop('checked')) {
      goodtime = true;
    } else {
      goodtime = false;
    }
  }
  function goodcomm(label){
    var checkbox = $('#' + $(label).attr('for'));

    if (checkbox.prop('checked')) {
      goodcomm = true;
    } else {
      goodcomm = false;
    }
  }
  function badtime(label){
    var checkbox = $('#' + $(label).attr('for'));

    if (checkbox.prop('checked')) {
      badtime = true;
    } else {
      badtime = false;
    }
  }
  function noshow(label){
    var checkbox = $('#' + $(label).attr('for'));

    if (checkbox.prop('checked')) {
      noshow = true;
    } else {
      noshow = false;
    }
  }
  function nomoney(label){
    var checkbox = $('#' + $(label).attr('for'));

    if (checkbox.prop('checked')) {
      nomoney = true;
    } else {
      nomoney = false;
    }
  }
  function badcomm(label){
    var checkbox = $('#' + $(label).attr('for'));

    if (checkbox.prop('checked')) {
      badcomm = true;
    } else {
      badcomm = false;
    }
  }
  function badmanner(label) {
    var checkbox = $('#' + $(label).attr('for'));

    if (checkbox.prop('checked')) {
      badmanner = true;
    } else {
      badmanner = false;
    }
  }

ํ•จ์ˆ˜ ๋‹ฌ์•„๋ด„

 

์ด์ œ ๋ฆฌ๋ทฐ๋ฅผ ๋ณด๋‚ด๋ด„

// ๋ฆฌ๋ทฐ ์ž‘์„ฑ
    @PostMapping("")
    public ApiResponse<Void> review(
        @AuthenticationPrincipal UserDetailsImpl userDetails,
        @RequestBody ReviewRequest reviewReq
    ) {
        reviewService.review(reviewReq, userDetails.getUser());
        return new ApiResponse<>(HttpStatus.OK.value(), "๋ฆฌ๋ทฐ๋ฅผ ์„ฑ๊ณต์ ์œผ๋กœ ์ „์†กํ–ˆ์Šต๋‹ˆ๋‹ค.");
    }

์—ฌ๊ธฐ๋กœ ๋ณด๋‚ด๋ฉด ๋จ

public record ReviewRequest(
    Long orderId,
    ScoreEnum score,
    boolean goodmanner,
    boolean goodtime,
    boolean goodcomm,
    boolean badtime,
    boolean noshow,
    boolean nomoney,
    boolean badcomm,
    boolean badmanner
) {

}
var checkbox = $('#' + $(label).attr('for'));
->
var checkbox = $(label).attr('for');

 

var goodmanner;
  var goodtime;
  var goodcomm;
  var badtime;
  var noshow;
  var nomoney;
  var badcomm;
  var badmanner;

  function goodmanner(label) {
    var checkbox = $(label).attr('for');

    if (checkbox.prop('checked')) {
      goodmanner = true;
    } else {
      goodmanner = false;
    }
  }

  function goodtime(label) {
    var checkbox = $(label).attr('for');

    if (checkbox.prop('checked')) {
      goodtime = true;
    } else {
      goodtime = false;
    }
  }

  function goodcomm(label) {
    var checkbox = $(label).attr('for');

    if (checkbox.prop('checked')) {
      goodcomm = true;
    } else {
      goodcomm = false;
    }
  }

  function badtime(label) {
    var checkbox = $(label).attr('for');

    if (checkbox.prop('checked')) {
      badtime = true;
    } else {
      badtime = false;
    }
  }

  function noshow(label) {
    var checkbox = $(label).attr('for');

    if (checkbox.prop('checked')) {
      noshow = true;
    } else {
      noshow = false;
    }
  }

  function nomoney(label) {
    var checkbox = $(label).attr('for');

    if (checkbox.prop('checked')) {
      nomoney = true;
    } else {
      nomoney = false;
    }
  }

  function badcomm(label) {
    var checkbox = $(label).attr('for');

    if (checkbox.prop('checked')) {
      badcomm = true;
    } else {
      badcomm = false;
    }
  }

  function badmanner(label) {
    var checkbox = $(label).attr('for');

    if (checkbox.prop('checked')) {
      badmanner = true;
    } else {
      badmanner = false;
    }
  }

์ € var๋“ค์„ sendReview/sendData์—์„œ ์ธ์‹์„ ๋ชปํ•ด์„œ ์•ˆ์ชฝ์œผ๋กœ ์˜ฎ๊น€

function sendReview() {

    let score = $('#customRange').val();

    var goodmanner;
    var goodmannerbox = $(goodmanner).attr('for');
    if (goodmannerbox.prop('checked')) {
      goodmanner = true;
    }

    sendData(score,goodmanner,goodtime,goodcomm,badtime,noshow,nomoney,badcomm,badmanner);
  }

  function sendData(score,goodmanner,goodtime,goodcomm,badtime,noshow,nomoney,badcomm,badmanner){
    let idForOrder = [[${orderId}]];

    $.ajax({
      type: 'POST',
      url: `/api/v1/reviews`,
      dataType: "json",
      contentType: 'application/json',
      data: JSON.stringify({
        orderId: idForOrder,
        score: score,
        goodmanner: goodmanner,
        goodtime: goodtime,
        goodcomm: goodcomm,
        badtime: badtime,
        noshow: noshow,
        nomoney: nomoney,
        badcomm: badcomm,
        badmanner: badmanner
      }),
      success: function (response) {
        console.log('Success:', response);
        alert(response.message);

      },
      error: function (error) {
        console.error('Error:', error);
      }
    });
  }

 

๐Ÿšฉ ๋ฌธ์ œ : ์ฒดํฌ๋ฅผ 

2:106 Uncaught TypeError: checkbox.prop is not a function at badtime (2:106:18) at HTMLLabelElement.onclick (2:41:82) badtime @ 2:106 onclick @ 2:41 2:159 Uncaught TypeError: Cannot read properties of undefined (reading 'prop') at sendReview (2:159:23) at HTMLButtonElement.onclick (2:55:27)

let score = $('#customRange').val();
    
    var goodmannerbox = $('#goodmanner');
    var goodmanner = goodmannerbox.checked;

์ด๋ ‡๊ฒŒ ํ•ด๋ด„

 

Resolved [org.springframework.http.converter.HttpMessageNotReadableException: JSON parse error: Cannot deserialize value of type boolean from Object value (token JsonToken.START_OBJECT)]

public record ReviewRequest(
    Long orderId,
    ScoreEnum score,
    boolean goodmanner,
    boolean goodtime,
    boolean goodcomm,
    boolean badtime,
    boolean noshow,
    boolean nomoney,
    boolean badcomm,
    boolean badmanner
) {

}

Boolean์œผ๋กœ ๋ฐ”๊ฟ”๋ด„

 

2024-01-19T15:40:21.105+09:00 WARN 13976 --- [nio-8080-exec-7] .w.s.m.s.DefaultHandlerExceptionResolver : Resolved [org.springframework.http.converter.HttpMessageNotReadableException: JSON parse error: Cannot deserialize value of type java.lang.Boolean from Object value (token JsonToken.START_OBJECT)]

๋˜ ๋˜‘๊ฐ™์€๊ฑฐ ๋œธ

2024-01-19T15:41:10.396+09:00 WARN 13976 --- [nio-8080-exec-3] .w.s.m.s.DefaultHandlerExceptionResolver : Resolved [org.springframework.http.converter.HttpMessageNotReadableException: JSON parse error: Cannot deserialize value of type java.lang.Boolean from Object value (token JsonToken.START_OBJECT)]

 

var goodmanner;
    var goodmannerbox = $('#goodmanner');
    if(goodmannerbox.checked){
      goodmanner = true;
    }

์ด๋ ‡๊ฒŒ ๋ฐ”๊ฟ”๋ด„

Resolved [org.springframework.http.converter.HttpMessageNotReadableException: JSON parse error: Cannot deserialize value of type java.lang.Boolean from Object value (token JsonToken.START_OBJECT)]

 

function sendReview() {

    let score = $('#customRange').val();

    var goodmanner;
    var goodmannerbox = $('#goodmanner');
    if(goodmannerbox.checked){
      goodmanner = "true";
    }

์ด๋ ‡๊ฒŒ ๋ฐ”๊ฟ”๋ด„

Resolved [org.springframework.http.converter.HttpMessageNotReadableException: JSON parse error: Cannot deserialize value of type java.lang.Boolean from Object value (token JsonToken.START_OBJECT)]

 

 

public record ReviewRequest(
    Long orderId,
    ScoreEnum score,
    boolean goodmanner,
    boolean goodtime,
    boolean goodcomm,
    boolean badtime,
    boolean noshow,
    boolean nomoney,
    boolean badcomm,
    boolean badmanner
) {

}

๋‹ค์‹œ๋ฐ”๊ฟ”๋ด„

Resolved [org.springframework.http.converter.HttpMessageNotReadableException: JSON parse error: Cannot deserialize value of type boolean from Object value (token JsonToken.START_OBJECT)]

 

if(goodmannerbox.checked){
      goodmanner = true;
    }else{
      goodmanner = false;
    }

์ด๋ ‡๊ฒŒ ํ•ด๋ด„

Resolved [org.springframework.http.converter.HttpMessageNotReadableException: JSON parse error: Cannot deserialize value of type boolean from Object value (token JsonToken.START_OBJECT)]

์ƒ๊ด€์—†์—ˆ์Œ

 

์™€ ์™œ ์•ˆ๋ ๊นŒ ํ•˜๊ณ  ์ฝ”๋“œ๋ณด๋ฉด์„œ ๋ฉ๋•Œ๋ฆฌ๋Š”๋ฐ ๊นจ๋‹ฌ์Œ์ด ์ฐพ์•„์˜ด

package com.moayo.moayoeats.backend.domain.review.dto.request;

import com.moayo.moayoeats.backend.domain.score.entity.ScoreEnum;

public record ReviewRequest(
    Long orderId,
    ScoreEnum score,
    boolean goodmanner,
    boolean goodtime,
    boolean goodcomm,
    boolean badtime,
    boolean noshow,
    boolean nomoney,
    boolean badcomm,
    boolean badmanner
) {

}

๋ฌธ์ œ๋Š” ๋‹ค๋ฅธ๋ฐ ์žˆ์—ˆ๋‹ค!!!

jsํŒŒ์ผ ๋ฐฑ๋‚  ๋“ค์—ฌ๋‹ค๋ด๋„ ์•ˆ๋จ

์™œ๋ƒ๋ฉด ๋ฌธ์ œ๋Š” Spring์ธก์— ์žˆ์œผ๋‹ˆ๊นŒ

Getter๋„ Setter๋„ Constructor๋„ ์•ˆ๋‹ฌ๋ ค์žˆ๋Š”๋ฐ ์–ด๋–ป๊ฒŒ ๋ณ€ํ™˜์‹œํ‚ค๋ƒ๊ณ ์š” ใ…‹ใ…‹ใ…‹

 

package com.moayo.moayoeats.backend.domain.review.dto.request;

import com.moayo.moayoeats.backend.domain.score.entity.ScoreEnum;
import lombok.Getter;
import lombok.RequiredArgsConstructor;

@Getter
@RequiredArgsConstructor
public record ReviewRequest(
    Long orderId,
    ScoreEnum score,
    boolean goodmanner,
    boolean goodtime,
    boolean goodcomm,
    boolean badtime,
    boolean noshow,
    boolean nomoney,
    boolean badcomm,
    boolean badmanner
) {

}

๋‘๊ฐœ ๋‹ฌ์•„์คฌ๋‹ค

์•„๋‹ˆ ์—๋Ÿฌ๋‚จ

๋ ˆ์ฝ”๋“œ๋Š” ์• ์ดˆ์— ํฌํ•จ์ด์•ผ

 

You expect a boolean from your @RequestBody Boolean vote however JSON sends text. You can either use the Payload class as suggested already but you can also simply change your controller to expect a String like this @RequestBody String vote and convert that string into boolean using Boolean.valueOf(vote) to be able to use it where you need it.

๋ผ๊ณ  ํ•˜๊ธธ๋ž˜ ๊ท€์ฐฎ์•„์„œ int๋กœ ๋ฐ”๊ฟ”์ฃผ๊ณ  0์ด๋ž‘ 1๋„ฃ์Œ

 

public record ReviewRequest(
    Long orderId,
    ScoreEnum score,
    Integer goodmanner,
    Integer goodtime,
    Integer goodcomm,
    Integer badtime,
    Integer noshow,
    Integer nomoney,
    Integer badcomm,
    Integer badmanner
) {

}
var goodmanner;
    var goodmannerbox = $('#goodmanner');
    if(goodmannerbox.checked){
      goodmanner = 1;
    }else{
      goodmanner = 0;
    }

 

์•„ ๊ทผ๋ฐ ๋‚ด๊ฐ€ ๊ท€์ฐฎ์•„์„œ goodmanner๊นŒ์ง€๋งŒ ํ•ด๋†”์„œ ๊ทธ๋žฌ๋˜๊ฑฐ๋ฉด ์–ด๋–กํ•˜์ง€ ใ…‹ใ…‹

sendData(score,goodmanner,goodtime,goodcomm,badtime,noshow,nomoney,badcomm,badmanner);

์™€ ๋…ธ๊ฐ€๋‹คํ–ˆ๋”๋‹ˆ ์ด์ œ ๋จ

function sendReview() {

    let score = $('#customRange').val();

    var goodmanner;
    var goodmannerbox = $('#goodmanner');
    if(goodmannerbox.checked){
      goodmanner = 1;
    }else{
      goodmanner = 0;
    }
    var goodtime;
    var goodtimebox = $('#goodtime');
    if(goodtimebox.checked){
      goodtime = 1;
    }else{
      goodtime = 0;
    }
    var goodcomm;
    var goodcommbox = $('#goodcomm');
    if(goodcommbox.checked){
      goodcomm = 1;
    }else{
      goodcomm = 0;
    }
    var badtime;
    var badtimebox = $('#goodcomm');
    if(badtimebox.checked){
      badtime = 1;
    }else{
      badtime = 0;
    }
    var noshow;
    var noshowbox = $('#goodcomm');
    if(noshowbox.checked){
      noshow = 1;
    }else{
      noshow = 0;
    }
    var nomoney;
    var nomoneybox = $('#goodcomm');
    if(nomoneybox.checked){
      nomoney = 1;
    }else{
      nomoney = 0;
    }
    var badcomm;
    var badcommbox = $('#goodcomm');
    if(badcommbox.checked){
      badcomm = 1;
    }else{
      badcomm = 0;
    }
    var badmanner;
    var badmannerbox = $('#goodcomm');
    if(badmannerbox.checked){
      badmanner = 1;
    }else{
      badmanner = 0;
    }

    sendData(score,goodmanner,goodtime,goodcomm,badtime,noshow,nomoney,badcomm,badmanner);
  }

  function sendData(score,goodmanner,goodtime,goodcomm,badtime,noshow,nomoney,badcomm,badmanner){
    let idForOrder = [[${orderId}]];

    $.ajax({
      type: 'POST',
      url: `/api/v1/reviews`,
      dataType: "json",
      contentType: 'application/json',
      data: JSON.stringify({
        orderId: idForOrder,
        score: score,
        goodmanner: goodmanner,
        goodtime: goodtime,
        goodcomm: goodcomm,
        badtime: badtime,
        noshow: noshow,
        nomoney: nomoney,
        badcomm: badcomm,
        badmanner: badmanner
      }),
      success: function (response) {
        console.log('Success:', response);
        alert(response.message);

      },
      error: function (error) {
        console.error('Error:', error);
      }
    });
  }

 

 

๊ทผ๋ฐ ๋‚ด๊ฐ€ ๋ฐ”๋ณด์ง“ํ–ˆ๋‹ค๋Š” ์ƒ๊ฐ์„ ์ง€์šธ์ˆ˜๊ฐ€ ์—†์Œ

๊ฐ’์„ ์•ˆ ๋ณด๋‚ด๋†“๊ณ  ๊ทธ๋ƒฅ goodtime:goodtime์œผ๋กœ ์ง€์ •ํ•˜๊ณ  ์žˆ์–ด์„œ ๊ทธ๋žฌ๋˜๊ฑฐ๊ฐ™์€๋ฐ…

๋‹ค์‹œ ๋˜๋Œ๋ฆฌ๊ณ  ํ•ด๋ด„

public record ReviewRequest(
    Long orderId,
    ScoreEnum score,
    Integer goodmanner,
    Integer goodtime,
    Integer goodcomm,
    Integer badtime,
    Integer noshow,
    Integer nomoney,
    Integer badcomm,
    Integer badmanner
) {

}

package com.moayo.moayoeats.backend.domain.review.dto.request;

import com.moayo.moayoeats.backend.domain.score.entity.ScoreEnum;

public record ReviewRequest(
    Long orderId,
    ScoreEnum score,
    boolean goodmanner,
    boolean goodtime,
    boolean goodcomm,
    boolean badtime,
    boolean noshow,
    boolean nomoney,
    boolean badcomm,
    boolean badmanner
) {

}

 

 

private void updateReview(ReviewRequest reviewReq, User receiver) {

        List<Review> reviews = reviewRepository.findAllByUser(receiver);
        List<Review> updated = new ArrayList<>();

        if (reviewReq.goodmanner()==1) {
            Review review = findReviewByContent(reviews, ReviewEnum.GOODMANNER, receiver);
            review.increaseCount();
            updated.add(review);
        }
        if (reviewReq.goodcomm()==1) {
            Review review = findReviewByContent(reviews, ReviewEnum.GOODCOMM, receiver);
            review.increaseCount();
            updated.add(review);
        }
        if (reviewReq.goodtime()==1) {
            Review review = findReviewByContent(reviews, ReviewEnum.GOODTIME, receiver);
            review.increaseCount();
            updated.add(review);
        }
        if (reviewReq.badtime()==1) {
            Review review = findReviewByContent(reviews, ReviewEnum.BADTIME, receiver);
            review.increaseCount();
            updated.add(review);
        }
        if (reviewReq.noshow()==1) {
            Review review = findReviewByContent(reviews, ReviewEnum.NOSHOW, receiver);
            review.increaseCount();
            updated.add(review);
        }
        if (reviewReq.nomoney()==1) {
            Review review = findReviewByContent(reviews, ReviewEnum.NOMONEY, receiver);
            review.increaseCount();
            updated.add(review);
        }
        if (reviewReq.badcomm()==1) {
            Review review = findReviewByContent(reviews, ReviewEnum.BADCOMM, receiver);
            review.increaseCount();
            updated.add(review);
        }
        if (reviewReq.badmanner()==1) {
            Review review = findReviewByContent(reviews, ReviewEnum.BADMANNER, receiver);
            review.increaseCount();
            updated.add(review);
        }
        reviewRepository.saveAll(updated);
    }

private void updateReview(ReviewRequest reviewReq, User receiver) {

        List<Review> reviews = reviewRepository.findAllByUser(receiver);
        List<Review> updated = new ArrayList<>();

        if (reviewReq.goodmanner()) {
            Review review = findReviewByContent(reviews, ReviewEnum.GOODMANNER, receiver);
            review.increaseCount();
            updated.add(review);
        }
        if (reviewReq.goodcomm()) {
            Review review = findReviewByContent(reviews, ReviewEnum.GOODCOMM, receiver);
            review.increaseCount();
            updated.add(review);
        }
        if (reviewReq.goodtime()) {
            Review review = findReviewByContent(reviews, ReviewEnum.GOODTIME, receiver);
            review.increaseCount();
            updated.add(review);
        }
        if (reviewReq.badtime()) {
            Review review = findReviewByContent(reviews, ReviewEnum.BADTIME, receiver);
            review.increaseCount();
            updated.add(review);
        }
        if (reviewReq.noshow()) {
            Review review = findReviewByContent(reviews, ReviewEnum.NOSHOW, receiver);
            review.increaseCount();
            updated.add(review);
        }
        if (reviewReq.nomoney()) {
            Review review = findReviewByContent(reviews, ReviewEnum.NOMONEY, receiver);
            review.increaseCount();
            updated.add(review);
        }
        if (reviewReq.badcomm()) {
            Review review = findReviewByContent(reviews, ReviewEnum.BADCOMM, receiver);
            review.increaseCount();
            updated.add(review);
        }
        if (reviewReq.badmanner()) {
            Review review = findReviewByContent(reviews, ReviewEnum.BADMANNER, receiver);
            review.increaseCount();
            updated.add(review);
        }
        reviewRepository.saveAll(updated);
    }

์ƒˆ๋กœ์šด ๋ฌธ์ œ ๋ฐœ์ƒ

์•„ ์ € ํ•จ์ˆ˜๋“ค ๋‹ค ์ง€์šฐ๊ณ  onclick์—์„œ๋Š” ์•ˆ ์ง€์›Œ์„œ ์ €๋Ÿฌ๋Š”๊ฑฐ์ž„

 

์ „์†ก์€ ๋˜๋Š”๋ฐ ๋ญ๊ฐ€๋œ๊ฑฐ์ง€

์•ˆ ๋“ค์–ด์˜จ ๊ฑฐ ๊ฐ™์€๋ฐ

14๋ฒˆ Order์— ๋Œ€ํ•ด์„œ ๋ฆฌ๋ทฐ๋ฅผ ์จ๋ด„

Order๋Š” ์‚ญ์ œ๋˜๋Š”๋ฐ

Review๋Š” ์•ˆ ์ƒ๊น€

@Override
    public void review(ReviewRequest reviewReq, User user) {
        Order order = findOrderById(reviewReq.orderId());
        //check if the receiver exists, to clarify that the review hasn't been made, not because the user doesn't exist
        if (!order.getUser().getId().equals(user.getId())) {
            throw new GlobalException(OrderErrorCode.FORBIDDEN_ACCESS);
        }
        User receiver = order.getReceiver();
        checkIfUserExists(receiver.getId());
        updateScore(reviewReq.score(), receiver);
        updateReview(reviewReq, receiver);
        orderRepository.delete(order);
    }
private void updateReview(ReviewRequest reviewReq, User receiver) {

        List<Review> reviews = reviewRepository.findAllByUser(receiver);
        List<Review> updated = new ArrayList<>();

        if (reviewReq.goodmanner()) {
            Review review = findReviewByContent(reviews, ReviewEnum.GOODMANNER, receiver);
            review.increaseCount();
            updated.add(review);
        }
        if (reviewReq.goodcomm()) {
            Review review = findReviewByContent(reviews, ReviewEnum.GOODCOMM, receiver);
            review.increaseCount();
            updated.add(review);
        }
        if (reviewReq.goodtime()) {
            Review review = findReviewByContent(reviews, ReviewEnum.GOODTIME, receiver);
            review.increaseCount();
            updated.add(review);
        }
        if (reviewReq.badtime()) {
            Review review = findReviewByContent(reviews, ReviewEnum.BADTIME, receiver);
            review.increaseCount();
            updated.add(review);
        }
        if (reviewReq.noshow()) {
            Review review = findReviewByContent(reviews, ReviewEnum.NOSHOW, receiver);
            review.increaseCount();
            updated.add(review);
        }
        if (reviewReq.nomoney()) {
            Review review = findReviewByContent(reviews, ReviewEnum.NOMONEY, receiver);
            review.increaseCount();
            updated.add(review);
        }
        if (reviewReq.badcomm()) {
            Review review = findReviewByContent(reviews, ReviewEnum.BADCOMM, receiver);
            review.increaseCount();
            updated.add(review);
        }
        if (reviewReq.badmanner()) {
            Review review = findReviewByContent(reviews, ReviewEnum.BADMANNER, receiver);
            review.increaseCount();
            updated.add(review);
        }
        reviewRepository.saveAll(updated);
    }

 

 

Score๋„ ๋“ค์–ด๊ฐ€๋Š”์ง€ ๋ชจ๋ฅด๊ฒ ์Œ

private Review findReviewByContent(List<Review> reviews, ReviewEnum content, User user) {
        //get Review when exists, make a new one when not
        for (Review review : reviews) {
            if (review.getContent().equals(content)) {
                reviews.remove(review);
                return review;
            }
        }
        return new Review(user, content);
    }

์—†์œผ๋ฉด ๋งŒ๋“ค์–ด์•ผ ๋˜๋Š”๋ฐ

์ €๊ฒŒ ๋‹ค ๋™์ž‘์ด ์•ˆ ํ•˜๋Š”๊ฑด

if (reviewReq.goodmanner()) {

์ด๊ฑฐ๋ถ€ํ„ฐ ๋™์ž‘์„ ์•ˆ ํ–ˆ๊ธฐ ๋•Œ๋ฌธ์ธ๊ฑฐ ๊ฐ™์Œ

 

ํฌ์ŠคํŠธ๋งจ์œผ๋กœ ํ…Œ์ŠคํŠธํ•ด๋ด„

16๋ฒˆ์œผ๋กœ ํ…Œ์ŠคํŠธํ•ด๋ด„

{
    "orderId" : 16,
    "score" : "FIVE",
    "goodmanner" : true,
    "goodtime" : true
}
{
    "status": 200,
    "message": "๋ฆฌ๋ทฐ๋ฅผ ์„ฑ๊ณต์ ์œผ๋กœ ์ „์†กํ–ˆ์Šต๋‹ˆ๋‹ค.",
    "data": null
}

์ผ๋‹จ Order๋Š” ์„ฑ๊ณต์ ์œผ๋กœ ์‚ฌ๋ผ์ง€๊ณ 

Review๋„ ์ƒ๊น€ใ…œใ…œ

 

boolean๋Œ€์‹  ๊ทธ๋ƒฅ int๋ฅผ ๋ณด๋‚ด๋ด„

package com.moayo.moayoeats.backend.domain.review.dto.request;

import com.moayo.moayoeats.backend.domain.score.entity.ScoreEnum;

public record ReviewRequest(
    Long orderId,
    ScoreEnum score,
    Integer goodmanner,
    Integer goodtime,
    Integer goodcomm,
    Integer badtime,
    Integer noshow,
    Integer nomoney,
    Integer badcomm,
    Integer badmanner
) {

}
function sendReview() {

    let score = $('#customRange').val();
    let scoreEnum;
    if(score === 1){
      scoreEnum = "ONE"
    }else if(score === 2){
      scoreEnum = "TWO"
    }else if(score === 3){
      scoreEnum = "THREE"
    }else if(score === 4){
      scoreEnum = "FOUR"
    }else if(score === 5){
      scoreEnum = "FIVE"
    }

    var goodmanner;
    var goodmannerbox = $('#goodmanner');
    if(goodmannerbox.checked){
      goodmanner = 1;
    }else{
      goodmanner = 0;
    }
    var goodtime;
    var goodtimebox = $('#goodtime');
    if(goodtimebox.checked){
      goodtime = 1;
    }else{
      goodtime = 0;
    }
    var goodcomm;
    var goodcommbox = $('#goodcomm');
    if(goodcommbox.checked){
      goodcomm = 1;
    }else{
      goodcomm = 0;
    }
    var badtime;
    var badtimebox = $('#goodcomm');
    if(badtimebox.checked){
      badtime = 1;
    }else{
      badtime = 0;
    }
    var noshow;
    var noshowbox = $('#goodcomm');
    if(noshowbox.checked){
      noshow = 1;
    }else{
      noshow = 0;
    }
    var nomoney;
    var nomoneybox = $('#goodcomm');
    if(nomoneybox.checked){
      nomoney = 1;
    }else{
      nomoney = 0;
    }
    var badcomm;
    var badcommbox = $('#goodcomm');
    if(badcommbox.checked){
      badcomm = 1;
    }else{
      badcomm = 0;
    }
    var badmanner;
    var badmannerbox = $('#goodcomm');
    if(badmannerbox.checked){
      badmanner = 1;
    }else{
      badmanner = 0;
    }

    sendData(scoreEnum,goodmanner,goodtime,goodcomm,badtime,noshow,nomoney,badcomm,badmanner);
  }

  function sendData(score,goodmanner,goodtime,goodcomm,badtime,noshow,nomoney,badcomm,badmanner){
    let idForOrder = [[${orderId}]];

    $.ajax({
      type: 'POST',
      url: `/api/v1/reviews`,
      dataType: "json",
      contentType: 'application/json',
      data: JSON.stringify({
        orderId: idForOrder,
        score: score,
        goodmanner: goodmanner,
        goodtime: goodtime,
        goodcomm: goodcomm,
        badtime: badtime,
        noshow: noshow,
        nomoney: nomoney,
        badcomm: badcomm,
        badmanner: badmanner
      }),
      success: function (response) {
        console.log('Success:', response);
        alert(response.message);

      },
      error: function (error) {
        console.error('Error:', error);
      }
    });
  }

 

๋‹ค์‹œ ํ•ด๋ด„

2024-01-19T16:26:57.703+09:00 ERROR 32796 --- [nio-8080-exec-2] o.a.c.c.C.[.[.[/].[dispatcherServlet]    : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed: java.lang.NullPointerException: Cannot invoke "com.moayo.moayoeats.backend.domain.score.entity.ScoreEnum.getScore()" because "score" is null] with root cause

java.lang.NullPointerException: Cannot invoke "com.moayo.moayoeats.backend.domain.score.entity.ScoreEnum.getScore()" because "score" is null
at com.moayo.moayoeats.backend.domain.score.entity.Score.update(Score.java:44) ~[main/:na]

 

 

private void updateScore(ScoreEnum scoreEnum, User user) {
        Score score = findScoreByUser(user);
        score.update(scoreEnum);//->์ด๊ฒŒ ์—๋Ÿฌ๊ฐ€ ๋‚จ
        scoreRepository.save(score);
    }
private Score findScoreByUser(User user) {
        return scoreRepository.findByUser(user).orElse(new Score(user));
    }
public void update(ScoreEnum score){
        this.total += score.getScore();
        this.count++;
    }

ScoreEnum์ด ์™œ null์ธ๋ฐ์š”

์•„ 0์ด๋ผ ์•ˆ ๋„ฃ์–ด์คฌ๋‚˜๋ด„

 

let score = $('#customRange').val();
    let scoreEnum;
    if(score === 1){
      scoreEnum = "ONE"
    }else if(score === 2){
      scoreEnum = "TWO"
    }else if(score === 3){
      scoreEnum = "THREE"
    }else if(score === 4){
      scoreEnum = "FOUR"
    }else if(score === 5){
      scoreEnum = "FIVE"
    }
<label for="customRange" class="form-label">์ ์ˆ˜</label>
    <input type="range" class="form-range" min="0" max="5" id="customRange">

min 0 → min 1

๋‹ค์‹œ ํ•ด๋ด„

java.lang.NullPointerException: Cannot invoke "com.moayo.moayoeats.backend.domain.score.entity.ScoreEnum.getScore()" because "score" is null at com.moayo.moayoeats.backend.domain.score.entity.Score.update(Score.java:44) ~[main/:na]

๋˜ ์ด๋Ÿฌ๋„ค

let score = $('#customRange').val();
    let scoreEnum;
    if(score === 1){
      scoreEnum = "ONE"
    }else if(score === 2){
      scoreEnum = "TWO"
    }else if(score === 3){
      scoreEnum = "THREE"
    }else if(score === 4){
      scoreEnum = "FOUR"
    }else if(score === 5){
      scoreEnum = "FIVE"
    }

์ด๊ฒŒ ์•ˆ ๋˜๋Š” ๊ฑฐ ๊ฐ™์Œ

 

// Convert the string to a number
score = parseInt(score, 10);

์ด๋ ‡๊ฒŒ ํ•ด์ฃผ๋˜๊ฐ€

์•„๋‹ˆ๋ฉด ๊ทธ๋ƒฅ ==์œผ๋กœ ๋น„๊ตํ•ด์•ผํ•œ๋‹ค๊ณ  ํ•จ

 

let score = $('#customRange').val();
    let scoreEnum;
    if(score == 1){
      scoreEnum = "ONE"
    }else if(score == 2){
      scoreEnum = "TWO"
    }else if(score == 3){
      scoreEnum = "THREE"
    }else if(score == 4){
      scoreEnum = "FOUR"
    }else if(score == 5){
      scoreEnum = "FIVE"
    }

์ด๋ ‡๊ฒŒ ํ•ด๋ด„

์•„๋‹ˆ ๋ฆฌ๋ทฐ๊ฐ€ ์•ˆ ์ƒ๊ฒจ์š”…..

์ด๊ฒŒ Spring์ธก์—์„œ ํƒ€์ž…๋ณ€ํ™˜ ์˜ค๋ฅ˜๊ฐ€ ์ƒ๊ธฐ์ง„ ์•Š์œผ๋‹ˆ๊นŒ ํ”„๋ก ํŠธ ๋ฌธ์ œ๋ผ๊ณ  ์˜ˆ์ธกํ•ด๋ด„

var goodmanner;
    var goodmannerbox = $('#goodmanner');
    if(goodmannerbox.is(':checked')){
      goodmanner = 1;
    }else{
      goodmanner = 0;
    }
    var goodtime;
    var goodtimebox = $('#goodtime');
    if(goodtimebox.is(':checked')){
      goodtime = 1;
    }else{
      goodtime = 0;
    }
    var goodcomm;
    var goodcommbox = $('#goodcomm');
    if(goodcommbox.is(':checked')){
      goodcomm = 1;
    }else{
      goodcomm = 0;
    }
    var badtime;
    var badtimebox = $('#goodcomm');
    if(badtimebox.is(':checked')){
      badtime = 1;
    }else{
      badtime = 0;
    }
    var noshow;
    var noshowbox = $('#goodcomm');
    if(noshowbox.is(':checked')){
      noshow = 1;
    }else{
      noshow = 0;
    }
    var nomoney;
    var nomoneybox = $('#goodcomm');
    if(nomoneybox.is(':checked')){
      nomoney = 1;
    }else{
      nomoney = 0;
    }
    var badcomm;
    var badcommbox = $('#goodcomm');
    if(badcommbox.is(':checked')){
      badcomm = 1;
    }else{
      badcomm = 0;
    }
    var badmanner;
    var badmannerbox = $('#goodcomm');
    if(badmannerbox.is(':checked')){
      badmanner = 1;
    }else{
      badmanner = 0;
    }

์ด๋ ‡๊ฒŒ ํ•ด๋ด„

 

User 2 ๋กœ ๋กœ๊ทธ์ธํ•ด์„œ ํ•ด๋ด„

 

๐Ÿšฉ๋ฌธ์ œ : ๋ฆฌ๋ทฐ๋ฅผ ์ž‘์„ฑํ•ด๋„ db์— ์ €์žฅ๋˜์ง€ ์•Š์Œ

Order 5๋ฒˆ์— ๋Œ€ํ•ด์„œ

๋ฆฌ๋ทฐ๋ฅผ ๋‚ ๋ ค๋ด๋„ db์— ์ €์žฅ๋˜์ง€ ์•Š์Œ

 

const is_checked = checkbox.checked;

.checked๋ฅผ ์จ๋ด„

 

var goodmanner;
    var goodmannerbox = $('#goodmanner');
    if(goodmannerbox.checked){
      goodmanner = 1;
    }else{
      goodmanner = 0;
    }
    var goodtime;
    var goodtimebox = $('#goodtime');
    if(goodtimebox.checked){
      goodtime = 1;
    }else{
      goodtime = 0;
    }
    var goodcomm;
    var goodcommbox = $('#goodcomm');
    if(goodcommbox.checked){
      goodcomm = 1;
    }else{
      goodcomm = 0;
    }
    var badtime;
    var badtimebox = $('#goodcomm');
    if(badtimebox.checked){
      badtime = 1;
    }else{
      badtime = 0;
    }
    var noshow;
    var noshowbox = $('#goodcomm');
    if(noshowbox.checked){
      noshow = 1;
    }else{
      noshow = 0;
    }
    var nomoney;
    var nomoneybox = $('#goodcomm');
    if(nomoneybox.checked){
      nomoney = 1;
    }else{
      nomoney = 0;
    }
    var badcomm;
    var badcommbox = $('#goodcomm');
    if(badcommbox.checked){
      badcomm = 1;
    }else{
      badcomm = 0;
    }
    var badmanner;
    var badmannerbox = $('#goodcomm');
    if(badmannerbox.is(':checked')){
      badmanner = 1;
    }else{
      badmanner = 0;
    }

์•„๋‹ˆ ์ง€๊ธˆ๋ณด๋‹ˆ ๋‹ค goodcomm์œผ๋กœ ๋œ๊ฒƒ๋„ ์žˆ์–ด์„œ ์ˆ˜์ •ํ•จ

 

๋ฆฌ๋ทฐ๋ฅผ ๋ณด๋‚ด๋ณด์•˜๋‹ค

Score๋Š” ์ด์ œ ์ž˜ ๋“ค์–ด๊ฐ

Review๋Š” ๋“ค์–ด๊ฐ€์ง€์ง€ ์•Š๋Š”๋‹ค

NOTIME count๊ฐ€ ์ƒ์„ฑ๋˜์ง€ ์•Š์Œ

function sendReview() {

    let score = $('#customRange').val();
    let scoreEnum;
    if(score == 1){
      scoreEnum = "ONE"
    }else if(score == 2){
      scoreEnum = "TWO"
    }else if(score == 3){
      scoreEnum = "THREE"
    }else if(score == 4){
      scoreEnum = "FOUR"
    }else if(score == 5){
      scoreEnum = "FIVE"
    }

    var goodmanner;
    var goodmannerbox = $('#goodmanner');
    if(goodmannerbox.prop('checked')){
      goodmanner = 1;
    }else{
      goodmanner = 0;
    }
    var goodtime;
    var goodtimebox = $('#goodtime');
    if(goodtimebox.prop('checked')){
      goodtime = 1;
    }else{
      goodtime = 0;
    }
    var goodcomm;
    var goodcommbox = $('#goodcomm');
    if(goodcommbox.prop('checked')){
      goodcomm = 1;
    }else{
      goodcomm = 0;
    }
    var badtime;
    var badtimebox = $('#goodcomm');
    if(badtimebox.prop('checked')){
      badtime = 1;
    }else{
      badtime = 0;
    }
    var noshow;
    var noshowbox = $('#goodcomm');
    if(noshowbox.prop('checked')){
      noshow = 1;
    }else{
      noshow = 0;
    }
    var nomoney;
    var nomoneybox = $('#goodcomm');
    if(nomoneybox.prop('checked')){
      nomoney = 1;
    }else{
      nomoney = 0;
    }
    var badcomm;
    var badcommbox = $('#goodcomm');
    if(badcommbox.prop('checked')){
      badcomm = 1;
    }else{
      badcomm = 0;
    }
    var badmanner;
    var badmannerbox = $('#goodcomm');
    if(badmannerbox.prop('checked')){
      badmanner = 1;
    }else{
      badmanner = 0;
    }

    sendData(scoreEnum,goodmanner,goodtime,goodcomm,badtime,noshow,nomoney,badcomm,badmanner);
  }

์ด๋ ‡๊ฒŒ ํ•˜๊ณ 

const goodmannerbox = document.getElementById('goodmanner');
var goodmanner = goodmannerbox.checked ? 1 : 0;

const goodtimebox = document.getElementById('goodtime');
var goodtime = goodtimebox.checked ? 1 : 0;

const goodcommbox = document.getElementById('goodcomm');
var goodcomm = goodcommbox.checked ? 1 : 0;

const badtimebox = document.getElementById('badtime');
var badtime = badtimebox.checked ? 1 : 0;

const noshowbox = document.getElementById('noshow');
var noshow = noshowbox.checked ? 1 : 0;

const nomoneybox = document.getElementById('nomoney');
var nomoney = nomoneybox.checked ? 1 : 0;

const badcommbox = document.getElementById('badcomm');
var badcomm = badcommbox.checked ? 1 : 0;

const badmannerbox = document.getElementById('badmanner');
var badmanner = badmannerbox.checked ? 1 : 0;

์ด๋ ‡๊ฒŒ ๋ฐ”๊ฟ”๋ด„

 

const goodmannerbox = document.getElementById('goodmanner');
var goodmanner = goodmannerbox.checked ? 1 : 0;

const goodtimebox = document.getElementById('goodtime');
var goodtime = goodtimebox.checked ? 1 : 0;

const goodcommbox = document.getElementById('goodcomm');
var goodcomm = goodcommbox.checked ? 1 : 0;

const badtimebox = document.getElementById('badtime');
var badtime = badtimebox.checked ? 1 : 0;

const noshowbox = document.getElementById('noshow');
var noshow = noshowbox.checked ? 1 : 0;

const nomoneybox = document.getElementById('nomoney');
var nomoney = nomoneybox.checked ? 1 : 0;

const badcommbox = document.getElementById('badcomm');
var badcomm = badcommbox.checked ? 1 : 0;

const badmannerbox = document.getElementById('badmanner');
var badmanner = badmannerbox.checked ? 1 : 0;

์ด๋ ‡๊ฒŒ ๋ฐ”๊ฟ”๋ด„

๋‹ค์‹œ ํ•ด๋ด„

์ž˜ ๋“ค์–ด์™”๋‹ค

 

 

์ „์ฒด๊ธ€ ํŽ˜์ด์ง€ ๋งŒ๋“ค์–ด๋ด„

// ๋ชจ๋“  ๊ธ€ ์กฐํšŒํ•˜๊ธฐ
    @GetMapping("/posts")
    public ApiResponse<List<BriefPostResponse>> getPosts(
        @AuthenticationPrincipal UserDetailsImpl userDetails) {
        return new ApiResponse<>(HttpStatus.OK.value(), "๋ชจ๋“  ๊ธ€ ์กฐํšŒ์— ์„ฑ๊ณตํ–ˆ์Šต๋‹ˆ๋‹ค.",
            postService.getPosts(userDetails.getUser()));
    }
//๊ธ€ ์นดํ…Œ๊ณ ๋ฆฌ๋ณ„ ์กฐํšŒ
    @GetMapping("/posts/category")
    public ApiResponse<List<BriefPostResponse>> getPostsByCategory(
        @AuthenticationPrincipal UserDetailsImpl userDetails,
        @Valid @RequestBody PostCategoryRequest postCategorySearchReq
    ) {
        return new ApiResponse<>(HttpStatus.OK.value(), "๊ธ€ ์นดํ…Œ๊ณ ๋ฆฌ๋ณ„ ์กฐํšŒ์— ์„ฑ๊ณตํ–ˆ์Šต๋‹ˆ๋‹ค.",
            postService.getPostsByCategory(postCategorySearchReq, userDetails.getUser()));
    }
public record PostCategoryRequest(@NotNull @Category String category) {

}
function getDataByCategory(categoryEnum){
    let category = categoryEnum;
    
    $.ajax({
      type: 'GET',
      url: `/api/v1/posts/category`,
      dataType: "json",
      contentType: 'application/json',
      data: JSON.stringify({
        category: category
      }),
      success: function (response) {
        console.log('Success:', response);

        drawAllPosts(response.data);

      },
      error: function (error) {
        console.error('Error:', error);
      }
    });
  }

์ด๋ ‡๊ฒŒ ํ•ด๋ด„

์ €๊ฑฐ ๋ˆ„๋ฅด๋ฉด ์ƒˆ๋กœ ๊ฒฐ๊ณผ ๋ฐ›์•„์™€์„œ ํ™”๋ฉด์— ์ถœ๋ ฅํ• ๊ฑด๋ฐ ๊ทธ๋Ÿผ ๊ธฐ์กด ๊ฒฐ๊ณผ๋Š” ์‚ญ์ œํ•ด์•ผํ•˜์ง€ ์•Š๋‚˜ ์‹ถ์–ด์„œ removeํ•จ์ˆ˜ ์•Œ์•„๋ด„

https://developer.mozilla.org/en-US/docs/Web/API/Element/remove

๊ทผ๋ฐ ์ด๊ฑฐ ๋ง๊ณ  child๋“ค์„ ๋‹ค removeํ•˜๊ณ  ์‹ถ์Œ

https://developer.mozilla.org/en-US/docs/Web/API/Node/removeChild

<div id="parent">
  <div id="child"></div>
</div>
const parent = document.getElementById("parent");
const child = document.getElementById("child");
const throwawayNode = parent.removeChild(child);

๊ทผ๋ฐ ๋‚˜๋Š” child๊ฐ€ ์—ฌ๋Ÿฌ๊ฐ ๋ฐ?

To remove all children from an element:

const element = document.getElementById("idOfParent");
while (element.firstChild) {
  element.removeChild(element.firstChild);
}

์ด๋ ‡๊ฒŒ ํ•ด ๋ด„

function removeAllPosts(){
    const element = document.getElementById("posts");
    while (element.firstChild) {
      element.removeChild(element.firstChild);
    }
  }
function all(){
    removeAllPosts();
    getData();
  }

์ „์ฒด๋ฅผ ๊ณ ๋ฅด๋ฉด ๋‹ค ์ง€์šฐ๊ณ  ์ƒˆ๋กœ ์ถœ๋ ฅํ•˜๊ฒŒ ํ•ด๋ด„

function burger(){
    removeAllPosts();
    getDataByCategory("BURGER");
  }

์ด๋ ‡๊ฒŒ ํ•ด๋ด„

๋‚˜๋จธ์ง€๋„ ๋˜‘๊ฐ™์ด ํ•จ

//๊ธ€ ๊ฒ€์ƒ‰ํ•˜๊ธฐ
    @GetMapping("/posts/search")
    public ApiResponse<List<BriefPostResponse>> searchPost(
        @AuthenticationPrincipal UserDetailsImpl userDetails,
        @Valid @RequestBody PostSearchRequest postSearchReq
    ) {
        return new ApiResponse<>(HttpStatus.OK.value(), "๊ฒ€์ƒ‰ ๊ฒฐ๊ณผ",
            postService.searchPost(postSearchReq, userDetails.getUser()));
    }
public record PostSearchRequest(
    @NotNull(message = "๊ฒ€์ƒ‰์–ด๋ฅผ ์ž…๋ ฅํ•˜์„ธ์š”.")
    String keyword
) {

}

์ €๊ฑฐ ๋ˆ„๋ฅด๋ฉด ์ƒˆ๋กœ ๊ฒฐ๊ณผ ๋ฐ›์•„์™€์„œ ํ™”๋ฉด์— ์ถœ๋ ฅํ• ๊ฑด๋ฐ ๊ทธ๋Ÿผ ๊ธฐ์กด ๊ฒฐ๊ณผ๋Š” ์‚ญ์ œํ•ด์•ผํ•˜์ง€ ์•Š๋‚˜ ์‹ถ์–ด์„œ removeํ•จ์ˆ˜ ์•Œ์•„๋ด„

๊ฒ€์ƒ‰ ์ž…๋ ฅ input๊ณผ ๋ฒ„ํŠผ์ด ๋‹ฌ๋ฆฐ ๋ถ€ํŠธ์ŠคํŠธ๋žฉ ์ฐพ์•„๋‹ค๊ฐ€ ๋งŒ๋“ฆ

<div class="input-group mb-3">
      <input aria-describedby="button-addon2" aria-label="keyword" class="form-control" id="keyword" placeholder="๊ฒ€์ƒ‰์–ด"
             type="text">
      <button class="btn btn-outline-secondary" onclick="search()" id="search" type="button">๊ฒ€์ƒ‰</button>
    </div>
function search(){
    var keyword = $('#keyword').val();

    removeAllPosts();
    getDataByKeyword(keyword);
  }

  function getDataByKeyword(keyword){
    var keyword = keyword;

    $.ajax({
      type: 'GET',
      url: `/api/v1/posts/search`,
      dataType: "json",
      contentType: 'application/json',
      data: JSON.stringify({
        keyword: keyword
      }),
      success: function (response) {
        console.log('Success:', response);

        drawAllPosts(response.data);

      },
      error: function (error) {
        console.error('Error:', error);
      }
    });
  }

์ผ๋‹จ ํ•ด๋ดค์Œ

์„ฑ๊ณตํ–ˆ๋Š”๋ฐ ์ €์žฅ๋œ ๊ธ€ ๋ฐ์ดํ„ฐ๊ฐ€ ํ•˜๋‚˜๋„ ์—†์–ด์„œ ํ™”๋ฉด์— ์ถœ๋ ฅ์€ ์•ˆ ๋จ

 

๐Ÿšฉ ๋ฌธ์ œ : ajax GET์„ ํ• ๋•Œ RequestBody๋กœ Object๋ฅผ ๋ณด๋‚ผ ์ˆ˜ ์—†์Œ

๊ฒ€์ƒ‰์„ ์‹œ๋„ํ•ด๋ดค๋”๋‹ˆ

์ด๊ฒŒ ๋˜ ๋œธ

java.lang.IllegalArgumentException: Invalid character found in the request target [/api/v1/posts/category?{%22category%22:%22BURGER%22} ]. The valid characters are defined in RFC 7230 and RFC 3986 ์ฃผ์†Œ ์•ˆ์— ์ € %22๊ฐ€ ๋Œ€์ฒด ๋ญ๋ž€๋ง์ž„

data: {
        keyword: keyword
      },

Resolved [org.springframework.http.converter.HttpMessageNotReadableException: Required request body is missing: public com.moayo.moayoeats.backend.global.dto.ApiResponse<java.util.List<com.moayo.moayoeats.backend.domain.post.dto.response.BriefPostResponse>> com.moayo.moayoeats.backend.domain.post.controller.PostController.searchPost(com.moayo.moayoeats.backend.global.security.UserDetailsImpl,com.moayo.moayoeats.backend.domain.post.dto.request.PostSearchRequest)]

๊ธ€ ํ•˜๋‚˜ ๋งŒ๋“ค์–ด๋ดค๋”๋‹ˆ ๊ทธ๊ฑด ์ž˜ ๋œธ

์นดํ…Œ๊ณ ๋ฆฌ ํ•œ์‹ ๋ˆŒ๋ €๋”๋‹ˆ ์ด๊ฑฐ ๋œธ

java.lang.IllegalArgumentException: Invalid character found in the request target [/api/v1/posts/category?{%22category%22:%22KOREAN%22} ]. The valid characters are defined in RFC 7230 and RFC 3986

 

๊ฒ€์ƒ‰๋ฒ„ํŠผ ๋ˆŒ๋Ÿฌ๋ดค๋”๋‹ˆ ๊ทธ๊ฑด ์ด๊ฑฐ ๋œธ

2024-01-19T20:43:50.924+09:00 WARN 29456 --- [nio-8080-exec-5] .w.s.m.s.DefaultHandlerExceptionResolver : Resolved [org.springframework.http.converter.HttpMessageNotReadableException: Required request body is missing: public com.moayo.moayoeats.backend.global.dto.ApiResponse<java.util.List<com.moayo.moayoeats.backend.domain.post.dto.response.BriefPostResponse>> com.moayo.moayoeats.backend.domain.post.controller.PostController.searchPost(com.moayo.moayoeats.backend.global.security.UserDetailsImpl,com.moayo.moayoeats.backend.domain.post.dto.request.PostSearchRequest)]

 

 

์Šคํƒ์˜ค๋ฒ„ํ”Œ๋กœ์šฐ์˜ ์–ด๋–ค ์‚ฌ๋žŒ์ด

Did you mean: URL2 = JSON.stringify(URL), and then URL2 = encodeURI(JSON.stringify(URL2))

์ด๊ฑฐ ํ•ด๋ณด๋ผ๊ณ  ํ•จ

function getDataByCategory(categoryEnum) {
    let category = categoryEnum;
    let URL = JSON.stringify({
          category: category
        })
    let categoryUrl= encodeURI(JSON.stringify(URL))

    $.ajax({
      type: 'GET',
      url: `/api/v1/posts/category?${categoryUrl}`,
      dataType: "json",
      contentType: 'application/json',
      data: {},
      /*
      JSON.stringify({
        category: category
      }),*/
      success: function (response) {
        console.log('Success:', response);

        drawAllPosts(response.data);

      },
      error: function (error) {
        console.error('Error:', error);
      }
    });
  }

์ด๊ฑฐ ํ•ด๋ด„

2024-01-19T20:54:15.791+09:00 WARN 14536 --- [nio-8080-exec-7] .w.s.m.s.DefaultHandlerExceptionResolver : Resolved [org.springframework.http.converter.HttpMessageNotReadableException: Required request body is missing: public com.moayo.moayoeats.backend.global.dto.ApiResponse<java.util.List<com.moayo.moayoeats.backend.domain.post.dto.response.BriefPostResponse>> com.moayo.moayoeats.backend.domain.post.controller.PostController.getPostsByCategory(com.moayo.moayoeats.backend.global.security.UserDetailsImpl,com.moayo.moayoeats.backend.domain.post.dto.request.PostCategoryRequest)]

์•ˆ ๋จ…

์•„์˜ˆ ๊ฐ์ฒด ์ทจ๊ธ‰์„ ์•ˆ ํ•ด์คŒ

https://stackoverflow.com/questions/46251131/invalid-character-found-in-the-request-target-in-spring-boot

์ด์‚ฌ๋žŒ์˜ ๋ฌธ์ œ ๋‚˜์™€ ๋™์ผํ•˜๋‹ค

According to https://tomcat.apache.org/tomcat-8.5-doc/config/systemprops.html, requestTargetAllow is deprecated. For me, the other solutions presented here did not work either. According to the Tomcat documentation I found a way to set the property relaxedQueryChars instead:

@Bean
public ConfigurableServletWebServerFactory webServerFactory() {
    TomcatServletWebServerFactory factory = new TomcatServletWebServerFactory();
    factory.addConnectorCustomizers(new TomcatConnectorCustomizer() {
        @Override
        public void customize(Connector connector) {
            connector.setProperty("relaxedQueryChars", "|{}[]");
        }
    });
    return factory;
}

18

For a Spring Boot application, just add to properties file:

server.tomcat.relaxed-query-chars=|,{,},[,]

There is also the following key: server.tomcat.relaxed-path-chars

@Configuration
public class WebServerConfig {

    @Bean
    public ConfigurableServletWebServerFactory webServerFactory() {
        TomcatServletWebServerFactory factory = new TomcatServletWebServerFactory();
        factory.addConnectorCustomizers(new TomcatConnectorCustomizer() {
            @Override
            public void customize(Connector connector) {
                connector.setProperty("relaxedQueryChars", "|{}[]");
            }
        });
        return factory;
    }
}

ํ•œ๋ฒˆ ์ด๋ ‡๊ฒŒ ํ•ด๋ด„

44.858+09:00 WARN 33020 --- [nio-8080-exec-7] .w.s.m.s.DefaultHandlerExceptionResolver : Resolved [org.springframework.http.converter.HttpMessageNotReadableException: Required request body is missing: public com.moayo.moayoeats.backend.global.dto.ApiResponse<java.util.List<com.moayo.moayoeats.backend.domain.post.dto.response.BriefPostResponse>> com.moayo.moayoeats.backend.domain.post.controller.PostController.getPostsByCategory(com.moayo.moayoeats.backend.global.security.UserDetailsImpl,com.moayo.moayoeats.backend.domain.post.dto.request.PostCategoryRequest)]

024-01-19T21:11:18.234+09:00 WARN 33020 --- [nio-8080-exec-8] .w.s.m.s.DefaultHandlerExceptionResolver : Resolved [org.springframework.http.converter.HttpMessageNotReadableException: Required request body is missing: public com.moayo.moayoeats.backend.global.dto.ApiResponse<java.util.List<com.moayo.moayoeats.backend.domain.post.dto.response.BriefPostResponse>> com.moayo.moayoeats.backend.domain.post.controller.PostController.searchPost(com.moayo.moayoeats.backend.global.security.UserDetailsImpl,com.moayo.moayoeats.backend.domain.post.dto.request.PostSearchRequest)]

Required request body is missing:

ํ•˜ ๋ชจ๋ฅด๊ฒ ๋‹ค

์•„๊นŒ๋„ ๊ทธ๋žฌ๋Š”๋ฐ POST๋Š” jsonํ˜•์‹์œผ๋กœ ์ž˜ ๋˜๋Š”๋ฐ get์€ ์•ˆ ๋ผ์„œ

Q. ์™œ ์•ˆ๋˜์ง€? POST๋Š” ์™œ ๋˜๋Š”๊ฑฐ์ง€?

๊ทธ๋ƒฅ requestParam์œผ๋กœ ์ˆ˜์ •ํ•ด์•ผํ•  ๊ฑฐ ๊ฐ™์Œ

https://www.baeldung.com/spring-request-param

 

โ›ณ ํ•ด๊ฒฐ : Get method RequestBody์—์„œ RequestParam ๋ฐฉ์‹์œผ๋กœ ๋ชจ๋‘ ๋ณ€๊ฒฝํ•จ

@Override
    public List<BriefPostResponse> searchPost(String keyword, User user) {
        //get all posts filtered by search keyword
        List<Post> posts = postRepository.findPostByStoreContaining(keyword)
            .orElse(null);
        //List<Post> -> List<BriefPostResponse>
        return postsToBriefResponses(posts);
    }

String keyword๋กœ ๋‹ค ๋ณ€๊ฒฝํ•จ

//๊ธ€ ๊ฒ€์ƒ‰ํ•˜๊ธฐ
    @GetMapping("/posts/search")
    public ApiResponse<List<BriefPostResponse>> searchPost(
        @AuthenticationPrincipal UserDetailsImpl userDetails,
        @RequestParam String keyword
    ) {
        return new ApiResponse<>(HttpStatus.OK.value(), "๊ฒ€์ƒ‰ ๊ฒฐ๊ณผ",
            postService.searchPost(keyword, userDetails.getUser()));
    }
@Override
    public List<BriefPostResponse> searchPost(String keyword, User user) {
        //get all posts filtered by search keyword
        List<Post> posts = postRepository.findPostByStoreContaining(keyword)
            .orElse(null);
        //List<Post> -> List<BriefPostResponse>
        return postsToBriefResponses(posts);
    }
$.ajax({
      type: 'GET',
      url: `/api/v1/posts/search?keyword=${keyword}`,
      dataType: "json",
      contentType: 'application/json',
      data: {},
      success: function (response) {
        console.log('Success:', response);

        drawAllPosts(response.data);

      },
      error: function (error) {
        console.error('Error:', error);
      }
    });

์ด๊ฑธ๋กœ ํ•ด๋ณด๊ธฐ

์ž˜ ๋จ

์นดํ…Œ๊ณ ๋ฆฌ๋„ ๋ฐ”๊ฟ”๋ด„

//๊ธ€ ์นดํ…Œ๊ณ ๋ฆฌ๋ณ„ ์กฐํšŒ
    @GetMapping("/posts/category")
    public ApiResponse<List<BriefPostResponse>> getPostsByCategory(
        @AuthenticationPrincipal UserDetailsImpl userDetails,
        @RequestParam CategoryEnum category
    ) {
        return new ApiResponse<>(HttpStatus.OK.value(), "๊ธ€ ์นดํ…Œ๊ณ ๋ฆฌ๋ณ„ ์กฐํšŒ์— ์„ฑ๊ณตํ–ˆ์Šต๋‹ˆ๋‹ค.",
            postService.getPostsByCategory(category, userDetails.getUser()));
    }
@Override
    public List<BriefPostResponse> getPostsByCategory(CategoryEnum category,
        User user) {
        List<Post> posts;
        if (category.equals(CategoryEnum.ALL.toString())) {
            posts = findAll();
        } else {
            posts = postRepository.findAllByCategoryEquals(category.toString()).orElse(null);
        }
        return postsToBriefResponses(posts);
    }

Resolved [org.springframework.web.bind.MissingServletRequestParameterException: Required request parameter 'category' for method parameter type CategoryEnum is not present]

์•„ html๋ฐ”๊พธ๋Š”๊ฑฐ ๊นŒ๋จน์Œ

function getDataByCategory(categoryEnum) {
    let category = categoryEnum;

    $.ajax({
      type: 'GET',
      url: `/api/v1/posts/category?category=${category}`,
      dataType: "json",
      contentType: 'application/json',
      data:{},
      success: function (response) {
        console.log('Success:', response);

        drawAllPosts(response.data);

      },
      error: function (error) {
        console.error('Error:', error);
      }
    });
  }

org.hibernate.query.QueryArgumentException: Argument [BURGER] of type [java.lang.String] did not match parameter type [com.moayo.moayoeats.backend.domain.post.entity.CategoryEnum

function getDataByCategory(categoryEnum) {
    let category = categoryEnum;

    $.ajax({
      type: 'GET',
      url: `/api/v1/posts/category`,
      dataType: "json",
      contentType: 'application/json',
      data:{category:category},
      success: function (response) {
        console.log('Success:', response);

        drawAllPosts(response.data);

      },
      error: function (error) {
        console.error('Error:', error);
      }
    });
  }

์ด๋ ‡๊ฒŒ ํ•ด๋ด„

org.hibernate.query.QueryArgumentException: Argument [CHICKEN] of type [java.lang.String] did not match parameter type [com.moayo.moayoeats.backend.domain.post.entity.CategoryEnum (n/a)] at org.hibernate.query.spi.QueryParameterBindingValidator.validate(QueryParameterBindingValidator.java:85) ~[hibernate-core-6.4.1.Final.jar:6.4.1.Final] at org.hibernate.query.spi.QueryParameterBindingValidator.validate(QueryParameterBindingValidator.java:32) ~[hibernate-core-6.4.1.Final.jar:6.4.1.Final] at org.hibernate.query.internal.QueryParameterBindingImpl.validate(QueryParameterBindingImpl.java:362) ~[hibernate-core-6.4.1.Final.jar:6.4.1.Final] at org.hibernate.query.internal.QueryParameterBindingImpl.setBindValue(QueryParameterBindingImpl.java:137) ~[hibernate-core-6.4.1.Final.jar:6.4.1.Final] at org.hibernate.query.spi.AbstractCommonQueryContract.setParameter(AbstractCommonQueryContract.java:1047) ~[hibernate-core-6.4.1.Final.jar:6.4.1.Final] at org.hibernate.query.spi.AbstractSelectionQuery.setParameter(AbstractSelectionQuery.java:966) ~[hibernate-core-6.4.1.Final.jar:6.4.1.Final] at org.hibernate.query.sqm.internal.QuerySqmImpl.setParameter(QuerySqmImpl.java:1324) ~[hibernate-core-6.4.1.Final.jar:6.4.1.Final] at org.hibernate.query.sqm.internal.QuerySqmImpl.setParameter(QuerySqmImpl.java:140) ~[hibernate-core-6.4.1.Final.jar:6.4.1.Final]

์•ˆ๋˜๋‚˜๋ด„

function getDataByCategory(categoryEnum) {
    let category = categoryEnum;

    $.ajax({
      type: 'GET',
      url: `/api/v1/posts/category?category=${category}`,
      dataType: "json",
      contentType: 'application/json',
      data:{},
      success: function (response) {
        console.log('Success:', response);

        drawAllPosts(response.data);

      },
      error: function (error) {
        console.error('Error:', error);
      }
    });
  }

ใ…ˆใ…ˆใ…‡ใ…ˆใ…‡ใ…ˆใ… ใ…ˆใ…‡

//๊ธ€ ์นดํ…Œ๊ณ ๋ฆฌ๋ณ„ ์กฐํšŒ
    @GetMapping("/posts/category")
    public ApiResponse<List<BriefPostResponse>> getPostsByCategory(
        @AuthenticationPrincipal UserDetailsImpl userDetails,
        @RequestParam @Category String category
    ) {
        return new ApiResponse<>(HttpStatus.OK.value(), "๊ธ€ ์นดํ…Œ๊ณ ๋ฆฌ๋ณ„ ์กฐํšŒ์— ์„ฑ๊ณตํ–ˆ์Šต๋‹ˆ๋‹ค.",
            postService.getPostsByCategory(category, userDetails.getUser()));
    }

์ผ๋‹จ ์ •ํ•ด์ง„๊ฑฐ ํ•ด๋ณด๊ณ  html์—์„œ ์ด์ƒํ•œ๊ฒƒ๋„ ๋ณด๋‚ด๋ด์•ผ์ง€

org.hibernate.query.QueryArgumentException: Argument [ASIAN] of type [java.lang.String] did not match parameter type [com.moayo.moayoeats.backend.domain.post.entity.CategoryEnum (n/a)] at org.hibernate.query.spi.QueryParameterBindingValidator.validate(QueryParameterBindingValidator.java:85) ~[hibernate-core-6.4.1.Final.jar:6.4.1.Final]

at com.moayo.moayoeats.backend.domain.post.service.impl.PostServiceImpl.getPostsByCategory(PostServiceImpl.java:138) ~[main/:na] at com.moayo.moayoeats.backend.domain.post.controller.PostController.getPostsByCategory(PostController.java:78) ~[main/:na]

Optional<List<Post>> findAllByCategoryEquals(String category);

String์ธ๋ฐ ๋ญ”์†Œ๋ฆฌํ•จ

@Override
    public List<BriefPostResponse> getPostsByCategory(String category,
        User user) {
        List<Post> posts;
        if (category.equals(CategoryEnum.ALL.toString())) {
            posts = findAll();
        } else {
            posts = postRepository.findAllByCategoryEquals(category).orElse(null);
        }
        return postsToBriefResponses(posts);
    }

์ด๊ฒƒ๋„ String์ด๊ณ 

//๊ธ€ ์นดํ…Œ๊ณ ๋ฆฌ๋ณ„ ์กฐํšŒ
    @GetMapping("/posts/category")
    public ApiResponse<List<BriefPostResponse>> getPostsByCategory(
        @AuthenticationPrincipal UserDetailsImpl userDetails,
        @RequestParam @Category String category
    ) {
        return new ApiResponse<>(HttpStatus.OK.value(), "๊ธ€ ์นดํ…Œ๊ณ ๋ฆฌ๋ณ„ ์กฐํšŒ์— ์„ฑ๊ณตํ–ˆ์Šต๋‹ˆ๋‹ค.",
            postService.getPostsByCategory(category, userDetails.getUser()));
    }

๋‹ค String์ธ๋ฐ?

๊ทผ๋ฐ Entity์— ์ €์žฅ๋œ ํƒ€์ž…์€ CategoryEnum์ด๋ผ ๊ทธ ๋ถ€๋ถ„ ๋ฐ”๊ฟ”๋ด„

Optional<List<Post>> findAllByCategoryEquals(CategoryEnum category);
@Override
    public List<BriefPostResponse> getPostsByCategory(String category,
        User user) {
        List<Post> posts;
        CategoryEnum categoryEnum = CategoryEnum.valueOf(category);
        if (category.equals(CategoryEnum.ALL.toString())) {
            posts = findAll();
        } else {
            posts = postRepository.findAllByCategoryEquals(categoryEnum).orElse(null);
        }
        return postsToBriefResponses(posts);
    }

์ž˜ ๋œ๋‹ค

 

์ด์ œ @Category ๊ฐ€ ๋˜๋Š”์ง€ ๋ณด๊ธฐ ์œ„ํ•ด html์„ ๋ฐ”๊ฟ”์„œ ํ…Œ์ŠคํŠธํ•ด๋ด„

function getDataByCategory(categoryEnum) {
    let category = categoryEnum;

    $.ajax({
      type: 'GET',
      url: `/api/v1/posts/category?category=${category}`,
      dataType: "json",
      contentType: 'application/json',
      data:{},
      success: function (response) {
        console.log('Success:', response);

        drawAllPosts(response.data);

      },
      error: function (error) {
        console.error('Error:', error);
      }
    });
  }

function getDataByCategory(categoryEnum) {
    let category = categoryEnum;

    $.ajax({
      type: 'GET',
      url: `/api/v1/posts/category?category=test`,
      dataType: "json",
      contentType: 'application/json',
      data:{},
      success: function (response) {
        console.log('Success:', response);

        drawAllPosts(response.data);

      },
      error: function (error) {
        console.error('Error:', error);
      }
    });
  }

์นดํ…Œ๊ณ ๋ฆฌ ๋ˆ„๋ฅผ๋•Œ๋งˆ๋‹ค ์—๋Ÿฌ๊ฐ€ ๋œธ!

ํฌ์ŠคํŠธ๋งจ์—์„œ๋„ ํ•ด๋ด„

localhost:8080/api/v1/posts/category?category=test

์ด๋ ‡๊ฒŒ ๋ณด๋‚ด๋ฉด

403Forbidden

์ด๋ ‡๊ฒŒ ๋œจ๊ณ 

localhost:8080/api/v1/posts/category?category=ALL

์ด๋ ‡๊ฒŒ ๋ณด๋‚ด๋ฉด ์ž˜ ๋œธ!

{
    "status": 200,
    "message": "๊ธ€ ์นดํ…Œ๊ณ ๋ฆฌ๋ณ„ ์กฐํšŒ์— ์„ฑ๊ณตํ–ˆ์Šต๋‹ˆ๋‹ค.",
    "data": [
        {
            "id": 34,
            "author": "๊ฐ€๋‚˜๋‹ค๋ผ",
            "address": "37.5675458,126.9714466",
            "store": "1",
            "minPrice": 1,
            "sumPrice": 0,
            "deadline": "2024-01-19T23:42:31"
        }
    ]
}

์ด๊ฑด ๋ฌด์Šจ ์—๋Ÿฌ๋ฅผ ๋˜์ง€๋Š”์ง€ ๋œจ์ง€๋„ ์•Š์•„์„œ ์–ด๋–ป๊ฒŒ Exception ์ฒ˜๋ฆฌํ•ด์•ผํ• ์ง€ ๋ชจ๋ฅด๊ฒ ๋‹ค!

→ ๐Ÿš€issue: ๋‚˜์ค‘์— ์ถ”๊ฐ€๋กœ ํ•ด๋ณด๊ธฐ!!!

 

 

 

'Developing > ๊ฐœ๋ฐœ์ผ์ง€' ์นดํ…Œ๊ณ ๋ฆฌ์˜ ๋‹ค๋ฅธ ๊ธ€

2024-01-18, Today I Learned  (0) 2024.01.18
2024-01-17, Today I Learned  (0) 2024.01.17
2024-01-16, Today I Learned  (0) 2024.01.16
2024-01-15, Today I Learned  (0) 2024.01.15
2024-01-14, Today I Learned  (0) 2024.01.15