2023.11.26 - [웹/Spring vue 웹 개발] - spring vue jpa repository 테스트코드

spring vue jpa repository 테스트코드

이전글: 2023.11.25 - [웹/Spring vue 웹 개발] - spring vue entity 변경 spring vue entity 변경 테이블을 이번에 전부 변경했습니다. https://www.erdcloud.com/d/TBkodsGPbZev8sBXs 백엔드 Draw ERD with your team members. All states are

kwaksh2319.tistory.com

이전글이는 레파지토리 테스트 코드를 작성했는데요.
오늘은 swagger를 이용해서 컨트롤러를 api 문서화 했습니다.
테스트코드는 아직 제가 완성을 못해서 다음주에 올리도록 하겠습니다.

 
controller 코드 및 service 코드도 다음에 테스트 코드 작성할떄 같이 올리도록 하겠습니다. 
 
 

이전글:

2023.11.25 - [웹/Spring vue 웹 개발] - spring vue entity 변경

 

spring vue entity 변경

테이블을 이번에 전부 변경했습니다. https://www.erdcloud.com/d/TBkodsGPbZev8sBXs 백엔드 Draw ERD with your team members. All states are shared in real time. And it's FREE. Database modeling tool. www.erdcloud.com users package kr.co.kshpro

kwaksh2319.tistory.com

UserRepositoryTest

package kr.co.kshproject.webDemo.Domain.Users;

import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest;

import java.util.List;
import java.util.Optional;

import static org.junit.jupiter.api.Assertions.*;

@DataJpaTest
class UsersRepositoryTest {

    @Autowired
    private UsersRepository usersRepository;

    @Test
    public void save() {
        Users newUser = new Users();
        newUser.setUsername("testuser");
        newUser.setEmail("test@example.com");
        newUser.setName("Test User");
        newUser.setLevel(1L);
        newUser.setPassword("password");
        Users savedUser = usersRepository.save(newUser);
        Optional<Users> foundUser = usersRepository.findById(savedUser.getId());

        assertTrue(foundUser.isPresent());
        assertEquals("testuser", foundUser.get().getUsername());
    }

    @Test
    public void findAll() {
        Users newUser = new Users();
        newUser.setUsername("testuser");
        newUser.setEmail("test@example.com");
        newUser.setName("Test User");
        newUser.setLevel(1L);
        newUser.setPassword("password");
        Users savedUser = usersRepository.save(newUser);

        List<Users> users = usersRepository.findAll();
        assertFalse(users.isEmpty());
    }

    @Test
    public void findById() {
        Users newUser = new Users();
        newUser.setUsername("testuser");
        newUser.setEmail("test@example.com");
        newUser.setName("Test User");
        newUser.setLevel(1L);
        newUser.setPassword("password");
        Users savedUser = usersRepository.save(newUser);

        Optional<Users> foundUser = usersRepository.findById(savedUser.getId());
        assertTrue(foundUser.isPresent());
        assertEquals("testuser", foundUser.get().getUsername());
    }

    @Test
    public void update() {
        Users newUser = new Users();
        newUser.setUsername("testuser");
        newUser.setEmail("test@example.com");
        newUser.setName("Test User");
        newUser.setLevel(1L);
        newUser.setPassword("password");
        Users savedUser = usersRepository.save(newUser);

        Users userToUpdate = usersRepository.findById(savedUser.getId()).get();
        userToUpdate.setName("Updated Name");
        usersRepository.save(userToUpdate);

        Optional<Users> updatedUser = usersRepository.findById(savedUser.getId());
        assertTrue(updatedUser.isPresent());
        assertEquals("Updated Name", updatedUser.get().getName());
    }

    @Test
    public void deleteAll() {
        Users newUser = new Users();
        newUser.setUsername("testuser");
        newUser.setEmail("test@example.com");
        newUser.setName("Test User");
        newUser.setLevel(1L);
        newUser.setPassword("password");
        Users savedUser = usersRepository.save(newUser);

        usersRepository.deleteAll();
        List<Users> users = usersRepository.findAll();
        assertTrue(users.isEmpty());
    }

}

ProductsRepositoryTest

package kr.co.kshproject.webDemo.Domain.Products;

import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest;

import java.util.List;
import java.util.Optional;

import static org.junit.jupiter.api.Assertions.*;

@DataJpaTest
class ProductsRepositoryTest {
    @Autowired
    private ProductsRepository productsRepository;

    @BeforeEach
    void before(){

    }

    @AfterEach
    void after() {
        // 테스트 데이터 정리
        productsRepository.deleteAll();
    }

    @Test
    public void save() {
        Products product=new Products();

        product.setProductName("testProduct");
        product.setPicture("testPicture");
        product.setDescribe("test");
        product.setPrice(100L);
        product.setSoldOut(false);
        product.setCreatedDate("20231125");
        product.setUpdateDate("20231125");

        product.setCategory(null);

        Products savedProduct = productsRepository.save(product);
        Optional<Products> foundProduct = productsRepository.findById(savedProduct.getId());

        assertTrue(foundProduct.isPresent());
        assertEquals("testProduct", foundProduct.get().getProductName());
    }

    @Test
    public void findAll() {
        Products product=new Products();
        product.setProductName("testProduct");
        product.setPicture("testPicture");
        product.setDescribe("test");
        product.setPrice(100L);
        product.setSoldOut(false);
        product.setCreatedDate("20231125");
        product.setUpdateDate("20231125");

        Products savedProducts = productsRepository.save(product);

        List<Products> products = productsRepository.findAll();
        assertFalse(products.isEmpty());
    }

    @Test
    public void findById() {
        Products product=new Products();
        product.setProductName("testProduct");
        product.setPicture("testPicture");
        product.setDescribe("test");
        product.setPrice(100L);
        product.setSoldOut(false);
        product.setCreatedDate("20231125");
        product.setUpdateDate("20231125");
        Products savedProducts = productsRepository.save(product);

        Optional<Products> foundProduct = productsRepository.findById(savedProducts.getId());
        assertTrue(foundProduct.isPresent());
        assertEquals("testProduct", foundProduct.get().getProductName());
    }

    @Test
    public void update() {
        Products product=new Products();
        product.setProductName("testProduct");
        product.setPicture("testPicture");
        product.setDescribe("test");
        product.setPrice(100L);
        product.setSoldOut(false);
        product.setCreatedDate("20231125");
        product.setUpdateDate("20231125");
        Products savedProduct = productsRepository.save(product);

        Products productToUpdate = productsRepository.findById(savedProduct.getId()).get();
        productToUpdate.setProductName("Updated Product");
        productsRepository.save(productToUpdate);

       Optional<Products> updatedProduct = productsRepository.findById(savedProduct.getId());
       assertTrue(updatedProduct.isPresent());
        assertEquals("Updated Product", updatedProduct.get().getProductName());
    }

    @Test
    public void deleteAll() {
        Products product=new Products();
        product.setProductName("testProduct");
        product.setPicture("testPicture");
        product.setDescribe("test");
        product.setPrice(100L);
        product.setSoldOut(false);
        product.setCreatedDate("20231125");
        product.setUpdateDate("20231125");
        Products savedProduct = productsRepository.save(product);

        productsRepository.deleteAll();
        List<Products> products = productsRepository.findAll();
        assertTrue(products.isEmpty());
    }
}

OrdersRepositoryTest

package kr.co.kshproject.webDemo.Domain.Orders;

import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest;

import java.util.List;
import java.util.Optional;

import static org.junit.jupiter.api.Assertions.*;

@DataJpaTest
class OrdersRepositoryTest {
    @Autowired
    private OrdersRepository ordersRepository;

    @BeforeEach
    void before(){

    }

    @AfterEach
    void after() {
        // 테스트 데이터 정리
        ordersRepository.deleteAll();
    }

    @Test
    public void save() {
        Orders order=new Orders();
        order.setStatus("T");
        order.setPrice(100L);
        order.setPayment("card");
        order.setCancel(false);
        order.setCreatedDate("20231125");
        order.setUpdateDate("20231125");
        order.setUsers(null);
        Orders savedOrder = ordersRepository.save(order);
        Optional<Orders> foundOrder = ordersRepository.findById(savedOrder.getId());

        assertTrue(foundOrder.isPresent());
        assertEquals("card", foundOrder.get().getPayment());
    }

    @Test
    public void findAll() {
        Orders order=new Orders();
        order.setStatus("T");
        order.setPrice(100L);
        order.setPayment("card");
        order.setCancel(false);
        order.setCreatedDate("20231125");
        order.setUpdateDate("20231125");
        order.setUsers(null);
        Orders savedOrders = ordersRepository.save(order);

        List<Orders> Orders  = ordersRepository.findAll();
        assertFalse(Orders.isEmpty());
    }

    @Test
    public void findById() {
        Orders order=new Orders();
        order.setStatus("T");
        order.setPrice(100L);
        order.setPayment("card");
        order.setCancel(false);
        order.setCreatedDate("20231125");
        order.setUpdateDate("20231125");
        order.setUsers(null);
        Orders savedOrder = ordersRepository.save(order);

        Optional<Orders> foundOrder = ordersRepository.findById(savedOrder.getId());
        assertTrue(foundOrder.isPresent());
        assertEquals("card", foundOrder.get().getPayment());
    }

