Error Logs๐Ÿพ

์ž‘์—…์ค‘ ์—๋Ÿฌ ์ •๋ฆฌ

hae02y 2023. 12. 7. 17:59
๋ฐ˜์‘ํ˜•
2023-10-08 05:21:35.706 ERROR 6064 --- [nio-8080-exec-2] o.a.c.c.C.[.[.[/].[dispatcherServlet]    : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is org.springframework.dao.InvalidDataAccessResourceUsageException: could not execute statement; SQL [n/a]; nested exception is org.hibernate.exception.SQLGrammarException: could not execute statement] with root cause

org.postgresql.util.PSQLException: ์˜ค๋ฅ˜: r.recruitid ์นผ๋Ÿผ ์—†์Œ
  Hint: ์•„๋งˆ "r.recruit_id" ์นผ๋Ÿผ์„ ์ฐธ์กฐํ•˜๋Š” ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค.
  Position: 91

nativeQuery = false ํ•˜๋‹ˆ๊นŒ ํ•ด๊ฒฐ

@Transactional ํ•˜๋‹ˆ๊นŒ ํ•ด๊ฒฐ


@Transactional  
@Modifying    
@Query(value = "update Recruit r set r.position = :position, r.bonus = :bonus, r.detail = :detail, r.technique = :technique where r.recruitId = :id", nativeQuery = false)  
    public int changeAll(@Param("position") String position,  
                          @Param("bonus") Long bonus,  
                          @Param("detail") String detail,  
                          @Param("technique") String technique,  
                          @Param("id") Long id);  
}
@Transactional  
public void patchRecruit(Recruit recruit) {  
    Recruit findedRecruit = recruitRepository.findById(recruit.getRecruitId()).orElseThrow();  

    recruitRepository.changeAll(recruit.getPosition(),recruit.getBonus(), recruit.getDetail(), recruit.getTechnique(),recruit.getRecruitId());  
}

๊ธฐ๋ณธํ‚ค ๋งคํ•‘์— ๋Œ€ํ•œ ์ดํ•ด

https://velog.io/@tritny6516/JPA-%EA%B8%B0%EB%B3%B8%ED%82%A4Primary-Key-%EB%A7%A4%ED%95%91-Id-GeneratedValue

๋งต์ŠคํŠธ๋Ÿญ์Šค ์‚ฌ์šฉ์ค‘ ์—๋Ÿฌ

๋งต์ŠคํŠธ๋ŸญํŠธ ์‚ฌ์šฉ์ค‘์— ๊ณ„์† ์—๋Ÿฌ๊ฐ€ ๋ฐœ์ƒํ•˜์˜€๋‹ค.

@Builder  
public class RecruitResponseDto {  

    private Long recruitId;  

    private String companyName;  

    private String nation;  

    private String region;  

    private String position;  

    private Long bonus;  

    private String technique;  
}
default List<RecruitResponseDto> recruitListToRecruitResponseDtos(List<Recruit> recruitList){  
    List<RecruitResponseDto> recruitResponseDtos = new ArrayList<>();  

    for(Recruit recruit : recruitList){  

        Company company = recruit.getCompany();  

        RecruitResponseDto recruitResponseDto = RecruitResponseDto.builder()  
                .recruitId(recruit.getRecruitId())  
                .region(company.getRegion())  
                .bonus(recruit.getBonus())  
                .nation(company.getNation())  
                .companyName(company.getName())  
                .position(recruit.getPosition())  
                .technique(recruit.getTechnique())  
                .build();  

        recruitResponseDtos.add(recruitResponseDto);  
    }  

    return recruitResponseDtos;  
}

์ด๋ ‡๊ฒŒ ๋Œ๋ฆฌ๋‹ˆ๊นŒ ๋ฐœ์ƒํ•˜๋Š” ์—๋Ÿฌ๋Š” ์—„์ฒญ ๋งŽ์•˜๋Š”๋ฐ
@Getter๋ฅผ ์ถ”๊ฐ€ํ•ด์ฃผ๋‹ˆ๊นŒ ์ •์ƒ๋™์ž‘ํ•œ๋‹ค.

์ฟผ๋ฆฌ

    @Query("SELECT r FROM Recruit r WHERE " +  
            "r.position LIKE %:search% OR " +  
            "CAST(r.bonus AS string) LIKE %:search% OR " +  
            "r.detail LIKE %:search% OR " +  
            "r.technique LIKE %:search% OR " +  
            "r.company.name LIKE %:search% OR " +  
            "r.company.nation LIKE %:search% OR " +  
            "r.company.region LIKE %:search% ")  
    List<Recruit> findRecruitsBySearchString(@Param("search") String search);  
}

