본문 바로가기
🍃 𝗦𝗽𝗿𝗶𝗻𝗴 𝗕𝗼𝗼𝘁

Spring Boot 게시글 좋아요 기능 구현(좋아요 조회, 좋아요 판별)

by 비타민찌 2022. 3. 30.
728x90

좋아요 기능

게시글에 좋아요 버튼 처음 누르면 좋아요,

이미 좋아요를 누른 게시글에 또 좋아요를 누르면 좋아요 취소가 되는 기능 구현.

좋아요를 누르는 파트1과,

좋아요를 누른 게시글을 조회2할 수 있는 두 파트로 나눠 정리한다.

 

[좋아요]

1) likes 테이블 생성.

create table likes (
    member_idx int,
    product_idx int,
    foreign key (member_idx) references member (idx),
    foreign key (product_idx) references product (idx),
    primary key (member_idx, product_idx)
);
 

* 이전글 [Spring Boot + JWT + Security + Security 권한 설정해서 '회원가입/로그인 구현'] 참고

 

- member_idx:

기존 사용자 table인 member table의 idx(pk)

- product_idx:

기존 상품 테이블인 product table의 idx(pk)

 

2) ProductController

@ResponseBody
    @GetMapping("/like/{idx}")
    public String likeProduct(@AuthenticationPrincipal UserLoginRes userLoginRes, @PathVariable int idx) {
        return  productService.likeProduct(userLoginRes.getIdx(),idx);
    }
 

 

3) ProductService

public String likeProduct(int userLoginResIdx, int idx){
        return productDao.likeProduct(userLoginResIdx, idx);
    }
 

 

4) ProductDao

public String likeProduct(int userLoginResIdx, int idx) {
        String getLikeQuery = "select * from likes where member_idx=? and product_idx=?";
        List<Map<String, Object>> rows = this.jdbcTemplate.queryForList(getLikeQuery, userLoginResIdx, idx);
 

해당 사용자가

게시글에 좋아요를 누른 적이 있는지 확인한다.

 

member_idx와 product_idx를 뽑아 rows에 저장해서

rows의 길이가 0인 경우, 즉 좋아요 누른 게시글이 없는 경우

like 테이블에 member_idx와 product_idx를 저장하자.

        if (rows.size() == 0) {
            String createProductQuery = "insert into likes (member_idx, product_idx) VALUES (?, ?)";

            Object[] createProductParams = new Object[]{userLoginResIdx, idx};

            this.jdbcTemplate.update(createProductQuery, createProductParams);

            String getLastInsertIdxQuery = "select last_insert_id()";
            int lastInsertIdx = this.jdbcTemplate.queryForObject(getLastInsertIdxQuery, int.class);

            return "added";
        }
 

그럼 그 반대의 경우는

rows의 길이가 0이 아닌, 이미 좋아요를 누른 게시글이다.

DELETE 쿼리로 좋아요 취소를 구현한다.

 else {
            String createProductQuery = "DELETE FROM likes WHERE member_idx=? and product_idx=?";

            Object[] createProductParams = new Object[]{userLoginResIdx, idx};

            this.jdbcTemplate.update(createProductQuery, createProductParams);

            String getLastInsertIdxQuery = "select last_insert_id()";
            int lastInsertIdx = this.jdbcTemplate.queryForObject(getLastInsertIdxQuery, int.class);

            return "deleted";

        }
 

 

[좋아요 누른 게시글 조회]

GetProductWithImageAndLikesRes 라는 모델을 생성한다.

기존의 GetProductWithImageRes 에서 like_check(Boolean) 변수만 하나 추가됐다.

@Getter
@Setter
@AllArgsConstructor
public class GetProductWithImageAndLikesRes {
    private int idx;
    private String name;
    private int brandIdx;
    private int categoryIdx;
    private int price;
    private int salePrice;
    private String deliveryType;
    private String isTodayDeal;
    private String filename;
    private Boolean like_check;
}
 

 

ProductDao

getProductsWithProductImage 메서드에서 로그인 하지 않은 사용자들은

like_check 가 false가 되게 한다.

    public List<GetProductWithImageAndLikesRes> getProductsWithProductImage() {
        String getProductsQuery = "SELECT * FROM product left JOIN (SELECT productIdx, group_concat(filename) FROM productImage group by productIdx) as pi ON product.idx=pi.productIdx";

        return this.jdbcTemplate.query(getProductsQuery,
                (rs, rowNum) -> new GetProductWithImageAndLikesRes(
                        rs.getObject("idx", int.class),
                        rs.getString("name"),
                        rs.getObject("brandIdx", int.class),
                        rs.getObject("categoryIdx", int.class),
                        rs.getObject("price", int.class),
                        rs.getObject("salePrice", int.class),
                        rs.getString("deliveryType"),
                        rs.getString("isTodayDeal"),
                        rs.getString("filename"),
                        false
                ));
    }
 

getProductsWithProductImageAndLikes 메서드에서 로그인한 사용자는

like_check 가 rs.getBoolean("like_ckeck") 즉 true나 false가 된다.

public List<GetProductWithImageAndLikesRes> getProductsWithProductImageAndLikes(int member_idx) {
        String getProductsQuery = "SELECT *, ifnull(product_idx, false) as like_ckeck FROM product left JOIN (SELECT productIdx, group_concat(filename) as filename FROM productImage group by productIdx) as pi ON product.idx=pi.productIdx LEFT JOIN (SELECT product_idx FROM likes WHERE member_idx=?) as likes ON likes.product_idx=product.idx;";

        return this.jdbcTemplate.query(getProductsQuery,
                (rs, rowNum) -> new GetProductWithImageAndLikesRes(
                        rs.getObject("idx", int.class),
                        rs.getString("name"),
                        rs.getObject("brandIdx", int.class),
                        rs.getObject("categoryIdx", int.class),
                        rs.getObject("price", int.class),
                        rs.getObject("salePrice", int.class),
                        rs.getString("deliveryType"),
                        rs.getString("isTodayDeal"),
                        rs.getString("filename"),
                        rs.getBoolean("like_ckeck")
                        ),member_idx);
    }
 

 

Advanced REST client로 테스트.

1)

1)

 
 

좋아요가 없을 때, 좋아요 눌러서 added 출력.

좋아요 누른 상태에서, 좋아요 눌러서 deleted 출력.

 

2) 조회 테스트

GET, http://localhost:8080/product/lists

 
 

 


* jdbcTemplate getObject null 일 때 처리 참고:

Checking for a null int value from a Java ResultSet

 

 

* MySQL 컬럼 순서 바꿔 출력하기, 컬럼 별명 붙이기

컬럼 이름에 number나 sales만 표시하면 어떤 데이터를 표시한 것인지 잘 모를 수 있다..

select 컬럼명 as 별명 from 테이블명;
 

이런 경우 컬럼을 알기 쉽도록 별명을 붙일 수 있는데,

컬럼 number에는 사원번호, sales 에는 매출이라는 별명을 붙여 보자.

select number as 사원번호, sales as 매출 from table_sales;
728x90

댓글