AI 해커톤간의 트러블 슈팅

Kevin·2024년 2월 17일
0

Trouble Shooting

목록 보기
1/7
post-thumbnail
package com.example.demo;

import com.example.demo.domain.Customer;
import com.example.demo.domain.Product;
import com.example.demo.repository.CustomerRepository;
import com.example.demo.repository.ProductRepository;
import lombok.RequiredArgsConstructor;
import org.springframework.boot.context.event.ApplicationReadyEvent;
import org.springframework.context.event.EventListener;
import org.springframework.stereotype.Component;

import javax.persistence.EntityManager;
import javax.transaction.Transactional;
import java.util.ArrayList;
import java.util.List;

@Component
@RequiredArgsConstructor
public class DataInit {

    private final EntityManager em;

    private final CustomerRepository customerRepository;

    private final ProductRepository productRepository;

    @Transactional
    @EventListener(ApplicationReadyEvent.class)
    public void initData() {

        // Product 생성
        Product product11 = new Product("아메리카노", 3000L);
        Product product22 = new Product("카페라떼", 3500L);
        Product product33 = new Product("스위트 아메리카노", 3300L);
        Product product44 = new Product("초콜릿", 4000L);

        List<Product> productList = new ArrayList<>();
        productList.add(product11);
        productList.add(product22);
        productList.add(product33);
        productList.add(product44);

        productRepository.saveAll(productList);

        List<Product> products = productRepository.findAll();
        Product product1 = products.get(0);
        Product product2 = products.get(1);
        Product product3 = products.get(2);
        Product product4 = products.get(3);

         /*
             양방향 관계에서는 반드시 주인에서 값을 변경해야 한다.
          */

        // Customer 생성
        // 10대
        Customer customer1 = new Customer(11, "male");
        product1.setCustomer(customer1);
        customerRepository.save(customer1);
        em.flush();

        product2.setCustomer(customer1);
        customerRepository.save(customer1);
        em.flush();

        product3.setCustomer(customer1);
        customerRepository.save(customer1);
        em.flush();

        product4.setCustomer(customer1);
        customerRepository.save(customer1);
        em.flush();

        Customer customer2 = new Customer(12, "female");
        product1.setCustomer(customer2);
        customerRepository.save(customer2);
        em.flush();

        product2.setCustomer(customer2);
        customerRepository.save(customer2);
        em.flush();

        product3.setCustomer(customer2);
        customerRepository.save(customer2);
        em.flush();

        product4.setCustomer(customer2);
        customerRepository.save(customer2);
        em.flush();

        Customer customer3 = new Customer(13, "female");
        product1.setCustomer(customer3);
        customerRepository.save(customer3);
        em.flush();

        product2.setCustomer(customer3);
        customerRepository.save(customer3);
        em.flush();

        product3.setCustomer(customer3);
        customerRepository.save(customer3);
        em.flush();

        Customer customer4 = new Customer(14, "female");
        product1.setCustomer(customer4);
        customerRepository.save(customer4);
        em.flush();

        product2.setCustomer(customer4);
        customerRepository.save(customer4);
        em.flush();

        Customer customer5 = new Customer(15, "female");
        product1.setCustomer(customer5);
        customerRepository.save(customer5);
        em.flush();

        product2.setCustomer(customer5);
        customerRepository.save(customer5);
        em.flush();

        Customer customer6 = new Customer(15, "female");
        product1.setCustomer(customer6);
        customerRepository.save(customer6);
        em.flush();

        Customer customer7 = new Customer(16, "female");
        product1.setCustomer(customer7);
        customerRepository.save(customer7);
        em.flush();

        Customer customer8 = new Customer(17, "female");
        product1.setCustomer(customer8);
        customerRepository.save(customer8);
        em.flush();

        // 20대 1, 3, 2, 4
        Customer customer9 = new Customer(22, "male");
        product1.setCustomer(customer9);
        customerRepository.save(customer9);
        em.flush();

        product3.setCustomer(customer9);
        customerRepository.save(customer9);
        em.flush();

        product2.setCustomer(customer9);
        customerRepository.save(customer9);
        em.flush();

        product4.setCustomer(customer9);
        customerRepository.save(customer9);
        em.flush();

        Customer customer10 = new Customer(24, "male");
        product1.setCustomer(customer10);
        customerRepository.save(customer10);
        em.flush();

        product3.setCustomer(customer10);
        customerRepository.save(customer10);
        em.flush();

        product2.setCustomer(customer10);
        customerRepository.save(customer10);
        em.flush();

        product4.setCustomer(customer10);
        customerRepository.save(customer10);
        em.flush()

        Customer customer39 = new Customer(52, "female");
        product2.setCustomer(customer39);
        customerRepository.save(customer39);
        em.flush();

        product3.setCustomer(customer39);
        customerRepository.save(customer39);
        em.flush();

        Customer customer40 = new Customer(51, "female");
        product2.setCustomer(customer40);
        customerRepository.save(customer40);
        em.flush();

        product3.setCustomer(customer40);
        customerRepository.save(customer40);
        em.flush();

        Customer customer41= new Customer(57, "male");
        product2.setCustomer(customer41);
        customerRepository.save(customer41);
        em.flush();

        Customer customer42= new Customer(59, "female");
        product2.setCustomer(customer42);
        customerRepository.save(customer42);
        em.flush();

        Customer customer43= new Customer(53, "female");
        product2.setCustomer(customer43);
        customerRepository.save(customer43);
        em.flush(
    }
}

문제 상황

Customer과 Product를 사전에 저장하는 코드이다. 이 때

Customer에 존재하는 Product 들이 Customer에 존재해야 하는데 존재하지 않는다.

1 2

한번 save() 메서드를 호출할 때 어떻게 SQL문 쿼리가 날라가는지 살펴보도록 하자.

Spring JPA의 save() 코드

@Transactional
	@Override
	public <S extends T> S save(S entity) {

		Assert.notNull(entity, "Entity must not be null.");

		if (entityInformation.isNew(entity)) {
			em.persist(entity);
			return entity;
		} else {
			return em.merge(entity);
		}
	}

실제 테스트 실행간 첫 save()시 SQL 문

insert 
    into
        customer
        (id, age, sex) 
    values
        (default, ?, ?)

두번째 save()시 SQL 문

update
        product 
    set
        customer_id=?,
        price=?,
        product_name=? 
    where
        id=?

두번째 save()시 insert가 아니라 update 쿼리가 날라가네?

그러면 왜 save()시 update로 넘어가는지 살펴보자.



문제 상황 가설

양방향 연관 관계 설정간 문제가 발생한거 아닐까?


기존 연관관계 편의 메소드 코드 #주인(N측)에