๋ชจ๋“ ๊ฑธ ์กฐํšŒํ•˜๋Š” ์ฟผ๋ฆฌ๋ฅผ ์ž‘์„ฑํ•˜๋ ค๋ฉด ์ด๋Ÿฐ์‹์œผ๋กœ ํ•ด์•ผํ•œ๋‹ค. queryDSL๊ฐ™์€ ๊ธฐ์ˆ  ์ ์šฉ์—†์ด ๊ทธ๋ƒฅ ๋ƒ…๋‹ค ๋•Œ๋ ค๋ฐ•์€๊ฑฐ๋‹ค. ์ด๊ฑฐ ๊ทผ๋ฐ ๋ฌธ์ œ๊ฐ€ ์žˆ๋‹ค. ๋ญ๋ƒ๋ฉด

    {

        "recruitId": 14,

        "companyName": "์›ํ‹ฐ๋“œ๋žฉ",

        "nation": "ํ•œ๊ตญ",

        "region": "์„œ์šธ",

        "position": "๋ฐฑ์—”๋“œ ์ฃผ๋‹ˆ์–ด ๊ฐœ๋ฐœ์ž",

        "bonus": 1000000,

        "technique": "Python"

    },

    {

        "recruitId": 15,

        "companyName": "๋„ค์ด๋ฒ„",

        "nation": "ํ•œ๊ตญ",

        "region": "ํŒ๊ต",

        "position": "๋ฐฑ์—”๋“œ ์ฃผ๋‹ˆ์–ด ๊ฐœ๋ฐœ์ž",

        "bonus": 1000000,

        "technique": "Python"

    },

    {

        "recruitId": 16,

        "companyName": "์›ํ‹ฐ๋“œ์ฝ”๋ฆฌ์•„",

        "nation": "ํ•œ๊ตญ",

        "region": "๋ถ€์‚ฐ",

        "position": "๋ฐฑ์—”๋“œ ์ฃผ๋‹ˆ์–ด ๊ฐœ๋ฐœ์ž",

        "bonus": 1000000,

        "technique": "Python"

    },

    {

        "recruitId": 17,

        "companyName": "์นด์นด์˜ค",

        "nation": "ํ•œ๊ตญ",

        "region": "ํŒ๊ต",

        "position": "๋ฐฑ์—”๋“œ ์ฃผ๋‹ˆ์–ด ๊ฐœ๋ฐœ์ž",

        "bonus": 1500000,

        "technique": "Python"

    }

]

๋ถ„๋ช… ์›ํ‹ฐ๋“œ๋ฅผ ๊ฒ€์ƒ‰์–ด๋กœ ๋„ฃ์—ˆ๋Š”๋ฐ ์นด์นด์˜ค๊ฐ€ ๋‚˜์™€๋ฒ„๋ฆฌ๋„ค..? ๊ทผ๋ฐ ์ด์œ ๋ฅผ ์ฐพ์•˜๋‹ค...ใ…‹ใ…‹ใ…‹
"r.detail LIKE %:search% OR " +
์ด๋ถ€๋ถ„์ด ๋ฌธ์ œ์˜€๋‹ค. detail์€ response๋กœ ํ‘œ์‹œ๋˜์ง„์•Š์ง€๋งŒ DB๋ฅผ ํ™•์ธํ•ด๋ณด๋‹ˆ
์›ํ‹ฐ๋“œ๋žฉ์—์„œ ๋ฐฑ์—”๋“œ ์ฃผ๋‹ˆ์–ด ๊ฐœ๋ฐœ์ž๋ฅผ ์ฑ„์šฉํ•ฉ๋‹ˆ๋‹ค. ์ž๊ฒฉ์š”๊ฑด์€.. ์š”๋ ‡๊ฒŒ ์จ์ ธ์žˆ๋˜๊ฒƒ..! ์ง€์›Œ์ฃผ๋‹ˆ๊นŒ ์ •์ƒ๋™์ž‘ํ•œ๋‹ค.

JPQL์—์„œ Long > String ๋ฐ”๊พธ๊ธฐ

"CAST(r.bonus AS string) LIKE %:search% OR "

์ด๋Ÿฐ์‹์œผ๋กœ ์‚ฌ์šฉํ•˜๋ฉด ๋œ๋‹ค!

detail ๊ตฌํ˜„์—์„œ

๋ฌธ์ œ์ ์ด ์žˆ๋Š”๋ฐ ์ง€๊ธˆ ํ‘œ์ถœ๋˜๋Š”๊ฒŒ ํ˜„์žฌ ์ž์„ธํžˆ๋ณด๊ธฐ๋ฅผ ๋ˆŒ๋ฅธ ๊ฒƒ๊นŒ์ง€ ํšŒ์‚ฌ๊ฐ€ ์˜ฌ๋ฆฐ ๋‹ค๋ฅธ ์ฑ„์šฉ๊ณต๊ณ ์— ํ‘œ์ถœ๋œ๋‹ค ์ด๋ถ€๋ถ„ ๋ฐ”๊ฟ”์ค˜์•ผํ•œ๋‹ค.

๋ฐ˜์‘ํ˜•