    @Test
    public void update() {
        Orders order=new Orders();
        order.setStatus("T");
        order.setPrice(100L);
        order.setPayment("card");
        order.setCancel(false);
        order.setCreatedDate("20231125");
        order.setUpdateDate("20231125");
        order.setUsers(null);
        Orders savedOrder = ordersRepository.save(order);

        Orders orderToUpdate = ordersRepository.findById(savedOrder.getId()).get();
        orderToUpdate.setPayment("cash");
        ordersRepository.save(orderToUpdate);

        Optional<Orders> updatedOrder = ordersRepository.findById(savedOrder.getId());
        assertTrue(updatedOrder.isPresent());
        assertEquals("cash", updatedOrder.get().getPayment());
    }

    @Test
    public void deleteAll() {
        Orders order=new Orders();
        order.setStatus("T");
        order.setPrice(100L);
        order.setPayment("card");
        order.setCancel(false);
        order.setCreatedDate("20231125");
        order.setUpdateDate("20231125");
        order.setUsers(null);
        Orders orderProduct = ordersRepository.save(order);

        ordersRepository.deleteAll();
        List<Orders> orders = ordersRepository.findAll();
        assertTrue(orders.isEmpty());
    }
}

NoticeRepositorylTest

package kr.co.kshproject.webDemo.Domain.Notice;

import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest;

import java.util.List;
import java.util.Optional;

import static org.junit.jupiter.api.Assertions.*;

@DataJpaTest
class NoticeRepositorylTest {
    @Autowired
    private NoticeRepository noticeRepository;

    @BeforeEach
    void before(){

    }

    @AfterEach
    void after() {
        // 테스트 데이터 정리
        noticeRepository.deleteAll();
    }

    @Test
    public void save() {
        Notice notice=new Notice();
        notice.setUsername("testUserName");
        notice.setTitle("test");
        notice.setContents("testcontent");
        notice.setUsers(null);
        notice.setEmail("test@mail.com");
        notice.setCreatedDate("20231125");

        Notice savedNotice = noticeRepository.save(notice);
        Optional<Notice> foundNotice = noticeRepository.findById(savedNotice.getId());

        assertTrue(foundNotice.isPresent());
        assertEquals("test", foundNotice.get().getTitle());
    }

    @Test
    public void findAll() {
        Notice notice=new Notice();
        notice.setUsername("testUserName");
        notice.setTitle("test");
        notice.setContents("testcontent");
        notice.setUsers(null);
        notice.setEmail("test@mail.com");
        notice.setCreatedDate("20231125");

        Notice savedNotice = noticeRepository.save(notice);

        List<Notice> notices  = noticeRepository.findAll();
        assertFalse(notices.isEmpty());
    }

    @Test
    public void findById() {
        Notice notice=new Notice();
        notice.setUsername("testUserName");
        notice.setTitle("test");
        notice.setContents("testcontent");
        notice.setUsers(null);
        notice.setEmail("test@mail.com");
        notice.setCreatedDate("20231125");

        Notice savedNotice = noticeRepository.save(notice);

        Optional<Notice> foundNotice = noticeRepository.findById(savedNotice.getId());
        assertTrue(foundNotice.isPresent());
        assertEquals("test", foundNotice.get().getTitle());
    }

    @Test
    public void update() {
        Notice notice=new Notice();
        notice.setUsername("testUserName");
        notice.setTitle("test");
        notice.setContents("testcontent");
        notice.setUsers(null);
        notice.setEmail("test@mail.com");
        notice.setCreatedDate("20231125");

        Notice savedNotice = noticeRepository.save(notice);

        Notice noticeToUpdate = noticeRepository.findById(savedNotice.getId()).get();
        noticeToUpdate.setTitle("update test");
        noticeRepository.save(noticeToUpdate);

        Optional<Notice> updatedNotice = noticeRepository.findById(savedNotice.getId());
        assertTrue(updatedNotice.isPresent());
        assertEquals("update test", updatedNotice.get().getTitle());
    }

    @Test
    public void deleteAll() {
        Notice notice=new Notice();
        notice.setUsername("testUserName");
        notice.setTitle("test");
        notice.setContents("testcontent");
        notice.setUsers(null);
        notice.setEmail("test@mail.com");
        notice.setCreatedDate("20231125");

        Notice savedNotice = noticeRepository.save(notice);
        noticeRepository.deleteAll();
        List<Notice> notices = noticeRepository.findAll();
        assertTrue(notices.isEmpty());
    }
}

 

CommentRepositoryTest

package kr.co.kshproject.webDemo.Domain.Comment;

import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest;

import java.util.List;
import java.util.Optional;

import static org.junit.jupiter.api.Assertions.*;
@DataJpaTest
class CommentRepositoryTest {
    @Autowired
    private CommentRepository commentRepository;

    @BeforeEach
    void before(){

    }

    @AfterEach
    void after() {
        // 테스트 데이터 정리
        commentRepository.deleteAll();
    }

    @Test
    public void save() {
        Comment comment=new Comment();
        comment.setUserName("testUserName");
        comment.setContents("test");
        comment.setCreatedDate("20231125");
        comment.setNotice(null);
        comment.setUsers(null);

        Comment savedComment = commentRepository.save(comment);
        Optional<Comment> foundComment = commentRepository.findById(savedComment.getId());

        assertTrue(foundComment.isPresent());
        assertEquals("test", foundComment.get().getContents());
    }

    @Test
    public void findAll() {
        Comment comment=new Comment();
        comment.setUserName("testUserName");
        comment.setContents("test");
        comment.setCreatedDate("20231125");
        comment.setNotice(null);
        comment.setUsers(null);

        Comment savedComment = commentRepository.save(comment);

        List<Comment> comments  = commentRepository.findAll();
        assertFalse(comments.isEmpty());
    }

    @Test
    public void findById() {
        Comment comment=new Comment();
        comment.setUserName("testUserName");
        comment.setContents("test");
        comment.setCreatedDate("20231125");
        comment.setNotice(null);
        comment.setUsers(null);

        Comment savedComment = commentRepository.save(comment);

        Optional<Comment> foundComment = commentRepository.findById(savedComment.getId());
        assertTrue(foundComment.isPresent());
        assertEquals("test", foundComment.get().getContents());
    }

    @Test
    public void update() {
        Comment comment=new Comment();
        comment.setUserName("testUserName");
        comment.setContents("test");
        comment.setCreatedDate("20231125");
        comment.setNotice(null);
        comment.setUsers(null);

        Comment savedComment = commentRepository.save(comment);

        Comment commentToUpdate = commentRepository.findById(savedComment.getId()).get();
        commentToUpdate.setContents("update test");
        commentRepository.save(commentToUpdate);

        Optional<Comment> updatedComment = commentRepository.findById(savedComment.getId());
        assertTrue(updatedComment.isPresent());
        assertEquals("update test", updatedComment.get().getContents());
    }

    @Test
    public void deleteAll() {
        Comment comment=new Comment();
        comment.setUserName("testUserName");
        comment.setContents("test");
        comment.setCreatedDate("20231125");
        comment.setNotice(null);
        comment.setUsers(null);

        Comment savedComment = commentRepository.save(comment);
        commentRepository.deleteAll();
        List<Comment> comments = commentRepository.findAll();
        assertTrue(comments.isEmpty());
    }
}

 

CategoryRepositoryTest

package kr.co.kshproject.webDemo.Domain.Category;

import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest;

import java.util.List;
import java.util.Optional;

import static org.junit.jupiter.api.Assertions.*;

@DataJpaTest
class CategoryRepositoryTest {
    @Autowired
    private CategoryRepository categoryRepository;

    @BeforeEach
    void before(){

    }

    @AfterEach
    void after() {
        // 테스트 데이터 정리
        categoryRepository.deleteAll();
    }

    @Test
    public void save() {
        Category category=new Category();
        category.setCategoryName("test");
        category.setParentCategory(null);
        category.setCreatedDate("20231125");
        category.setUpdateDate("20231125");

        Category savedCategory = categoryRepository.save(category);
        Optional<Category> foundCategory = categoryRepository.findById(savedCategory.getId());

        assertTrue(foundCategory.isPresent());
        assertEquals("test", foundCategory.get().getCategoryName());
    }

    @Test
    public void findAll() {
        Category category=new Category();
        category.setCategoryName("test");
        category.setParentCategory(null);
        category.setCreatedDate("20231125");
        category.setUpdateDate("20231125");

        Category savedCategory = categoryRepository.save(category);

        List<Category> categories  = categoryRepository.findAll();
        assertFalse(categories.isEmpty());
    }

    @Test
    public void findById() {
        Category category=new Category();
        category.setCategoryName("test");
        category.setParentCategory(null);
        category.setCreatedDate("20231125");
        category.setUpdateDate("20231125");

        Category savedCategory = categoryRepository.save(category);

        Optional<Category> foundCategory= categoryRepository.findById(savedCategory.getId());
        assertTrue(foundCategory.isPresent());
        assertEquals("test", foundCategory.get().getCategoryName());
    }

    @Test
    public void update() {
        Category category=new Category();
        category.setCategoryName("test");
        category.setParentCategory(null);
        category.setCreatedDate("20231125");
        category.setUpdateDate("20231125");

        Category savedCategory = categoryRepository.save(category);

        Category categoryToUpdate = categoryRepository.findById(savedCategory.getId()).get();
        categoryToUpdate.setCategoryName("update test");
        categoryRepository.save(categoryToUpdate);

        Optional<Category> updatedCategory = categoryRepository.findById(savedCategory.getId());
        assertTrue(updatedCategory.isPresent());
        assertEquals("update test", updatedCategory.get().getCategoryName());
    }