       public void setCustomer(Customer customer) {
               //기존 팀과 관계를 제거
               if (this.customer !=null) {
                   this.customer.getProducts().remove(this);
               }
               this.customer = customer;
               customer.getProducts().add(this);
           }

연관관계 편의 메서드를 아래와 같이 변경하니 두번째 save()도 정상적으로 Insert가 되었다.

    public void setCustomer(Customer customer) {
            //기존 팀과 관계를 제거
            if (this.customer !=null) {
                this.customer.getProducts().remove(this);
            }
            this.customer = customer;
    
            if (!customer.getProducts().contain(this)) {
                customer.getProducts().add(this);
            }
        }

위와 같이 연관 관계 편의 메서드를 변경하니 정상적으로 insert SQL 문이 출력된다.

    2023-09-04 00:06:29.984 DEBUG 64813 --- [           main] org.hibernate.SQL                        : 
        insert 
        into
            product
            (id, customer_id, price, product_name) 
        values
            (default, ?, ?, ?)
    2023-09-04 00:06:29.985 DEBUG 64813 --- [           main] org.hibernate.SQL                        : 
        insert 
        into
            product
            (id, customer_id, price, product_name) 
        values
            (default, ?, ?, ?)

정상적으로 출력되는 이유
기존 단순히 주인이 아닌 Customer 측이 null인지만 검증을 하고, 주인인 Product에서 customer가 컬렉션에 있는지를 검증을 하지 않아서,

Customer가 Product의 컬렉션에 기존에 있는 경우에 더티체킹이 발생해서 update 쿼리가 발생한 것이었다.




어쨋든 오늘도 해결~

undefined

profile
Hello, World! \n

0개의 댓글