멋사 Backend Plus 28일차 🦁

μ‹ μž¬μ›Β·2023λ…„ 12μ›” 2일

μ˜€λŠ˜λ„ μ˜€μ „κ³Ό μ˜€ν›„μ‹œκ°„ λ™μ•ˆ νŒ€ ν”„λ‘œμ νŠΈλ₯Ό μ§„ν–‰ν•˜μ˜€κ³ , 쀑간에 1μ‹œκ°„ 정도 쀑간 λ°œν‘œ 점검이 μžˆμ—ˆλ‹€.

μ˜€μ „

  • μ˜€μ „μ— λ§ˆμ£Όν–ˆλ˜ JPA μ—°κ΄€ 관계에 λŒ€ν•œ μ—λŸ¬μ— λŒ€ν•΄ 정리 ν•˜κ² μŠ΅λ‹ˆλ‹€.

transientPropertyValueException: object references an unsaved transient instance - save the transient instance before flushing

μ΄λŸ¬ν•œ μ—λŸ¬κ°€ λ°œμƒν•œ μ΄μœ λŠ” μ—°κ΄€ κ΄€κ³„μ˜ 주인의 데이터λ₯Ό λ„£μ§€μ•Šκ³  μžμ‹ ν…Œμ΄λΈ”μ— 데이터λ₯Ό λ„£μœΌλ €κ³  ν•˜λ©΄ μ—λŸ¬κ°€ λ°œμƒν•˜κ²Œ λ©λ‹ˆλ‹€.
(연관관계 λ©”μ†Œλ“œκ°€ μžˆλŠ” 경우)

@JoinColumn ν‚€μ›Œλ“œλŠ” λ‹€λ₯Έ 컬럼과 쑰인 ν•œλ‹€λŠ” 뜻 이며, FK 즉 μ™Έλž˜ν‚€λ₯Ό κ°€μ§€λŠ” μͺ½μ΄ 연관관계 주인이 되게 λ©λ‹ˆλ‹€.

@ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "product_id")
    private Product product;

mappedBy ν‚€μ›Œλ“œλŠ” μžμ‹ ν…Œμ΄λΈ”κ³Ό 같은 의미둜 생각 ν•˜λ©΄ 될 것 κ°™μŠ΅λ‹ˆλ‹€.

@OneToMany(
            mappedBy = "product",
            orphanRemoval = true)
    @Builder.Default
    private List<Image> productImages = new ArrayList<>();

μ΄λŸ¬ν•œ Entity 클래슀 κ΄€κ³„μ—μ„œ

public void create(CreateRequest createRequest, MultipartFile images) 
												throws IOException {
        if (isImageExists(images)) {
	// Productλ₯Ό λ¨Όμ € μ €μž₯ ν•˜μ§€ μ•ŠμœΌλ©΄ μœ„μ˜ μ—λŸ¬κ°€ λ°œμƒν•œλ‹€.
	// μ΄μœ λ‘œλŠ” Productλ₯Ό μ €μž₯ν•˜μ§€ μ•ŠμœΌλ©΄, JoinColumn의 product_idλ₯Ό μ•Œμˆ˜κ°€ μ—†λ‹€.
            Product product = initProduct(createRequest);
            
            imageService.uploadImage(product, images);
        }
    }

ν•΄κ²° λ°©λ²•μœΌλ‘œλŠ” @ManyToOne, @OneToOne, @OneToMany의 연관관계 μ–΄λ…Έν…Œμ΄μ…˜μ— cascade ν‚€μ›Œλ“œλ₯Ό μž‘μ„±ν•˜μ—¬ μ˜μ†μ„±μ„ 전이 ν• μˆ˜ μžˆλ‹€κ³  ν•©λ‹ˆλ‹€.

➑ 아직 잘 λͺ¨λ₯΄λŠ” μƒνƒœμ—μ„œ μ •λ¦¬ν•˜λŠ” 것 보닀 ν”„λ‘œμ νŠΈκ°€ μ–ΌμΆ” λλ‚˜κ°€λ©΄ 적용 ν•΄λ³΄λ©΄μ„œ 정리 해놔야겠닀.

λ²ˆμ™Έλ‘œ ν…Œμ΄λΈ”μ„ DROP ν•΄μ•Ό ν•  κ²½μš°κ°€ μžˆμ—ˆλŠ”λ° μ—λŸ¬λ₯Ό λ§ˆμ£Όν–ˆμŠ΅λ‹ˆλ‹€.

(μ‹€μ œλ‘œ νšŒμ‚¬μ—μ„œλŠ” ν…Œμ΄λΈ”μ„ DROP ν•  일이 κ±°~의 μ—†λ‹€κ³  ν•œλ‹€)

[23000][1451] (conn=3) Cannot delete or update a parent row: a foreign key constraint fails.

μ΄λŸ¬ν•œ μ—λŸ¬λ₯Ό 마주 ν•˜κ²Œ λ˜μ—ˆλŠ”λ°, μ΄μœ λ‘œλŠ” ν˜„μž¬ μ‚­μ œν•˜λ €λŠ” ν…Œμ΄λΈ”μ„ λ˜λŠ” 행이 λ‹€λ₯Έ ν…Œμ΄λΈ”μ—μ„œ μ°Έμ‘° ν•˜κ³  있기 λ•Œλ¬Έμž…λ‹ˆλ‹€.

➑ ν•΄κ²° 방법 μœΌλ‘œλŠ” μ°Έμ‘°ν•˜κ³  μžˆλŠ” ν…Œμ΄λΈ”μ˜ μ°Έμ‘°λ₯Ό ν•΄μ œ (μ‚­μ œ) ν•˜λŠ” 것 μž…λ‹ˆλ‹€. (μ°Έμ‘°ν•˜λŠ” ν…Œμ΄λΈ”μ„ λ¨Όμ € DROP)