    @Test
    public void deleteAll() {
        Category category=new Category();
        category.setCategoryName("test");
        category.setParentCategory(null);
        category.setCreatedDate("20231125");
        category.setUpdateDate("20231125");

        Category savedCategory = categoryRepository.save(category);
        categoryRepository.deleteAll();
        List<Category> categories = categoryRepository.findAll();
        assertTrue(categories.isEmpty());
    }
}

 

BeginOrderRepositoryTest

package kr.co.kshproject.webDemo.Domain.BeginOrder;

import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest;

import java.util.List;
import java.util.Optional;

import static org.junit.jupiter.api.Assertions.*;

@DataJpaTest
class BeginOrderRepositoryTest {
    @Autowired
    private BeginOrderRepository beginOrderRepository;

    @BeforeEach
    void before(){

    }

    @AfterEach
    void after() {
        // 테스트 데이터 정리
        beginOrderRepository.deleteAll();
    }

    @Test
    public void save() {
        BeginOrder beginOrder=new BeginOrder();
        beginOrder.setPicture("test");
        beginOrder.setOrders(null);
        beginOrder.setProducts(null);
        beginOrder.setQuantity(1L);
        beginOrder.setCreatedDate("20231125");
        beginOrder.setUpdateDate("20231125");

        BeginOrder savedBeginOrder = beginOrderRepository.save(beginOrder);
        Optional<BeginOrder> foundBeginOrder= beginOrderRepository.findById(savedBeginOrder.getId());

        assertTrue(foundBeginOrder.isPresent());
        assertEquals("test", foundBeginOrder.get().getPicture());
    }

    @Test
    public void findAll() {
        BeginOrder beginOrder=new BeginOrder();
        beginOrder.setPicture("test");
        beginOrder.setOrders(null);
        beginOrder.setProducts(null);
        beginOrder.setQuantity(1L);
        beginOrder.setCreatedDate("20231125");
        beginOrder.setUpdateDate("20231125");

        BeginOrder savedBeginOrder = beginOrderRepository.save(beginOrder);

        List<BeginOrder> beginOrders  = beginOrderRepository.findAll();
        assertFalse(beginOrders.isEmpty());
    }

    @Test
    public void findById() {
        BeginOrder beginOrder=new BeginOrder();
        beginOrder.setPicture("test");
        beginOrder.setOrders(null);
        beginOrder.setProducts(null);
        beginOrder.setQuantity(1L);
        beginOrder.setCreatedDate("20231125");
        beginOrder.setUpdateDate("20231125");

        BeginOrder savedBeginOrder = beginOrderRepository.save(beginOrder);

        Optional<BeginOrder> foundBeginOrder= beginOrderRepository.findById(savedBeginOrder.getId());
        assertTrue(foundBeginOrder.isPresent());
        assertEquals("test", foundBeginOrder.get().getPicture());
    }

    @Test
    public void update() {
        BeginOrder beginOrder=new BeginOrder();
        beginOrder.setPicture("test");
        beginOrder.setOrders(null);
        beginOrder.setProducts(null);
        beginOrder.setQuantity(1L);
        beginOrder.setCreatedDate("20231125");
        beginOrder.setUpdateDate("20231125");

        BeginOrder savedBeginOrder = beginOrderRepository.save(beginOrder);

        BeginOrder beginOrderToUpdate = beginOrderRepository.findById(savedBeginOrder.getId()).get();
        beginOrderToUpdate.setPicture("update test");
        beginOrderRepository.save(beginOrderToUpdate);

        Optional<BeginOrder> updatedBeginOrder = beginOrderRepository.findById(savedBeginOrder.getId());
        assertTrue(updatedBeginOrder.isPresent());
        assertEquals("update test", updatedBeginOrder.get().getPicture());
    }

    @Test
    public void deleteAll() {
        BeginOrder beginOrder=new BeginOrder();
        beginOrder.setPicture("test");
        beginOrder.setOrders(null);
        beginOrder.setProducts(null);
        beginOrder.setQuantity(1L);
        beginOrder.setCreatedDate("20231125");
        beginOrder.setUpdateDate("20231125");

        BeginOrder savedBeginOrder = beginOrderRepository.save(beginOrder);
        beginOrderRepository.deleteAll();
        List<BeginOrder> beginOrderes = beginOrderRepository.findAll();
        assertTrue(beginOrderes.isEmpty());
    }
}

 

BasketsRepositoryTest

package kr.co.kshproject.webDemo.Domain.Baskets;

import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest;

import java.util.List;
import java.util.Optional;

import static org.junit.jupiter.api.Assertions.*;

@DataJpaTest
class BasketsRepositoryTest {
    @Autowired
    private BasketsRepository basketsRepository;

    @BeforeEach
    void before(){

    }

    @AfterEach
    void after() {
        // 테스트 데이터 정리
        basketsRepository.deleteAll();
    }

    @Test
    public void save() {
        Baskets basket=new Baskets();
        basket.setProductName("test");
        basket.setQuantity(1L);
        basket.setProductStatus("T");
        basket.setProducts(null);
        basket.setUsers(null);
        basket.setCreateDate("20231125");
        basket.setUpdateDate("20231125");

        Baskets savedBasket = basketsRepository.save(basket);
        Optional<Baskets> foundBBasket= basketsRepository.findById(savedBasket.getId());

        assertTrue(foundBBasket.isPresent());
        assertEquals("test", foundBBasket.get().getProductName());
    }

    @Test
    public void findAll() {
        Baskets basket=new Baskets();
        basket.setProductName("test");
        basket.setQuantity(1L);
        basket.setProductStatus("T");
        basket.setProducts(null);
        basket.setUsers(null);
        basket.setCreateDate("20231125");
        basket.setUpdateDate("20231125");

        Baskets savedBasket = basketsRepository.save(basket);

        List<Baskets> baskets  = basketsRepository.findAll();
        assertFalse(baskets.isEmpty());
    }

    @Test
    public void findById() {
        Baskets basket=new Baskets();
        basket.setProductName("test");
        basket.setQuantity(1L);
        basket.setProductStatus("T");
        basket.setProducts(null);
        basket.setUsers(null);
        basket.setCreateDate("20231125");
        basket.setUpdateDate("20231125");

        Baskets savedBasket = basketsRepository.save(basket);

        Optional<Baskets> foundBasket= basketsRepository.findById(savedBasket.getId());
        assertTrue(foundBasket.isPresent());
        assertEquals("test", foundBasket.get().getProductName());
    }

    @Test
    public void update() {
        Baskets basket=new Baskets();
        basket.setProductName("test");
        basket.setQuantity(1L);
        basket.setProductStatus("T");
        basket.setProducts(null);
        basket.setUsers(null);
        basket.setCreateDate("20231125");
        basket.setUpdateDate("20231125");

        Baskets savedBasket = basketsRepository.save(basket);

        Baskets basketToUpdate = basketsRepository.findById(savedBasket.getId()).get();
        basketToUpdate.setProductName("update test");
        basketsRepository.save(basketToUpdate);

        Optional<Baskets> updatedBaskets = basketsRepository.findById(savedBasket.getId());
        assertTrue(updatedBaskets.isPresent());
        assertEquals("update test", updatedBaskets.get().getProductName());
    }

    @Test
    public void deleteAll() {
        Baskets basket=new Baskets();
        basket.setProductName("test");
        basket.setQuantity(1L);
        basket.setProductStatus("T");
        basket.setProducts(null);
        basket.setUsers(null);
        basket.setCreateDate("20231125");
        basket.setUpdateDate("20231125");

        Baskets savedBasket = basketsRepository.save(basket);
        basketsRepository.deleteAll();
        List<Baskets> beginBaskets = basketsRepository.findAll();
        assertTrue(beginBaskets.isEmpty());
    }
}

테이블을 이번에 전부 변경했습니다. 

https://www.erdcloud.com/d/TBkodsGPbZev8sBXs

 

백엔드

Draw ERD with your team members. All states are shared in real time. And it's FREE. Database modeling tool.

www.erdcloud.com

 

users

package kr.co.kshproject.webDemo.Domain.Users;

import com.fasterxml.jackson.annotation.JsonManagedReference;
import kr.co.kshproject.webDemo.Domain.Baskets.Baskets;
import kr.co.kshproject.webDemo.Domain.Comment.Comment;
import kr.co.kshproject.webDemo.Domain.Notice.Notice;
import kr.co.kshproject.webDemo.Domain.Orders.Orders;
import lombok.*;

import javax.persistence.*;
import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.NotNull;
import java.util.ArrayList;
import java.util.List;

@Entity
@Getter
@Table(name = "users")
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class Users {

    @Id
    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "USERS_SEQ")
    @SequenceGenerator(name = "USERS_SEQ", sequenceName = "USERS_SEQ", allocationSize = 1)
    @Column(name = "ID")
    private Long id; //key

    @NotEmpty
    @Column(name = "username")
    @Setter
    private String username; //사용자 아이디

    @NotEmpty
    @Setter
    private String email; //이메일

    @NotEmpty
    @Setter
    private String name; //사용자 이름

    @NotNull
    @Setter
    private Long level; // 계정권한 레벨

    @Setter
    private String password;

    @JsonManagedReference
    @OneToMany(mappedBy = "users", cascade = CascadeType.ALL, fetch = FetchType.LAZY)
    private List<Comment> comments = new ArrayList<>();

    @JsonManagedReference
    @OneToMany(mappedBy = "users", cascade = CascadeType.ALL, fetch = FetchType.LAZY)
    private List<Notice> notices = new ArrayList<>();

    @JsonManagedReference
    @OneToMany(mappedBy = "users", cascade = CascadeType.ALL, fetch = FetchType.LAZY)
    private List<Baskets> baskets = new ArrayList<>();

    @JsonManagedReference
    @OneToMany(mappedBy = "users", cascade = CascadeType.ALL, fetch = FetchType.LAZY)
    private List<Orders> orders = new ArrayList<>();
}

