INSERT 직후 PK 얻기 & JOIN을 활용한 상품 목록 조회

heeezni·2025년 6월 14일

Java GUI 프로젝트

목록 보기
17/20

SQL - last_insert_id()

INSERT로 인해 AUTO_INCREMENT된 PK중 최신값 얻기

  • 현재 세션(내 연결)에서 마지막으로 생성된 AUTO_INCREMENT 값만 반환됨

  • ❌ 절대 max() 사용 금지: 모든 유저의 데이터 중 가장 큰 값이 반환되므로 안전하지 않음

  • 사용 SQL: SELECT last_insert_id();
    last_insert_id()는 세션 단위라서 다른 유저의 insert에 영향을 받지 않음
    max()보다 안전

	public int selectRecentPk() {
		Connection con = null;
		PreparedStatement pstmt = null;
		ResultSet rs = null;

		int pk = 0; // 반환할 PK 값

		con = dbManger.getConnection(); // DB 연결
        
		StringBuffer sql = new StringBuffer();
        // 현재 세션 기준 마지막 insert된 PK 조회
		sql.append("select last_insert_id() as product_id"); 

		try {
			pstmt = con.prepareStatement(sql.toString());
			rs = pstmt.executeQuery(); // 쿼리 실행

			while (rs.next()) {
				pk = rs.getInt("product_id"); // 조회된 PK 값 가져오기
			}
		} catch (SQLException e) {
			e.printStackTrace();
		} finally {
			dbManger.release(rs, pstmt);
		}
		return pk;
	}
/*---------▼ ProductPage.java에서-----------------------------------------------*/
// ProductDAO에게 상품 insert 요청 (DB에 저장)
productDAO.insert(product);

// ✅ 방금 insert된 상품의 PK(primary key) 값 조회
int product_id = productDAO.selectRecentPk();

// ✅ 조회한 PK를 Product 객체에 다시 주입 (객체 상태 완성)
product.setProduct_id(product_id); // ★ 중요: DB와 객체 상태를 일치시킴 ★

왜 방금 insert된 상품의 PK를 Product 객체에 다시 주입할까?

DB에 저장된 실제 상품과 Java의 Product 객체가
동일한 실체임을 보장하려면,
last_insert_id()로 구한 최신 PK를
해당 객체(Product)에도 주입해야 한다.

📌 이렇게 해야 이후 연관 작업(insert, update, delete 등)에서도
Product 객체를 DB와 연결된 진짜 데이터로 일관되게 활용할 수 있다.

👉 즉, "이 객체 = 방금 DB에 저장된 상품" 으로써의 정체성이 확립된다.


SQL - JOIN

Inner Join을 이용한 3테이블 조인

모든 상품 목록 가져오기 ( 상위카테고리 + 하위카테고리 + 상품 JOIN )

	public List<Product> selectAll() {
		Connection con = dbManger.getConnection();
		PreparedStatement pstmt = null;
		ResultSet rs = null;

		// 배열 대신 List 사용 → ResultSet을 앞뒤로 이동할 필요 없음, 크기 미지정 가능
		List<Product> list = new ArrayList<>();

		StringBuffer sql = new StringBuffer();

		// ✅ INNER JOIN을 이용한 3테이블 조인
		// (topcategory ↔ subcategory ↔ product 순서로 연결)
		// color, size, img는 상세보기에서 보여주기 때문에 여기서는 제외
		sql.append("select ");
		sql.append("t.topcategory_id, top_name, ");
		sql.append("s.subcategory_id, sub_name, ");
		sql.append("product_id, product_name, brand, price, discount, introduce, detail ");
		sql.append("from topcategory t ");
		sql.append("inner join subcategory s on t.topcategory_id = s.topcategory_id ");
		sql.append("inner join product p on s.subcategory_id = p.subcategory_id");

		try {
			pstmt = con.prepareStatement(sql.toString());
			rs = pstmt.executeQuery(); // 쿼리 실행

			while (rs.next()) {
				// 상품 객체 생성 및 값 주입
				Product product = new Product();
				product.setProduct_id(rs.getInt("product_id"));
				product.setProduct_name(rs.getString("product_name"));
				product.setBrand(rs.getString("brand"));
				product.setPrice(rs.getInt("price"));
				product.setDiscount(rs.getInt("discount"));
				product.setIntroduce(rs.getString("introduce"));
				product.setDetail(rs.getString("detail"));

				// 하위카테고리 객체 생성
				SubCategory subcategory = new SubCategory();
				subcategory.setSubcategory_id(rs.getInt("subcategory_id")); // "s.subcategory_id" ❌ 아님
				subcategory.setSub_name(rs.getString("sub_name"));

				// 상위카테고리 객체 생성 → 하위카테고리에 주입
				TopCategory topcategory = new TopCategory();
				topcategory.setTopcategory_id(rs.getInt("topcategory_id")); // "t.topcategory_id" ❌ 아님
				topcategory.setTop_name(rs.getString("top_name"));
				subcategory.setTopCategory(topcategory);

				// 상품에 하위카테고리 포함시켜 연관관계 구성
				product.setSubcategory(subcategory);

				// 리스트에 추가
				list.add(product);
			}
		} catch (SQLException e) {
			e.printStackTrace();
		} finally {
			dbManger.release(rs, pstmt);
		}

		return list;
	}

Join

JOIN 종류의미누락 시 처리 방식
INNER JOIN공통 데이터만 조회매칭 안 되면 제외
LEFT OUTER JOIN왼쪽 테이블 전부 + 매칭오른쪽 NULL 채움
RIGHT OUTER JOIN오른쪽 테이블 전부 + 매칭왼쪽 NULL 채움
profile
아이들의 가능성을 믿었던 마음 그대로, 이제는 나의 가능성을 믿고 나아가는 중입니다.🌱

0개의 댓글