REFERENCE : https://bcp0109.tistory.com/344

μ˜€ν›„

νŽ˜μ΄μ§• 처리

  • μƒν’ˆ μ‘°νšŒμ— λŒ€ν•œ νŽ˜μ΄μ§• 처리 κΈ°λŠ₯ κ΅¬ν˜„μ„ ν•˜κ³  있던 도쀑에 νŒ€μ› ν•œλΆ„λ„ νŽ˜μ΄μ§• 처리λ₯Ό μœ„ν•΄ Response (응닡) DTO 클래슀λ₯Ό κ³΅ν†΅μœΌλ‘œ μ‚¬μš©ν•˜λ©΄ 쒋을것 κ°™λ‹€λŠ” μ˜κ²¬μ„ μ œμ‹œν•˜μ…¨λ‹€. (μ œλ„€λ¦­ μ‚¬μš©)
    μ œμ‹œν•˜μ‹  μ½”λ“œλŠ” μ•„λž˜μ˜ μ½”λ“œλ‹€.
@Getter
@Setter
public class PageResponse<T> {
    private List<T> content;
    private int pageNumber;
    private int pageSize;
    private int totalPages;
    private long totalElements;

    public PageResponse(Page<T> page) {
        this.content = page.getContent();
        this.pageNumber = page.getNumber() + 1;
        this.pageSize = page.getSize();
        this.totalPages = page.getTotalPages();
        this.totalElements = page.getTotalElements();
    }

}

μ•„λž˜μ˜ μ½”λ“œλŠ” νŽ˜μ΄μ§• 쑰회λ₯Ό μœ„ν•œ 컨트둀러 λ‹¨μž…λ‹ˆλ‹€.
defaultValue 쑰건을 μž‘μ„±ν•¨μœΌλ‘œμ¨ 0λΆ€ν„° μ‹œμž‘ν•˜λŠ” νŽ˜μ΄μ§• λ„˜λ²„κ°€ 1λΆ€ν„° μ‹œμž‘ν• μˆ˜ 있게 λ©λ‹ˆλ‹€.

 @GetMapping("/all")
    public RsData readPageByProduct(@RequestParam(name = "pageNumber", 
    		defaultValue = PAGE_START_NUMBER) Integer page) {
        
        Pageable pageRequest = PageRequest.of(page - 1, 5);
        Page<ViewAllResponse> pageByProduct =
        		productService.readPageByProduct(pageRequest);
                
                // νƒ€μž…μ„ μ œλ„€λ¦­μœΌλ‘œ λ°›κΈ° λ•Œλ¬Έμ— λ‹€μ–‘ν•œ 객체둜 λ„˜κ²¨μ€„ 수 μžˆλ‹€.
        return RsData.successOf(new PageResponse<>(pageByProduct));
    }

ν•œμ‹œκ°„ 정도 4개의 νŒ€ 쀑간 λ°œν‘œκ°€ μžˆμ—ˆλ‹€.

➑ 우리 νŒ€μ„ μ œμ™Έν•˜κ³  λ‹€λ₯Έ νŒ€λ“€μ€ PDF ν˜Ήμ€ PPT μ •λ„λ§ŒμœΌλ‘œ λ°œν‘œλ₯Ό μ§„ν–‰ ν•˜μ˜€λŠ”λ°, μš°λ¦¬νŒ€μ€ λ…Έμ…˜μ— μ •λ¦¬ν•œ API μ—”λ“œ 포인트, ERDλ“± κ³Ό μ›Ή νŽ˜μ΄μ§€λ₯Ό μ–΄λŠμ •λ„ κ΅¬ν˜„ ν•΄μ„œ μ›Ή νŽ˜μ΄μ§€ 캑쳐둜 Flow λ₯Ό μ„€λͺ… ν•˜μ˜€λ‹€.

마무리

ngrinder Tool (도ꡬ)λ₯Ό μ‚¬μš©ν•˜μ—¬ μ„±λŠ₯ ν…ŒμŠ€νŠΈ (λΆ€ν•˜ ν…ŒμŠ€νŠΈ) λ₯Ό μ§„ν–‰ν•˜κ³  μ‹Άκ³ , μ•„λ§ˆ μ§„ν–‰ν•  μ˜ˆμ •μž…λ‹ˆλ‹€.

(포슀트 λ§¨μ—μ„œλ„ μ„±λŠ₯ ν…ŒμŠ€νŠΈλ₯Ό μ§€μ›ν•˜μ§€λ§Œ, ngrinder λŠ” λŒ€κ·œλͺ¨ λΆ„μ‚°λœ(?) ν™˜κ²½μ— νŠΉν™” λ˜μ–΄μžˆλ‹€κ³  ν•©λ‹ˆλ‹€.)

➑ ν¬μŠ€νŠΈλ§¨μœΌλ‘œλŠ” API μ„±λŠ₯ ν…ŒμŠ€νŠΈλ₯Ό ν•΄λ³΄μ•˜μŠ΅λ‹ˆλ‹€. ngrinder Tool을 μ‚¬μš©ν•˜μ—¬ μ„±λŠ₯ (λΆ€ν•˜) ν…ŒμŠ€νŠΈλ₯Ό μ§„ν–‰ν• λ•Œ 차이점을 닀뀄 λ³΄κ² μŠ΅λ‹ˆλ‹€.

0개의 λŒ“κΈ€