notice

package kr.co.kshproject.webDemo.Domain.Notice;

import com.fasterxml.jackson.annotation.JsonBackReference;
import com.fasterxml.jackson.annotation.JsonManagedReference;
import kr.co.kshproject.webDemo.Domain.Comment.Comment;
import kr.co.kshproject.webDemo.Domain.Users.Users;
import lombok.*;

import javax.persistence.*;
import javax.validation.constraints.NotEmpty;
import java.util.ArrayList;
import java.util.List;

@Entity
@Table(name = "Notice")
@Builder
@NoArgsConstructor
@AllArgsConstructor
@Data
public class Notice {
    @Id
    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "NOTICE_SEQ")
    @SequenceGenerator(name = "NOTICE_SEQ", sequenceName = "NOTICE_SEQ", allocationSize = 1)
    @Column(name = "ID")
    private Long id; //key

    @NotEmpty
    @Setter
    private String username;

    @NotEmpty
    @Setter
    private String title;

    @NotEmpty
    @Setter
    private String contents;

    @NotEmpty
    @Setter
    private String email;

    @NotEmpty
    @Setter
    @Column(name = "created_date")
    private String createdDate;

    @JsonBackReference
    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name="user_id")
    @Setter
    private Users users;

    @JsonManagedReference
    @OneToMany(mappedBy = "notice", cascade = CascadeType.ALL, fetch = FetchType.LAZY)
    private List<Comment> comments = new ArrayList<>();
}

comments

package kr.co.kshproject.webDemo.Domain.Comment;

import com.fasterxml.jackson.annotation.JsonBackReference;
import kr.co.kshproject.webDemo.Domain.Notice.Notice;
import kr.co.kshproject.webDemo.Domain.Users.Users;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.Setter;

import javax.persistence.*;
import javax.validation.constraints.NotEmpty;

@Entity
@Table(name = "Comment")
@NoArgsConstructor
@AllArgsConstructor
@Data
public class Comment {

    @Id
    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "COMMENT_SEQ")
    @SequenceGenerator(name = "COMMENT_SEQ", sequenceName = "COMMENT_SEQ", allocationSize = 1)
    private Long id;

    @JsonBackReference
    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name="notice_id")
    @Setter
    private Notice notice;

    @JsonBackReference
    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name="user_id")
    @Setter
    private Users users;

    @NotEmpty
    @Setter
    private String userName;

    @NotEmpty
    @Setter
    private String contents;

    @NotEmpty
    @Setter
    @Column(name = "created_date")
    private String createdDate;
}

products

package kr.co.kshproject.webDemo.Domain.Products;

import com.fasterxml.jackson.annotation.JsonBackReference;
import com.fasterxml.jackson.annotation.JsonManagedReference;
import kr.co.kshproject.webDemo.Domain.Baskets.Baskets;
import kr.co.kshproject.webDemo.Domain.BeginOrder.BeginOrder;
import kr.co.kshproject.webDemo.Domain.Category.Category;
import lombok.*;

import javax.persistence.*;
import javax.validation.constraints.NotEmpty;
import java.util.ArrayList;
import java.util.List;

@Entity
@Table(name = "Products")
@Builder
@NoArgsConstructor
@AllArgsConstructor
@Data
public class Products {
    @Id
    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "PRODUCT_SEQ")
    @SequenceGenerator(name = "PRODUCT_SEQ", sequenceName = "PRODUCT_SEQ", allocationSize = 1)
    @Column(name = "ID")
    private Long id; //key

    @NotEmpty
    @Setter
    private String productName;

    @NotEmpty
    @Setter
    private String describe;

    @NotEmpty
    @Setter
    private Long price;

    @NotEmpty
    @Setter
    private String picture;

    @NotEmpty
    @Setter
    @Column(name = "sold_out")
    private boolean soldOut;

    @NotEmpty
    @Setter
    @Column(name = "created_date")
    private String createdDate;

    @NotEmpty
    @Setter
    @Column(name = "update_date")
    private String updateDate;

    @JsonBackReference
    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name="category_id")
    @Setter
    private Category category;

    @JsonManagedReference
    @OneToMany(mappedBy = "products", cascade = CascadeType.ALL, fetch = FetchType.LAZY)
    private List<Baskets> baskets = new ArrayList<>();

    @JsonManagedReference
    @OneToMany(mappedBy = "products", cascade = CascadeType.ALL, fetch = FetchType.LAZY)
    private List<BeginOrder> beginOrders = new ArrayList<>();
}

orders

package kr.co.kshproject.webDemo.Domain.Orders;

import com.fasterxml.jackson.annotation.JsonBackReference;
import com.fasterxml.jackson.annotation.JsonManagedReference;
import kr.co.kshproject.webDemo.Domain.BeginOrder.BeginOrder;
import kr.co.kshproject.webDemo.Domain.Users.Users;
import lombok.*;

import javax.persistence.*;
import javax.validation.constraints.NotEmpty;
import java.util.ArrayList;
import java.util.List;

@Entity
@Table(name = "Orders")
@Builder
@NoArgsConstructor
@AllArgsConstructor
@Data
public class Orders {
    @Id
    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "PRODUCT_SEQ")
    @SequenceGenerator(name = "PRODUCT_SEQ", sequenceName = "PRODUCT_SEQ", allocationSize = 1)
    @Column(name = "ID")
    private Long id; //key

    @NotEmpty
    @Setter
    private String payment;

    @NotEmpty
    @Setter
    private String status;

    @NotEmpty
    @Setter
    private Long price;

    @NotEmpty
    @Setter
    private boolean cancel;

    @NotEmpty
    @Setter
    @Column(name = "created_date")
    private String createdDate;

    @NotEmpty
    @Setter
    @Column(name = "update_date")
    private String updateDate;

    @JsonBackReference
    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name="user_id")
    @Setter
    private Users users;

    @JsonManagedReference
    @OneToMany(mappedBy = "orders", cascade = CascadeType.ALL, fetch = FetchType.LAZY)
    private List<BeginOrder> beginOrders = new ArrayList<>();

}

beginorders

package kr.co.kshproject.webDemo.Domain.BeginOrder;

import com.fasterxml.jackson.annotation.JsonBackReference;
import kr.co.kshproject.webDemo.Domain.Orders.Orders;
import kr.co.kshproject.webDemo.Domain.Products.Products;
import lombok.*;

import javax.persistence.*;
import javax.validation.constraints.NotEmpty;

@Entity
@Table(name = "BeginOrder")
@Builder
@NoArgsConstructor
@AllArgsConstructor
@Data
public class BeginOrder {
    @Id
    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "BEGINORDER_SEQ")
    @SequenceGenerator(name = "BEGINORDER_SEQ", sequenceName = "BEGINORDER_SEQ", allocationSize = 1)
    @Column(name = "ID")
    private Long id; //key

    //프로덕트  ID
    @JsonBackReference
    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name="product_id")
    @Setter
    private Products products;
    //주문 ID
    @JsonBackReference
    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name="order_id")
    @Setter
    private Orders orders;

    @NotEmpty
    @Setter
    private Long quantity;

    @NotEmpty
    @Setter
    private String picture;

    @NotEmpty
    @Setter
    @Column(name = "created_date")
    private String createdDate;

    @NotEmpty
    @Setter
    @Column(name = "update_date")
    private String updateDate;
}

category

package kr.co.kshproject.webDemo.Domain.Category;

import com.fasterxml.jackson.annotation.JsonBackReference;
import com.fasterxml.jackson.annotation.JsonManagedReference;
import kr.co.kshproject.webDemo.Domain.Products.Products;
import lombok.*;

import javax.persistence.*;
import javax.validation.constraints.NotEmpty;
import java.util.ArrayList;
import java.util.List;

@Entity
@Table(name = "Category")
@Builder
@NoArgsConstructor
@AllArgsConstructor
@Data
public class Category {
    @Id
    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "CATEGORY_SEQ")
    @SequenceGenerator(name = "CATEGORY_SEQ", sequenceName = "CATEGORY_SEQ", allocationSize = 1)
    @Column(name = "ID")
    private Long id; //key

    @NotEmpty
    @Setter
    private String categoryName;

    @NotEmpty
    @Setter
    @Column(name = "created_date")
    private String createdDate;

    @NotEmpty
    @Setter
    @Column(name = "update_date")
    private String updateDate;

    @JsonBackReference
    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name="category_id")
    @Setter
    private Category parentCategory;

    @JsonManagedReference
    @OneToMany(mappedBy = "category", cascade = CascadeType.ALL, fetch = FetchType.LAZY)
    private List<Products> products = new ArrayList<>();

    @JsonManagedReference
    @OneToMany(mappedBy = "parentCategory", cascade = CascadeType.ALL, fetch = FetchType.LAZY)
    private List<Category> parentCategories = new ArrayList<>();
}

