InvalidDataAccessApiUsageException: org.hibernate.QueryException: could not instantiate class

 

아....참 ㅋㅋ 

이것때문에 어제 1시간을 봣는데 

https://stackoverflow.com/questions/40960093/spring-data-jpa-could-not-instantiate-class

 

Spring Data JPA could not instantiate class

I have problem with my code. I paste below my DAO interface: public interface EventDao extends CrudRepository<Event, Integer>{ ... @Query("SELECT new com.patryk.entity.ActionStatistics(e.a...

stackoverflow.com

꼼꼼히 테이블 파라미터를 확인합시다.

제 코드 변경점

private long userId; ->private Long userId;

2023.11.27 - [웹/Spring vue 웹 개발] - spring vue swagger 사용 및 controller,serivce 코드 완료

 

spring vue swagger 사용 및 controller,serivce 코드 완료

2023.11.26 - [웹/Spring vue 웹 개발] - spring vue jpa repository 테스트코드 spring vue jpa repository 테스트코드이전글: 2023.11.25 - [웹/Spring vue 웹 개발] - spring vue entity 변경 spring vue entity 변경 테이블을 이번에 전

kwaksh2319.tistory.com

 

이번주 이상하게 사적인 일들이 많다보니 공부를 조금 많이 못했습니다.

그래도 swagger에서 테스트 안되던 문제들은 해결했고요. 조만간 다른 컨트롤러들도 전부 변경 예정입니다. 현재는 usersController만 완료되었습니다.

지금 결과도 올바르게 나옵니다.

결과: 

 

추가된 내용 :

commonserivce

package kr.co.kshproject.webDemo.Common;

import org.springframework.stereotype.Service;

import javax.persistence.EntityManager;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Root;

@Service
public class CommonService {
    public <T> Long findAllCount(EntityManager entityManager ,CriteriaBuilder cb,Class<T> entityClass) {
        CriteriaQuery<Long> countQuery = cb.createQuery(Long.class);
        Root<T> root = countQuery.from(entityClass);
        countQuery.select(cb.count(root));
        return entityManager.createQuery(countQuery).getSingleResult();
    }
}

 

usersRepositoryImpl

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

import kr.co.kshproject.webDemo.Common.CommonService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;

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.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.concurrent.ConcurrentHashMap;

@Repository
public class UsersCustomRepositoryImpl implements UsersCustomRepository{
    @PersistenceContext
    private EntityManager entityManager;

    private final CommonService commonService;

    @Autowired
    public UsersCustomRepositoryImpl( CommonService commonService){
        this.commonService=commonService;
    }

    @Override
    public Optional<Users> findById(Long id) {
        CriteriaBuilder cb = entityManager.getCriteriaBuilder();
        //Notice 사용 이유는 댓글들을 불러오기때문
        CriteriaQuery<Users> cq = cb.createQuery(Users.class);
        Root<Users> user = cq.from(Users.class);
        user.fetch("comments", JoinType.LEFT);
        user.fetch("notices", JoinType.LEFT);
        user.fetch("baskets", JoinType.LEFT);
        user.fetch("orders", JoinType.LEFT);

        cq.where(cb.equal(user.get("id"), id));
        //cq 쿼리 실행
        TypedQuery<Users> query = entityManager.createQuery(cq);
        List<Users> result = query.getResultList();
        //삼항 연산자 result 비엇을시 empty() 존재지 resutl 리턴
        return result.isEmpty() ? Optional.empty(): Optional.of(result.get(0));
    }

    @Override
    public List<UsersDTO> findAllDto() {
        CriteriaBuilder cb = entityManager.getCriteriaBuilder();
        CriteriaQuery<UsersDTO> cq = cb.createQuery(UsersDTO.class);
        Root<Users> user = cq.from(Users.class);
        cq.select(cb.construct(
                UsersDTO.class,
                user.get("id"),
                user.get("username"),
                user.get("email"),
                user.get("name"),
                user.get("level"),
                user.get("password")
        ));
        TypedQuery<UsersDTO> query = entityManager.createQuery(cq);

        return query.getResultList();
    }

    @Override
    public Map<String,List> findAll(int page, int size) {
        List<Long> totalSize =new LinkedList<>();
        Map<String,List> userDTOList=new ConcurrentHashMap<>();

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

        //from 절
        Root<Users> user = cq.from(Users.class);

        cq.select(cb.construct(
                UsersDTO.class,
                user.get("id"),
                user.get("username"),
                user.get("email"),
                user.get("name"),
                user.get("level"),
                user.get("password")
        ));
        //cq 쿼리 실행
        TypedQuery<UsersDTO> query = entityManager.createQuery(cq);
        //게시판 총사이즈
        Long tSize=commonService.findAllCount(entityManager,cb,Users.class);
        tSize=tSize/size+1;
        totalSize.add(tSize);

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

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

        //결과값 리턴
        return userDTOList;
    }
}

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.24 - [웹/Spring] - Spring Security 구조에 대해서 - 필터에 대해서

 

Spring Security 구조에 대해서 - 필터에 대해서

https://docs.spring.io/spring-security/reference/servlet/architecture.html#servlet-filterchainproxy Architecture :: Spring Security The Security Filters are inserted into the FilterChainProxy with the SecurityFilterChain API. Those filters can be used for

kwaksh2319.tistory.com

이전글을 이어서 작성하도록 하겠습니다. 

참조 원서:

https://docs.spring.io/spring-security/reference/servlet/architecture.html#servlet-filterchainproxy

 

Architecture :: Spring Security

The Security Filters are inserted into the FilterChainProxy with the SecurityFilterChain API. Those filters can be used for a number of different purposes, like authentication, authorization, exploit protection, and more. The filters are executed in a spec

docs.spring.io

DelegatingFilterProxy란?

스프링은 서블릿 컨테이너의 lifecycle와 스프링의 ApplicationContext 간의 연결을 가능하게 하는 DelegatingFilterProxy라는 필터 구현체를 제공합니다.

서블릿 컨테이너는 자체 표준을 사용하여 filter 인스턴스를 등록할 수 있지만, 스프링에서 정의된 빈(Bean)에 대해서는 인지하지 못합니다.

서블릿 컨테이너 원리을 통해 DelegatingFilterProxy를 등록할 수 있지만, 모든 작업을 filter를 구현한 스프링 bean에 위임합니다.

 

해석하면 위와같은데 내용이 참 어렵죠. 그래서 좀더 자세히 설명하기전에 간단히 개념부터 보겠습니다.

여기서  ApplicationContext 란?

https://velog.io/@choidongkuen/Spring-Application-Context-%EB%9E%80

 

[Spring] Application Context 란?

업로드중..

velog.io

간단히 말해서 스프링의 컨테이너인데

토비스프링 3.1에서  page 95 쯤에   ApplicationContextbean factory랑 비슷하다고 생각하라고 합니다. 동일시한다 라고 써잇더라고요.

원래는 토비스프링 3.1에서도 말하지만 bean factory보다는 좀더 확장된 개념이 ApplicationContext이다라고 합니다

아무튼 어떤 기능에 대한 확장이니까 bean 객체들을 관리하는 IOC엔진이라고 생각하면 편합니다.

 

여기서 초보자 분들은 

IOC는 역전 제어가 뭐지?라고 할수있습니다. 간단히 설명하면 IOC는 spring framework에  의존하는 방식이라 생각하면 좀 편합니다. 뭐 간단히 객체 생성같은거를 개발자가 아니라 framework가 대신해주는거죠! (말그대로 자동화!, 사람의 실수를 줄이는 거죠! 항상 개발자는 사람은 실수한다는 마음으로 개발해야 자동화를 하려고 노력하는것 같아요!)

.

이번엔 서블릿 컨테이너는 이전링크에서말했던 서블릿을 관리하는 컨테이너 겠죠

정의는 서블릿 컨테이너(Servlet Container)는 자바 웹 애플리케이션에서 중요한 역할을 하는 구성 요소입니다. 자바 서블릿을 실행하는 환경을 제공하며, 웹 서버와 함께 동작하여 HTTP 요청과 응답을 처리하는 역할입니다.

 

아래는 filter chain과 filter 인스턴스안에 DelegatingFilterProxy의 모습입니다.

 

 

 

DelegatingFilterProxy는 Bean Filter0 가 호출될때 ApplicationContext의 Bean Filter0에서 나타납니다. 아래 간단히 코드를 확인해보죠

 

public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) {
	Filter delegate = getFilterBean(someBeanName); //1
	delegate.doFilter(request, response);  //2
}

여기서 1 번코드를 보면요

Filter delegate = getFilterBean(someBeanName); //1

여기서 스피링 빈에 등록된 필터는 lazily 하게 가져옵니다.(spring에서 lazy는 직접적 호출하기전까지는 생성및 초기화를 하지 않는다! 라고는걸로 있습니다. 즉 lazy 에 대한 개념을 알고가면 좋습니다.)

예를들어 DelegatingFilterProxy에서의 delegate 는 bean filter0의 instacne입니다.

 

여기서 delegate란?

일반적으로 객체가 특정 작업을 다른 객체에 위임하는 개념입니다. 즉 여기서 말하고자 하는것은 bean filter0가  DelegatingFilterProxy다 라고 생각하면 좋을듯합니다 ( 제가 틀렷다면 지적부탁드리겠습니다 제가 이해한건 이거입니다 )

 

여기서 2번 코드를 보면요

delegate.doFilter(request, response);  //2

Spring bean에서 delgate 작업을 한다라고 합니다. 즉  DelegatingFilterProxy가 작동합니다

 

원문을 해석하면 

마지막으로  DelegatingFilterProxy의 또 다른 장점은 Filter bean 인스턴스를 찾는 것을 지연시킬 수 있다는 것입니다. 이는 컨테이너가 시작되기 전에 Filter 인스턴스를 등록해야 하기 때문에 중요합니다. 그러나 Spring에서는 일반적으로 ContextLoaderListener를 사용하여 Spring Beans를 로드하는데, 이는 Filter 인스턴스가 등록되어야 할 시점 이후에야 완료됩니다.

 

말이 참 어렵죠.

먼저 ContextLoaderListener란?

주로 웹 기반의 Spring 애플리케이션에서 중요한 역할을 하며, 애플리케이션의 시작과 종료 시점에 각각 컨텍스트를 초기화하고 정리하는 역할을 합니다.( 즉 ApllicaitonContext를 초기화 및 종료 하는 역할 이라고 생각하면 편합니다.  일단 이것도 제가 생각한거라 틀릴수 잇습니다. 틀리면 지적부탁드립니다)

 

그렇다면 

쉽게 설명하자면  spring에서 spring filter 인스턴스가 등록되어야 할 시점 이후에 ApplicationContext에서 spring beans을 불러오는겁니다. 근데 어째서 DelegatingFilterProxy는 필터 인스턴스를 늦게 로드 시킬까요?

(이유는 성능 최적화에 있다고하는데  . 당연한 얘기겟지만 모든 컴포너트를 즉시 로딩하면 상당한 양의 메모리를 차지하기 때문에 이런방식을 택한것같습니다. 이건 제추측입니다. 이것도 틀리면 지적부탁드립니다 보통 lazy한 경우가 다 성능 최적화여서 ㅠㅠ )

다음엔 securityFilterChain에 대해서 정리해보겠습니다.

 

 

https://docs.spring.io/spring-security/reference/servlet/architecture.html#servlet-filterchainproxy

 

Architecture :: Spring Security

The Security Filters are inserted into the FilterChainProxy with the SecurityFilterChain API. Those filters can be used for a number of different purposes, like authentication, authorization, exploit protection, and more. The filters are executed in a spec

docs.spring.io

일단 스프링 시큐리에 구조에 대해서 알아보려 합니다.

사실상 기존에 사용만 해봤지 실제 구조가 어떻게 굴러가는지에 대해서는 정확하게 공부하지 않았습니다.(반성중..사실 좀 바빳다는게 핑계... ㅎㅎ)

 

좋은 기회여서 일단 원서를 보면서 구조를 파악 해보려 합니다 ㅎㅎ

최대한 자세히 설명하거여서 쉬운 용어들 조차 설명을 할거라 내용이 조금 길어질수도 있습니다. 고수님들께서는 다른거 참조하셔도 됩니다. (저같은 초보를 위한 초보자들을 위해서... ㅎㅎ)

 

필터(filter)에 대해서 

스프링 시큐리티의 서블릿 제공은 서블릿 필터에서 합니다!

 

여기서 서블릿이란? (모르는 분들을 위해서)

서블릿(Servlet)이란 동적 웹 페이지를 만들 때 사용되는 자바 기반의 웹 애플리케이션 프로그래밍 기술이다. 서블릿은 웹 요청과 응답의 흐름을 간단한 메서드 호출만으로 체계적으로 다룰 수 있게 해준다.(일단 spring mvc servlet에서는 DispatcherServlet 이어서 그건 아래에 설명하겠습니다.) 

https://ko.wikipedia.org/wiki/%EC%9E%90%EB%B0%94_%EC%84%9C%EB%B8%94%EB%A6%BF

 

자바 서블릿 - 위키백과, 우리 모두의 백과사전

위키백과, 우리 모두의 백과사전. 서블릿은 여기로 연결됩니다. 다른 뜻에 대해서는 서블렛 문서를 참고하십시오. JSP 파일의 수명. 자바 서블릿(Java Servlet)은 자바를 사용하여 웹페이지를 동적으

ko.wikipedia.org

 

자 그렇다면 이제 저희는 서블릿을 알고간거죠.

서블릿 필터는 일반적으로 필터의 역할을 보여주는데 도움을 준다고합니다.

아래 이미지는 single http request 다루는 일반적인 레이어입니다.

 

클라이언트에서 -> appliaciton으로 request를 보내면, URI Request 경로를 기반으로, HttpServletRequest 처리해야하는 filter 인스턴스와 서블릿을 포함하는  filterChain을 컨테이너에 생성합니다.

 

여기서 컨테이너란? (모르는 분들을 위해서)

https://ittrue.tistory.com/220

 

[Spring] 스프링 컨테이너(Spring Container)란 무엇인가?

본 내용은 온라인 강의 사이트 인프런의 김영한 님의 강의 내용이 포함되어 있습니다. '스프링 핵심 원리 - 기본편' 스프링 핵심 원리 - 기본편 - 인프런 | 강의 스프링 입문자가 예제를 만들어가

ittrue.tistory.com

스프링 컨테이너는 스프링 프레임워크의 핵심 컴포넌트이다.

스프링 컨테이너는 자바 객체의 생명 주기를 관리하며, 생성된 자바 객체들에게 추가적인 기능을 제공한다.

스프링에서는 자바 객체를 빈(Bean)이라 한다.



즉, 스프링 컨테이너는 내부에 존재하는 빈의 생명주기를 관리(빈의 생성, 관리, 제거 등)하며, 생성된 빈에게 추가적인 기능을 제공하는 것이다.



스프링 컨테이너는 XML, 어노테이션 기반의 자바 설정 클래스로 만들 수 있다.

스프링 부트(Spring Boot)를 사용하기 이전에는 xml을 통해 직접적으로 설정해 주어야 했지만, 스프링 부트가 등장하면서 대부분 사용하지 않게 되었다.

출처: https://ittrue.tistory.com/220 [IT is True:티스토리]

블로그 글을 빌리자면 스프링 자바 객체를 자동적으로 생명주기를 관리해주는곳이 컨테이너입니다.

그러니까 굳이 new 객체 생성하지 않아도 된다!! 이런 느낌입니다.

말그대로 filterChain도 스프링 컨테이너에 관리되는셈이죠!

 

여기서 또하나 URI와 URL이란? (모르는 분들을 위해서..저도 가끔 헷갈림 ㅎㅎ)

 

https://grape-blog.tistory.com/10

 

URI, URL 이란?

URI란 ? URI(Uniform Resource Identifier) 인터넷 자원을 나타내는 고유 식별자 이다. URI 에 "I" 가 Identifier인 것은 인터넷에 있는 자료의 ID를 뜻하는 것이다. 즉, 다른 자료가 똑같은 이름을 가지고 있으면

grape-blog.tistory.com

출처:https://grape-blog.tistory.com/10

위에 이미지를 보시면 확실하게 아시겠죠?

쉽게 설명해서 url은 도메인만 있는거, uri는 쿼리파라미터,패스,페이지 모든걸 포함하고 있다고 생각하면 편합니다. 

 

이 filterchain은 spring mvc application에 

당연아시겠지만 spring mvc 에서의 servlet은 DispatcherServlet입니다.

 

DispatcherServlet이란?

https://mangkyu.tistory.com/18

 

[Spring] Dispatcher-Servlet(디스패처 서블릿)이란? 디스패처 서블릿의 개념과 동작 과정

이번에는 servlet의 심화 또는 대표주자인 dispatcher-servlet에 대해서 알아보도록 하겠습니다. 1. Dispatcher-Servlet(디스패처 서블릿)의 개념 [ Dispatcher-Servlet(디스패처 서블릿) 이란? ] 디스패처 서블릿의

mangkyu.tistory.com

이블로그 글을 빌리자면 

디스패처 서블릿의 dispatch는 "보내다"라는 뜻을 가지고 있습니다. 그리고 이러한 단어를 포함하는 디스패처 서블릿은 HTTP 프로토콜로 들어오는 모든 요청을 가장 먼저 받아 적합한 컨트롤러에 위임해주는 프론트 컨트롤러(Front Controller)라고 정의할 수 있습니다.
이것을 보다 자세히 설명하자면, 클라이언트로부터 어떠한 요청이 오면 Tomcat(톰캣)과 같은 서블릿 컨테이너가 요청을 받게 됩니다. 그리고 이 모든 요청을 프론트 컨트롤러인 디스패처 서블릿이 가장 먼저 받게 됩니다. 그러면 디스패처 서블릿은 공통적인 작업을 먼저 처리한 후에 해당 요청을 처리해야 하는 컨트롤러를 찾아서 작업을 위임합니다.
여기서 Front Controller(프론트 컨트롤러)라는 용어가 사용되는데, Front Controller는 주로 서블릿 컨테이너의 제일 앞에서 서버로 들어오는 클라이언트의 모든 요청을 받아서 처리해주는 컨트롤러로써, MVC 구조에서 함께 사용되는 디자인 패턴입니다.
출처: https://mangkyu.tistory.com/18 [MangKyu's Diary:티스토리]

말그대로 http 요청이 오면 가장 먼저 받는 위치에 존재하는 컨트롤러라고 생각하시면 편합니다.

 

당연히 아시겟지만 하나의 서블릿은  HttpServletRequest 및 HttpServletResponse를 처리할 수 있습니다.

하지만!! 하나 이상의 filter는 아래 다음과 같은 목적으로 이용할수 있습니다.

 

DownStream Filter 인스턴스 또는 서블릿이 호출되는 것을 방지합니다. 이 경우 필터는 일반적으로 HttpServletResponse를 작성합니다.

DownStream Filter  와 서블릿이 사용하는 HttpServletRequest나 HttpServletResponse를 수정합니다

 

DownStream Filter란?(저도 몰랐네요 ..)

말그대로 특정 필터 이후에 위치하는 필터들을 DownStream Filter라고 합니다.

 

결국 여기서 말하자고 하는것은요.

원문을보면

The power of the Filter comes from the FilterChain that is passed into it.

저도 이해한느낌이 filter의 강력한 힘은 filterchain을 통함으로라는건데 filter의 강력한점이 filterchain덕분이다 라는뜻 같네요. (혹시나 저도 이부분좀 이해가 안가서 이런느낌인가 합니다.)

 

간단히 filter chain의 코드를 보겟습니다.

public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) {
	// do something before the rest of the application
    chain.doFilter(request, response); // invoke the rest of the application
    // do something after the rest of the application
}

 

오늘은 여기까지하고 내일은 DelegatingFilterProxy에 대해서 알아보겠습니다.

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

+ Recent posts