2023.11.12 - [웹/Spring vue 웹 개발] - spring vue 댓글 완료

 

spring vue 댓글 완료

2023.11.11 - [웹/Spring vue 웹 개발] - spring vue 댓글 05 spring vue 댓글 05 2023.11.11 - [웹/Spring vue 웹 개발] - spring vue 댓글04 spring vue 댓글04 2023.11.05 - [웹/Spring vue 웹 개발] - spring vue 댓글03 spring vue 댓글03 2023.

kwaksh2319.tistory.com

 

이번에 게시판과 댓글을 추가 하면서 몇가지 어드민쪽 코드도 수정중에 있습니다. 코드는 좀더 수정한후에 블로그에 넣어도록 하겠습니다. 

영상 :

 

 

ui는 조금 나중에 수정하겠습니다. 일단 댓글 수정,삭제 그리고 게시판들을 어드민에서 관리하도록 하고요.

그리고 어드민 코드 정리한후에 상품쪽이랑 장바구니 주문쪽 다시 작성해도록 하겠습니다.

사진:

댓글 controller

import kr.co.kshproject.webDemo.Applicaiton.Comment.CommentService;
import kr.co.kshproject.webDemo.Domain.Comment.Comment;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

import java.util.List;
import java.util.Optional;

@Slf4j
@RestController
@RequestMapping("/comment")
public class CommentController {
    private final CommentService commentService;

    @Autowired
    public CommentController(CommentService commentService){
        this.commentService=commentService;
    }

    @PostMapping("/{page}/{id}")
    public ResponseEntity<Comment> save(@PathVariable int page, @PathVariable Long id, @RequestBody Comment comment) {
        return ResponseEntity.ok(commentService.save(page,id,comment));
    }

    @GetMapping
    public ResponseEntity<List<Comment>> findAll(){
        return ResponseEntity.ok( commentService.findAll());
    }

    @GetMapping("/{id}")
    public Optional<Comment> findById(@PathVariable Long id){
        return commentService.findById(id);
    }

    @PutMapping("/{id}")
    public ResponseEntity<Comment> update(@PathVariable Long id, @RequestBody Comment comment){
        return ResponseEntity.ok(commentService.update(id,comment));
    }

    @DeleteMapping("/{id}")
    public ResponseEntity<?> deleteById(@PathVariable Long id) {
        commentService.deleteById(id);
        return ResponseEntity.noContent().build();
    }

    @DeleteMapping
    public void deleteAll(){
        commentService.deleteAll();
    }
}

서비스 

package kr.co.kshproject.webDemo.Applicaiton.Comment;

import kr.co.kshproject.webDemo.Domain.Comment.Comment;
import kr.co.kshproject.webDemo.Domain.Comment.CommentRepository;
import kr.co.kshproject.webDemo.Domain.Notice.Notice;
import kr.co.kshproject.webDemo.Domain.Notice.NoticeCustomRepository;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

import java.time.LocalDate;
import java.util.List;
import java.util.Optional;
@Slf4j
@Service
@AllArgsConstructor
public class CommentServiceImpl implements CommentService{
    private static final Logger logger = LoggerFactory.getLogger(CommentServiceImpl.class);
    private final CommentRepository commentRepository;
    private final NoticeCustomRepository noticeCustomRepository;

    @Override
    public Comment save(int page, Long noticeId, Comment comment) {
        LocalDate now = LocalDate.now();
        Optional<Notice> notice =noticeCustomRepository.findWithCommentsById(page,noticeId);
        Notice tmpNotice= notice.get();

        //TODO
        comment.setUserName("admin");// 유저변경할것
        comment.setNotice(tmpNotice);
        comment.setCreatedDate(now.toString());
        return commentRepository.save(comment);
    }

    @Override
    public List<Comment> findAll() {
        return commentRepository.findAll();
    }

    @Override
    public Optional<Comment> findById(Long id) {
        return commentRepository.findById(id);
    }

    @Override
    public Comment update(Long id, Comment saveComment) {
        Optional<Comment> findComment =commentRepository.findById(id);
        if(findComment.isPresent()==false){
            return null;
        }
        Comment comment=findComment.get();
        comment.setContents(saveComment.getContents());
        return commentRepository.save(comment);
    }

    @Override
    public void deleteById(Long id) {
        commentRepository.deleteById(id);
    }

    @Override
    public void deleteAll() {
        commentRepository.deleteAll();
    }
}

레파지토리

package kr.co.kshproject.webDemo.Domain.Comment;

import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;

@Repository
public interface CommentRepository extends JpaRepository<Comment,Long> {
}

DTO 

package kr.co.kshproject.webDemo.Domain.Comment;

import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;

@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
public class CommentDTO {
    private Long id;
    private Long noticeId; // 대신 Notice 엔티티의 ID를 저장
    private String userName;
    private String contents;
    private String createdDate;

    public CommentDTO(Comment comment) {
        this.id = comment.getId();
        this.noticeId = comment.getNotice().getId(); // Notice의 ID를 가져옵니다.
        this.userName = comment.getUserName();
        this.contents = comment.getContents();
        this.createdDate = comment.getCreatedDate();
    }
}

테이블

package kr.co.kshproject.webDemo.Domain.Comment;
import com.fasterxml.jackson.annotation.JsonBackReference;
import kr.co.kshproject.webDemo.Domain.Notice.Notice;
import lombok.*;
import javax.persistence.*;
import javax.validation.constraints.NotEmpty;

@Entity
@Table(name = "Comment")
@NoArgsConstructor
@AllArgsConstructor
@Data
public class Comment {

    @Id
    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "COMMENT_SEQ")
    @SequenceGenerator(name = "COMMENT_SEQ", sequenceName = "COMMENT_SEQ", allocationSize = 1)
    private Long id;

    @JsonBackReference
    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name="notice_id")
    @Setter
    private Notice notice;

    @NotEmpty
    @Setter
    private String userName;

    @NotEmpty
    @Setter
    private String contents;

    @NotEmpty
    @Setter
    @Column(name = "created_date")
    private String createdDate;
}

 

' > Spring vue 웹 개발' 카테고리의 다른 글

spring vue jpa repository 테스트코드  (1) 2023.11.26
spring vue entity 변경  (2) 2023.11.25
spring vue 댓글 완료  (0) 2023.11.12
spring vue 댓글 05  (1) 2023.11.11
spring vue 댓글04  (1) 2023.11.11

2023.11.11 - [웹/Spring vue 웹 개발] - spring vue 댓글 05

 

spring vue 댓글 05

2023.11.11 - [웹/Spring vue 웹 개발] - spring vue 댓글04 spring vue 댓글04 2023.11.05 - [웹/Spring vue 웹 개발] - spring vue 댓글03 spring vue 댓글03 2023.10.14 - [웹/Spring vue 웹 개발] - spring vue 댓글 02 spring vue 댓글 02이전

kwaksh2319.tistory.com

일단 게시판도 조금 수정해야하는 부분도 있어서 완료했고요. 댓글들도 전부 달리도록 하였습니다.

이제 세션추가랑 유저구분할수 있도록 할거고요. 음 먼저 관리자 페이지는 제가 지금 다시 개발중이라 일단 개발되는데로 운영서버에 올릴 예정입니다. 아직 운영서버에는 적용이 안되었습니다.

영상:

이미지:

 

코드:

게시판 컨트롤러

@Slf4j
@RestController
@RequestMapping("/notice")
public class NoticeController {
   private final NoticeService noticeService;

    @Autowired
    public NoticeController(NoticeService noticeService){
        this.noticeService=noticeService;
   }

   @PostMapping
   public ResponseEntity<Notice> save(@RequestBody Notice notice){
        return ResponseEntity.ok(noticeService.save(notice));
   }

    @GetMapping
    public ResponseEntity< Map<String,List> > findAll(){
        return ResponseEntity.ok( noticeService.findAllWithComments(1));
    }

   @GetMapping("/{page}")
    public ResponseEntity< Map<String,List> > findAll(@PathVariable int page){
        return ResponseEntity.ok( noticeService.findAllWithComments(page));
   }

   @GetMapping("/{page}/{id}")
   public ResponseEntity<Notice> findWithCommentsById(@PathVariable int page,@PathVariable Long id){
        Optional<Notice> notice=noticeService.findWithCommentsById(page,id);
        return ResponseEntity.ok( notice.get() );
   }

   @PutMapping("/{id}")
   public ResponseEntity<Notice> update(@PathVariable Long id, @RequestBody Notice notice){
       return ResponseEntity.ok(noticeService.update(id,notice));
   }

   @DeleteMapping
   public void deleteAll(){
        noticeService.deleteAll();
   }
}

게시판 서비스 

package kr.co.kshproject.webDemo.Applicaiton.Notice;

import kr.co.kshproject.webDemo.Domain.Notice.Notice;
import kr.co.kshproject.webDemo.Domain.Notice.NoticeCustomRepository;
import kr.co.kshproject.webDemo.Domain.Notice.NoticeRepository;
import lombok.extern.slf4j.Slf4j;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.time.LocalDate;
import java.util.List;
import java.util.Map;
import java.util.Optional;
@Slf4j
@Service
public class NoticeServiceImpl implements NoticeService {
    private static final Logger logger = LoggerFactory.getLogger(NoticeServiceImpl.class);

    private final NoticeRepository noticeRepository;

    private final NoticeCustomRepository noticeCustomRepository;

    @Autowired
    public NoticeServiceImpl(NoticeRepository noticeRepository,NoticeCustomRepository noticeCustomRepository){
        this.noticeRepository=noticeRepository;
        this.noticeCustomRepository=noticeCustomRepository;
    }

    @Override
    public Notice save(Notice notice) {
        LocalDate now = LocalDate.now();
        notice.setCreatedDate(now.toString());
        notice.setUsername("admin");
        return noticeRepository.save(notice);
    }
    
    @Override
    public List<Notice> findAll() {
        return noticeRepository.findAll();
    }

    @Override
    public Optional<Notice> findById(Long id) {
        return noticeRepository.findById(id);
    }

    @Override
    public Map<String,List> findAllWithComments(int page) {
        //admin get pagesize;
        int pageSize=10;
        return noticeCustomRepository.findAllWithComments(page,pageSize);
    }

    @Override
    public Optional<Notice> findWithCommentsById(int page,Long id) {
        Optional<Notice> result= noticeCustomRepository.findWithCommentsById(page,id);
        return result;
    }

    @Override
    public Notice update(Long id,Notice saveNotice) {
        Optional<Notice> findNotice = noticeRepository.findById(id);

        if(findNotice.isPresent()==false){
            return null;
        }

        Notice notice=findNotice.get();
        notice.setTitle(saveNotice.getTitle());
        notice.setContents(saveNotice.getContents());
        return noticeRepository.save(notice);
    }
    @Override
    public void deleteAll() {
        noticeRepository.deleteAll();
    }
}

게시판 레파지토리

import org.springframework.stereotype.Repository;

import javax.persistence.criteria.CriteriaBuilder;
import java.util.List;
import java.util.Map;
import java.util.Optional;

@Repository
public interface NoticeCustomRepository {
    public Map<String, List> findAllWithComments(int page, int pageSize);

     Long findAllCountNotice(CriteriaBuilder cb);
    Optional<Notice> findWithCommentsById(int page,Long id) ;
}

게시판 레파지토리

import lombok.extern.slf4j.Slf4j;

import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.TypedQuery;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.JoinType;
import javax.persistence.criteria.Root;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;

@Slf4j
public class NoticeRepositoryImpl implements NoticeCustomRepository {
    @PersistenceContext
    private EntityManager entityManager;

    @Override
    public Map<String,List> findAllWithComments(int page, int pageSize) {
        List<Long> totalSize =new LinkedList<>();
        Map<String,List> noticeDTOList=new ConcurrentHashMap<>();

        //Criteria API 사용
        CriteriaBuilder cb = entityManager.getCriteriaBuilder();
        //NoticeDTO <= Notice 커멘트 사용하지 않기 위함
        CriteriaQuery<NoticeDTO> cq = cb.createQuery(NoticeDTO.class);

        //from 절
        Root<Notice> notice = cq.from(Notice.class);
        //SELECT id,username,title,contents,email,createdDate FROM Notice LIMIT [pageSize] OFFSET (page-1) * [pageSize] ;
        cq.select(cb.construct(
                NoticeDTO.class,
                notice.get("id"),
                notice.get("username"),
                notice.get("title"),
                notice.get("contents"),
                notice.get("email"),
                notice.get("createdDate")
        ));
        //cq 쿼리 실행
        TypedQuery<NoticeDTO> query = entityManager.createQuery(cq);
        //게시판 총사이즈
        Long tSize=findAllCountNotice(cb);
        tSize=tSize/pageSize+1;
        totalSize.add(tSize);

        //cq 쿼리 실행 후 페이지 갯수만큼 불러오기
        query.setFirstResult( (page-1) *pageSize);
        query.setMaxResults(pageSize);

        //맵리스트 저장
        noticeDTOList.put("lists",query.getResultList());
        noticeDTOList.put("totalSize",totalSize);

        //결과값 리턴
        return noticeDTOList;
    }

    @Override
    public Long findAllCountNotice(CriteriaBuilder cb) {
        //게시판 총 카운트
        CriteriaQuery<Long> countQuery = cb.createQuery(Long.class);
        Root<Notice> countRoot = countQuery.from(Notice.class);
        countQuery.select(cb.count(countRoot));
        Long totalRecords = entityManager.createQuery(countQuery).getSingleResult();
        return totalRecords;
    }


    @Override
    public Optional<Notice> findWithCommentsById(int page,Long id)  {

        //Criteria API 사용
        CriteriaBuilder cb = entityManager.getCriteriaBuilder();
        //Notice 사용 이유는 댓글들을 불러오기때문
        CriteriaQuery<Notice> cq = cb.createQuery(Notice.class);

        /*select * from Notice LEFT JOIN Comments where id='id'*/
        //from Notice
        Root<Notice> notice = cq.from(Notice.class);
        //left join
        notice.fetch("comments", JoinType.LEFT);
        cq.where(cb.equal(notice.get("id"), id));
        //cq 쿼리 실행
        TypedQuery<Notice> query = entityManager.createQuery(cq);
        List<Notice> result = query.getResultList();
        //삼항 연산자 result 비엇을시 empty() 존재지 resutl 리턴
        return result.isEmpty() ? Optional.empty(): Optional.of(result.get(0));
    }
}

게시판 dto

import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;

@Getter
@Setter
@AllArgsConstructor
@NoArgsConstructor
public class NoticeDTO {
    private Long id;
    private String username;
    private String title;
    private String contents;
    private String email;
    private String createdDate;

    // Constructor that takes an entity Notice
    public NoticeDTO(Notice notice) {
        this.id = notice.getId();
        this.username = notice.getUsername();
        this.title = notice.getTitle();
        this.contents = notice.getContents();
        this.email = notice.getEmail();
        this.createdDate = notice.getCreatedDate();
    }
}

게시판 테이블

import com.fasterxml.jackson.annotation.JsonManagedReference;
import kr.co.kshproject.webDemo.Domain.Comment.Comment;
import lombok.*;

import javax.persistence.*;
import javax.validation.constraints.NotEmpty;
import java.util.ArrayList;
import java.util.List;

@Entity
@Table(name = "Notice")
@Builder
@NoArgsConstructor
@AllArgsConstructor
@Data
public class Notice {
    @Id
    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "NOTICE_SEQ")
    @SequenceGenerator(name = "NOTICE_SEQ", sequenceName = "NOTICE_SEQ", allocationSize = 1)
    @Column(name = "ID")
    private Long id; //key

    @NotEmpty
    @Setter
    private String username;

    @NotEmpty
    @Setter
    private String title;

    @NotEmpty
    @Setter
    private String contents;

    @NotEmpty
    @Setter
    private String email;

    @NotEmpty
    @Setter
    @Column(name = "created_date")
    private String createdDate;

    @JsonManagedReference
    @OneToMany(mappedBy = "notice", cascade = CascadeType.ALL, fetch = FetchType.LAZY)
    private List<Comment> comments = new ArrayList<>();
}

댓글 컨트롤러

import kr.co.kshproject.webDemo.Applicaiton.Comment.CommentService;
import kr.co.kshproject.webDemo.Domain.Comment.Comment;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

import java.util.List;
import java.util.Optional;

@Slf4j
@RestController
@RequestMapping("/comment")
public class CommentController {
    private final CommentService commentService;

    @Autowired
    public CommentController(CommentService commentService){
        this.commentService=commentService;
    }

    @PostMapping("/{page}/{id}")
    public ResponseEntity<Comment> save(@PathVariable int page, @PathVariable Long id, @RequestBody Comment comment) {
        return ResponseEntity.ok(commentService.save(page,id,comment));
    }

    @GetMapping
    public ResponseEntity<List<Comment>> findAll(){
        return ResponseEntity.ok( commentService.findAll());
    }

    @GetMapping("/{id}")
    public Optional<Comment> findById(@PathVariable Long id){
        return commentService.findById(id);
    }

    @PutMapping("/{id}")
    public ResponseEntity<Comment> update(@PathVariable Long id, @RequestBody Comment comment){
        return ResponseEntity.ok(commentService.update(id,comment));
    }

    @DeleteMapping
    public void deleteAll(){
        commentService.deleteAll();
    }
}

 

댓글 서비스

package kr.co.kshproject.webDemo.Applicaiton.Comment;

import kr.co.kshproject.webDemo.Domain.Comment.Comment;

import java.util.List;
import java.util.Optional;

public interface CommentService {
    Comment save(int page,Long noticeId,Comment comment);
    List<Comment> findAll();
    Optional<Comment> findById(Long id);
    Comment update(Long id,Comment saveComment);
    void deleteAll();
}
package kr.co.kshproject.webDemo.Applicaiton.Notice;

import kr.co.kshproject.webDemo.Domain.Notice.Notice;
import kr.co.kshproject.webDemo.Domain.Notice.NoticeCustomRepository;
import kr.co.kshproject.webDemo.Domain.Notice.NoticeRepository;
import lombok.extern.slf4j.Slf4j;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.time.LocalDate;
import java.util.List;
import java.util.Map;
import java.util.Optional;
@Slf4j
@Service
public class NoticeServiceImpl implements NoticeService {
    private static final Logger logger = LoggerFactory.getLogger(NoticeServiceImpl.class);

    private final NoticeRepository noticeRepository;

    private final NoticeCustomRepository noticeCustomRepository;

    @Autowired
    public NoticeServiceImpl(NoticeRepository noticeRepository,NoticeCustomRepository noticeCustomRepository){
        this.noticeRepository=noticeRepository;
        this.noticeCustomRepository=noticeCustomRepository;
    }

    @Override
    public Notice save(Notice notice) {
        LocalDate now = LocalDate.now();
        notice.setCreatedDate(now.toString());
        notice.setUsername("admin");
        return noticeRepository.save(notice);
    }

    @Override
    public List<Notice> findAll() {
        return noticeRepository.findAll();
    }

    @Override
    public Optional<Notice> findById(Long id) {
        return noticeRepository.findById(id);
    }

    @Override
    public Map<String,List> findAllWithComments(int page) {
        //admin get pagesize;
        int pageSize=10;
        return noticeCustomRepository.findAllWithComments(page,pageSize);
    }

    @Override
    public Optional<Notice> findWithCommentsById(int page,Long id) {
        Optional<Notice> result= noticeCustomRepository.findWithCommentsById(page,id);
        return result;
    }

    @Override
    public Notice update(Long id,Notice saveNotice) {
        Optional<Notice> findNotice = noticeRepository.findById(id);

        if(findNotice.isPresent()==false){
            return null;
        }

        Notice notice=findNotice.get();
        notice.setTitle(saveNotice.getTitle());
        notice.setContents(saveNotice.getContents());
        return noticeRepository.save(notice);
    }
    @Override
    public void deleteAll() {
        noticeRepository.deleteAll();
    }
}

댓글 레파지토리

package kr.co.kshproject.webDemo.Domain.Comment;

import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;

@Repository
public interface CommentRepository extends JpaRepository<Comment,Long> {
}

댓글 테이블

import com.fasterxml.jackson.annotation.JsonBackReference;
import kr.co.kshproject.webDemo.Domain.Notice.Notice;
import lombok.*;
import javax.persistence.*;
import javax.validation.constraints.NotEmpty;

@Entity
@Table(name = "Comment")
@NoArgsConstructor
@AllArgsConstructor
@Data
public class Comment {

    @Id
    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "COMMENT_SEQ")
    @SequenceGenerator(name = "COMMENT_SEQ", sequenceName = "COMMENT_SEQ", allocationSize = 1)
    private Long id;

    @JsonBackReference
    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name="notice_id")
    @Setter
    private Notice notice;

    @NotEmpty
    @Setter
    private String userName;

    @NotEmpty
    @Setter
    private String contents;

    @NotEmpty
    @Setter
    @Column(name = "created_date")
    private String createdDate;
}

' > Spring vue 웹 개발' 카테고리의 다른 글

spring vue entity 변경  (2) 2023.11.25
spring vue 어드민 리팩토링01  (0) 2023.11.18
spring vue 댓글 05  (1) 2023.11.11
spring vue 댓글04  (1) 2023.11.11
spring vue 댓글03  (0) 2023.11.05

2023.11.11 - [웹/Spring vue 웹 개발] - spring vue 댓글04

 

spring vue 댓글04

2023.11.05 - [웹/Spring vue 웹 개발] - spring vue 댓글03 spring vue 댓글03 2023.10.14 - [웹/Spring vue 웹 개발] - spring vue 댓글 02 spring vue 댓글 02이전에 이어서 service랑 controller를 작성을 전부 완료하였고 테스트

kwaksh2319.tistory.com

기존에 좀 많이 힘들었던 부분이 제법있었습니다. 

먼저 

hibernate.HibernateException: collection was evicted

이 문제가 발생했었는데요. 

이 코드에서의 문제가 발생했었습니다. 

@Override
    public Optional<Notice> findWithCommentsById(Long id)  {
        //Criteria API 사용
        CriteriaBuilder cb = entityManager.getCriteriaBuilder();
        //Notice 사용 이유는 댓글들을 불러오기때문
        CriteriaQuery<Notice> cq = cb.createQuery(Notice.class);

        /*select * from Notice LEFT JOIN Comments where id='id'*/
        //from Notice
        Root<Notice> notice = cq.from(Notice.class);
        //left join
        notice.fetch("comments", JoinType.LEFT);
        cq.where(cb.equal(notice.get("id"), id));
        //cq 쿼리 실행
        TypedQuery<Notice> query = entityManager.createQuery(cq);
        List<Notice> result = query.getResultList();
        //삼항 연산자 result 비엇을시 empty() 존재지 resutl 리턴
        return result.isEmpty() ? Optional.empty(): Optional.of(result.get(0));
    }
TypedQuery<Notice> query = entityManager.createQuery(cq);

 이 쿼리 실행문에서 발생했었는데 알고보니 제가 이전에

@JsonManagedReference
@OneToMany(mappedBy = "notice", cascade = CascadeType.ALL, fetch = FetchType.LAZY)
private Set<Comment> comments = new HashSet<>();

해쉬셋으로 댓글을 가져왔었습니다.

이것저것 찾아보다가 

https://stackoverflow.com/questions/65058723/hibernateexception-in-hashcode-or-in-equals

 

HibernateException in hashCode or in equals

I am using spring and hibernate. When fetching without having implemented equals and hashCode, everyting works fine. When I add the two methods and execute the query a Lazyinitializationexception is

stackoverflow.com

글을 빌리자면 

  • 컬렉션 로딩: Hibernate는 Company 엔티티의 garages와 같은 내부 컬렉션을 로딩해야 할 필요가 있습니다.
  • 해시 코드 호출 시점: Company의 hashCode 메소드가 호출되는 시점에서 Hibernate는 아직 내부 컬렉션을 로딩하지 않았습니다. 이는 HashSet 내부에서 Hibernate의 내부 코드에 의해 발생합니다.
  • 내부 혼란: 컬렉션이 로딩되어야 한다는 요청은 있었지만, 실제로 아직 로딩되지 않았기 때문에 Hibernate는 혼란스러워합니다.

이런 문제가 발생한다고 하여서 

@JsonManagedReference
@OneToMany(mappedBy = "notice", cascade = CascadeType.ALL, fetch = FetchType.LAZY)
private List<Comment> comments = new ArrayList<>();

리스트로 바꿔서 해결했습니다.

ㅠㅠㅠㅠㅠ 

그리고 나서 또 문제가 발생했습니다. 

HttpMessageNotWritableException

위에처럼 messageNotWritabelException이 발생햇는데 

다행히도 이문제는

@JsonManagedReference
@JsonBackReference

으로 해결할수 있었습니다. 

무슨 문제이길래 이 어노테이션으로 해결한걸까요? 다음과 같습니다.

@JsonManagedReference와 @JsonBackReference

이 두 어노테이션은 순환 참조 문제를 해결하는 데 사용됩니다. 순환 참조는 JSON 직렬화 과정에서 무한 루프를 발생시킬 수 있으며, 이를 방지하기 위해 이 어노테이션이 필요합니다.

  • @JsonManagedReference: '부모' 측에 사용되며, 직렬화 과정에서 이 어노테이션이 적용된 필드를 포함시킵니다.
  • @JsonBackReference: '자식' 측에 사용되며, 직렬화 과정에서 이 어노테이션이 적용된 필드를 제외합니다. 이 어노테이션은 역직렬화 과정에서는 유효합니다.

결론적으론 JSON 직렬화 과정에서 무한 루프를 방지하기 위함인데  JSON 직렬화 과정에서 무한 루프는 왜 일어날까요?

 

JSON 직렬화 과정에서 무한 루프가 발생하는 주된 이유는 "순환 참조" 때문입니다. 순환 참조는 객체가 직접적이거나 간접적으로 자기 자신을 참조할 때 발생합니다. 예를 들어, 두 객체가 서로를 참조하거나, 객체가 자신을 포함하는 컬렉션을 참조하는 경우가 있습니다.  

 

순환참조로 인한 무한루프가 발생할수 있다고해서 이를 방지하기 위함이라고 합니다. 음 쉽게 설명해서 양방향으로 서로 참조하는걸 단방향으로 바꿔주는 셈이죠 (제가 이해한건 이거인데 틀리면 지적부탁드립니다.)

 

그래서 댓글을 넣고 게시판을 확인해봤습니다. 아직 vue는 개발이 덜 되어서 postman으로 확인해봤습니다. 

결과 화면 :

잘 나왔죠! 내일은 vue쪽도 만들어서 댓글도 보이도록 해보겠습니다. 시간이 나오려나 모르겠네요 ㅎㅎ ㅠ 

' > Spring vue 웹 개발' 카테고리의 다른 글

spring vue 어드민 리팩토링01  (0) 2023.11.18
spring vue 댓글 완료  (0) 2023.11.12
spring vue 댓글04  (1) 2023.11.11
spring vue 댓글03  (0) 2023.11.05
spring vue 댓글 02  (0) 2023.10.14

2023.11.05 - [웹/Spring vue 웹 개발] - spring vue 댓글03

 

spring vue 댓글03

2023.10.14 - [웹/Spring vue 웹 개발] - spring vue 댓글 02 spring vue 댓글 02이전에 이어서 service랑 controller를 작성을 전부 완료하였고 테스트도 완료하였습니다. 내일은 프론트단을 완료하고 현재 pc내에서

kwaksh2319.tistory.com

먼저 오늘 좀 여러가지 문제점발견하면서 해결을 했습니다.

먼저 기존에 말했던 @Transational방식이 아니라 DTO를 이용하여 댓글을 post 했습니다. 

NoticeDTO

@Getter
@Setter
@AllArgsConstructor
@NoArgsConstructor
public class NoticeDTO {
    private Long id;
    private String username;
    private String title;
    private String contents;
    private String email;
    private String createdDate;

    // Constructor that takes an entity Notice
    public NoticeDTO(Notice notice) {
        this.id = notice.getId();
        this.username = notice.getUsername();
        this.title = notice.getTitle();
        this.contents = notice.getContents();
        this.email = notice.getEmail();
        this.createdDate = notice.getCreatedDate();
    }
}

 


NoticeRepositoryImpl 

package kr.co.kshproject.webDemo.Domain.Notice;

import lombok.extern.slf4j.Slf4j;

import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.TypedQuery;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.JoinType;
import javax.persistence.criteria.Root;
import java.util.List;
import java.util.Optional;

@Slf4j
public class NoticeRepositoryImpl implements NoticeCustomRepository {
    @PersistenceContext
    private EntityManager entityManager;

    @Override
    public List<NoticeDTO> findAllWithComments() {
        //Criteria API 사용
        CriteriaBuilder cb = entityManager.getCriteriaBuilder();
        //NoticeDTO <= Notice 커멘트 사용하지 않기 위함
        CriteriaQuery<NoticeDTO> cq = cb.createQuery(NoticeDTO.class);

        //from 절
        Root<Notice> notice = cq.from(Notice.class);
        //선택 및 조건 설정 =>select id,username,title,contents,email,createdDate from notice;
        cq.select(cb.construct(
                NoticeDTO.class,
                notice.get("id"),
                notice.get("username"),
                notice.get("title"),
                notice.get("contents"),
                notice.get("email"),
                notice.get("createdDate")
        ));

        //cq 쿼리 실행
        TypedQuery<NoticeDTO> query = entityManager.createQuery(cq);
        //결과값 리턴
        return query.getResultList();
    }


    @Override
    public Optional<Notice> findWithCommentsById(Long id)  {
        //Criteria API 사용
        CriteriaBuilder cb = entityManager.getCriteriaBuilder();
        //Notice 사용 이유는 댓글들을 불러오기때문
        CriteriaQuery<Notice> cq = cb.createQuery(Notice.class);

        /*select * from Notice LEFT JOIN Comments where id='id'*/
        //from Notice
        Root<Notice> notice = cq.from(Notice.class);
        //left join
        notice.fetch("comments", JoinType.LEFT);
        cq.where(cb.equal(notice.get("id"), id));
        //cq 쿼리 실행
        TypedQuery<Notice> query = entityManager.createQuery(cq);
        List<Notice> result = query.getResultList();
        //삼항 연산자 result 비엇을시 empty() 존재지 resutl 리턴
        return result.isEmpty() ? Optional.empty(): Optional.of(result.get(0));
    }
}

여기서  아래 findAllwithCommets는 게시글 전부 불러오는거고요. 제가 선택한 방법은 Criterai api를 사용해서 쿼리문을 불어왔습니다 left join에 대해서 이해하셔야 아래 구문이 이해가 가십니다.  

@Override
public List<NoticeDTO> findAllWithComments() {
    //Criteria API 사용
    CriteriaBuilder cb = entityManager.getCriteriaBuilder();
    //NoticeDTO <= Notice 커멘트 사용하지 않기 위함
    CriteriaQuery<NoticeDTO> cq = cb.createQuery(NoticeDTO.class);

    //from 절
    Root<Notice> notice = cq.from(Notice.class);
    //선택 및 조건 설정 =>select id,username,title,contents,email,createdDate from notice;
    cq.select(cb.construct(
            NoticeDTO.class,
            notice.get("id"),
            notice.get("username"),
            notice.get("title"),
            notice.get("contents"),
            notice.get("email"),
            notice.get("createdDate")
    ));

    //cq 쿼리 실행
    TypedQuery<NoticeDTO> query = entityManager.createQuery(cq);
    //결과값 리턴
    return query.getResultList();
}

이런식으로 transactal query를 불러오지않고 불러오도록 하였습니다. 

결과 화면 : 

' > Spring vue 웹 개발' 카테고리의 다른 글

spring vue 댓글 완료  (0) 2023.11.12
spring vue 댓글 05  (1) 2023.11.11
spring vue 댓글03  (0) 2023.11.05
spring vue 댓글 02  (0) 2023.10.14
spring vue 댓글 01  (1) 2023.10.09

2023.10.14 - [웹/Spring vue 웹 개발] - spring vue 댓글 02

spring vue 댓글 02

이전에 이어서 service랑 controller를 작성을 전부 완료하였고 테스트도 완료하였습니다. 내일은 프론트단을 완료하고 현재 pc내에서 웹 작동해볼 예정이고 운영웹에는 테스트 조금더 한후에 적용

kwaksh2319.tistory.com

10월 중순부터 11월 아마 중순까지는 주말마다  바쁘기도 했고 주말마다 좀 바쁠 예정입니다. 아마 12월 넘어가야 여유가 생길듯합니다. 일단 그래도 틈틈히 시간나면 개발하겠습니다. 요즘 알고리즘이 여러가지 복습을 하다보니 좀 늦어지네요.
 
일단 게시판불러오면서 댓글들도 불러오는게 문제여서 몇가지를 수정했습니다.
 

Resolved [org.springframework.http.converter.HttpMessageNotWritableException: 
Could not write JSON: failed to lazily initialize a collection of role:
kr.co.kshproject.webDemo.Domain.Notice.Notice.comments,
could not initialize proxy - no Session; nested exception is com.fasterxml.
jackson.databind.JsonMappingException: failed to lazily initialize a collection of role: 
kr.co.kshproject.webDemo.Domain.Notice.Notice.comments, 
could not initialize proxy 
- no Session (through reference chain: java.util.ArrayList[0]-
>kr.co.kshproject.webDemo.Domain.Notice.Notice["comments"])]

 
원인은 아래와 LazyInitializationException 오류 메시지는 Hibernate 세션이 닫혀있는 상태여서 그렇습니다.  lazy loading 으로 인한 문제라고합니다.
 Hibernate 세션이란?
https://www.tutorialspoint.com/hibernate/hibernate_sessions.htm

Hibernate - Sessions

Hibernate Sessions - A Session is used to get a physical connection with a database. The Session object is lightweight and designed to be instantiated each time an interaction is needed with the database. Persistent objects are saved and retrieved through

www.tutorialspoint.com

데이터베이스와 물리적으로 연결하는 데 사용됩니다. Session 개체는 가볍고 데이터베이스와의 상호 작용이 필요할 때마다 인스턴스화되도록 설계되었습니다. 영구 객체는 Session 객체를 통해 저장되고 검색이라고 하는데. 제가 이해한건 그냥 로그인이나 원격 같은데 접속할떄 그 세션과 동일하게 db 세션객체에 접근해서 crud를 해줄수 있는게 아닐까 생각합니다.
 제가 생각한게 맞은게아니라면 잘못된거면 지적 부탁드리겠습니다.
 
lazy loading 이란?
즉, 사용자가 보지 않는 것들을 당장 로딩하지 않는다.
그러다가 나중에 사용자가 필요로 하는 시점에 로딩하는 것입니다.
https://ko.wikipedia.org/wiki/%EC%A7%80%EC%97%B0%EB%90%9C_%EB%A1%9C%EB%94%A9

FetchType.LAZY
@OneToMany(mappedBy = "notice", cascade = CascadeType.ALL, fetch = FetchType.LAZY)
    private List<Comment> comments = new ArrayList<>();

그래서 일단 transcationl(readyOnly=true) 접근하여 해결하였습니다.
여러가지 방법이 있는데 
다음에는 DTO방식으로 접근하는걸로 수정해보도록 하겠습니다. 
그리고 다른방식으로는 osiv도 있는데요 이것도 잠재적 위험성을 가지고 있다고합니다.
https://medium.com/frientrip/spring-boot%EC%9D%98-open-in-view-%EA%B7%B8-%EC%9C%84%ED%97%98%EC%84%B1%EC%97%90-%EB%8C%80%ED%95%98%EC%97%AC-83483a03e5dc

Spring Boot의 open-in-view, 그 위험성에 대하여.

실제 서버 장애 해결과정을 중심으로

medium.com

 

spring.jpa.open-in-view = false

링크글을 빌리면 저도 비슷하게 db connection deadlock을 걸려본적이있는데 당시에는 제가 enitiyManger.close를 하지않아 발생한거였습니다. 반대로 이글을 빌리자면 opiv 을 true로 변경시 문제가 발생할수 있다고합니다. 와 무섭네요...
아무튼 lazy-loading을 해결하기위해 여러가지 방법이 있긴하지만 그중에서 가장 좋은 방향으로 선택하는게 좋겠네요 
  
서비스 

@Transactional(readOnly = true)
@Override
public List<Notice> findAllWithComments() {
      return noticeRepository.findAllWithComments();
}

컨트롤러 

@GetMapping
 public ResponseEntity<List<Notice>> findAll(){
      return ResponseEntity.ok( noticeService.findAllWithComments());
}

이렇게 하니 문제없이 잘 되었습니다. 
성공화면 : 

 

' > Spring vue 웹 개발' 카테고리의 다른 글

spring vue 댓글 05  (1) 2023.11.11
spring vue 댓글04  (1) 2023.11.11
spring vue 댓글 02  (0) 2023.10.14
spring vue 댓글 01  (1) 2023.10.09
spring vue 게시판 리팩토링 완료 (프론트단 및 백단 연결 변경 완료)  (0) 2023.10.08

+ Recent posts