묻고 답해요
160만명의 커뮤니티!! 함께 토론해봐요.
인프런 TOP Writers
-
미해결실전! 스프링 부트와 JPA 활용1 - 웹 애플리케이션 개발
JPA강의에서 Build and run using 을 Gradle로 사용하는 이유 알 수 있을까요?
다른 강의에선 작동 속도때문에 전부 인텔리제이로 바꿔서 진행했었는데 강의 교안을 보면 스프링부트 3.2 이상부터는 gradle로 하라고 나와있어 궁금하여 질문드립니다.
-
해결됨실전! 스프링 부트와 JPA 활용1 - 웹 애플리케이션 개발
실전! 스프링 부트와 JPA 활용1 - 웹 애플리케이션 개발
학습하는 분들께 도움이 되고, 더 좋은 답변을 드릴 수 있도록 질문전에 다음을 꼭 확인해주세요.1. 강의 내용과 관련된 질문을 남겨주세요.2. 인프런의 질문 게시판과 자주 하는 질문(링크)을 먼저 확인해주세요.(자주 하는 질문 링크: https://bit.ly/3fX6ygx)3. 질문 잘하기 메뉴얼(링크)을 먼저 읽어주세요.(질문 잘하기 메뉴얼 링크: https://bit.ly/2UfeqCG)질문 시에는 위 내용은 삭제하고 다음 내용을 남겨주세요.=========================================[질문 템플릿]1. 강의 내용과 관련된 질문인가요? (예/아니오)2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? (예/아니오)3. 질문 잘하기 메뉴얼을 읽어보셨나요? (예/아니오)[질문 내용]https://drive.google.com/drive/folders/1jHYkBAHDuUoSr5hjn0Kp5CzTAWLem3Zu?usp=drive_link 코드를 쭉 작성해봤는데 마지막에 submit할 때 whiteError페이지가 나옵니다. gpt에 해결책을 물어봤을 때에러 로그를 보면, Thymeleaf 템플릿을 처리하는 동안 문제가 발생한 것을 알 수 있습니다. 특히, item.orderItems[0].item.name라는 표현식에서 문제가 발생했습니다.에러의 원인에러 메시지 중에서 가장 중요한 부분은 다음과 같습니다:Caused by: org.springframework.expression.spel.SpelEvaluationException: EL1025E: The collection has '0' elements, index '0' is invalid 이 메시지는 item.orderItems[0]에서 인덱스를 사용하여 컬렉션의 첫 번째 요소에 접근하려고 했지만, orderItems 컬렉션이 비어 있어서 인덱스 0이 유효하지 않다는 것을 의미합니다. 즉, orderItems 컬렉션이 비어있거나 null일 때 이 표현식을 평가하려다가 오류가 발생한 것입니다.해결 방법컬렉션이 비어있을 경우에 대한 처리:Thymeleaf 템플릿에서 컬렉션이 비어있는 경우를 대비하여 조건문을 추가할 수 있습니다. 예를 들어, orderItems가 비어있지 않은 경우에만 접근하도록 할 수 있습니다.<div th:if="${item.orderItems.size() > 0}"> <span th:text="${item.orderItems[0].item.name}">Item Name</span> </div> 안전한 접근을 위한 기본값 제공:orderItems 컬렉션이 비어있을 때 안전하게 처리하기 위해, th:text 속성에서 기본값을 제공할 수 있습니다.<span th:text="${item.orderItems.size() > 0 ? item.orderItems[0].item.name : 'No items'}">Item Name</span> 서버 측에서 데이터 처리:서버 코드에서 orderItems가 비어있는 경우에 대해 적절히 처리하도록 할 수도 있습니다. 예를 들어, orderItems가 비어있다면 기본값을 설정하거나, 비어있음을 표시하는 별도의 로직을 추가할 수 있습니다.템플릿 구조 개선:템플릿 구조를 개선하여, orderItems가 비어있을 때는 특정 HTML 요소를 렌더링하지 않도록 할 수 있습니다.결론에러의 원인은 item.orderItems[0].item.name에서, orderItems 컬렉션이 비어있을 때 인덱스 0에 접근하려고 했기 때문입니다. 이를 해결하려면 위의 방법 중 하나를 사용하여, orderItems가 비어있는 경우를 안전하게 처리해야 합니다. 템플릿에서 Thymeleaf의 조건문이나 기본값 제공 기능을 사용하여 이 문제를 해결할 수 있습니다. 이런식으로 나왔고 h2데이터베이스의 order자체에 값이 잘 저장된 것은 확인했는데 무엇이 문제인지 잘 모르겠어서 질문드립니다
-
미해결실전! 스프링 부트와 JPA 활용1 - 웹 애플리케이션 개발
테스트코드 데이터소스 분리
학습하는 분들께 도움이 되고, 더 좋은 답변을 드릴 수 있도록 질문전에 다음을 꼭 확인해주세요.1. 강의 내용과 관련된 질문을 남겨주세요.2. 인프런의 질문 게시판과 자주 하는 질문(링크)을 먼저 확인해주세요.(자주 하는 질문 링크: https://bit.ly/3fX6ygx)3. 질문 잘하기 메뉴얼(링크)을 먼저 읽어주세요.(질문 잘하기 메뉴얼 링크: https://bit.ly/2UfeqCG)질문 시에는 위 내용은 삭제하고 다음 내용을 남겨주세요.=========================================[질문 템플릿]1. 강의 내용과 관련된 질문인가요? 예2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? 예3. 질문 잘하기 메뉴얼을 읽어보셨나요? 예[질문 내용]테스트 application.properties와 메인의 application.properties의 설정으로테스트와 실제 어플의 db 동작을 분리 할수 있는데만약에 테스트에서도 테스트 패키지 혹은 테스트 별로db를 다르게 사용하려면 어떻게 해야하나요?단위 테스트 할 기능중에 db종속적인 부분이 있어서질문 드려요!
-
미해결실전! 스프링 부트와 JPA 활용1 - 웹 애플리케이션 개발
QueryDsl관하여 질문 드립니다.
학습하는 분들께 도움이 되고, 더 좋은 답변을 드릴 수 있도록 질문전에 다음을 꼭 확인해주세요.1. 강의 내용과 관련된 질문을 남겨주세요.2. 인프런의 질문 게시판과 자주 하는 질문(링크)을 먼저 확인해주세요.(자주 하는 질문 링크: https://bit.ly/3fX6ygx)3. 질문 잘하기 메뉴얼(링크)을 먼저 읽어주세요.(질문 잘하기 메뉴얼 링크: https://bit.ly/2UfeqCG)질문 시에는 위 내용은 삭제하고 다음 내용을 남겨주세요.=========================================[질문 템플릿]1. 강의 내용과 관련된 질문인가요? (예/아니오)네2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? (예/아니오)네3. 질문 잘하기 메뉴얼을 읽어보셨나요? (예/아니오)네[질문 내용]안녕하세요. 근래에 쿼리 DSL을 배우면서 적용을 해보고 있습니다! 쿼리dsl을 사용하면 @OneToMany 등등 연관관계 매핑이 필요 없는지 궁금합니다. 필요하다면 왜 필요한지도 궁금합니다!!
-
미해결실전! 스프링 부트와 JPA 활용1 - 웹 애플리케이션 개발
delivery 인식 불가 ㅠ
학습하는 분들께 도움이 되고, 더 좋은 답변을 드릴 수 있도록 질문전에 다음을 꼭 확인해주세요.1. 강의 내용과 관련된 질문을 남겨주세요.2. 인프런의 질문 게시판과 자주 하는 질문(링크)을 먼저 확인해주세요.(자주 하는 질문 링크: https://bit.ly/3fX6ygx)3. 질문 잘하기 메뉴얼(링크)을 먼저 읽어주세요.(질문 잘하기 메뉴얼 링크: https://bit.ly/2UfeqCG)질문 시에는 위 내용은 삭제하고 다음 내용을 남겨주세요.=========================================[질문 템플릿]1. 강의 내용과 관련된 질문인가요? (예/아니오) 예2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? (예/아니오)에3. 질문 잘하기 메뉴얼을 읽어보셨나요? (예/아니오)예[질문 내용]여기에 질문 내용을 남겨주세요.위 강의를 듣고잇는데, delivery가 제 개발환경에서는 인식이 안됩니다...선언부 미인식 문제 자주 하는 질문을 참고해서 IDE 초기화도 해보고 했는데, 안되서 질문드립니다. 뭔가 설정을 잘못한거 같아서 JDK와 Gradle 설정 부분도 제대로 되어 있는 것 확인했습니다.
-
미해결따라하며 배우는 리액트 테스트 [2023.11 업데이트]
제공해주신 코드를 vscode에서 켜도 eslint가 안됩니다.
따라하며 배우는 리액트 테스트코드 강의에서 eslint가 적용되었다고 하는 파일자체를 받아 npm install을 헀는데,eslint가 작동되지않습니다.extension에서도 eslint를 받았고, npm install을 한 상태에서test()let test = () => {}와 같은 오류가 발생될 코드를 작성해도 eslint가 반응하지 못하는데 이유가 뭘까요 강의에는 설정이 적용되어있다고 하는데
-
미해결실전! 스프링 부트와 JPA 활용1 - 웹 애플리케이션 개발
MemberServiceTest 오류
학습하는 분들께 도움이 되고, 더 좋은 답변을 드릴 수 있도록 질문전에 다음을 꼭 확인해주세요.1. 강의 내용과 관련된 질문을 남겨주세요.2. 인프런의 질문 게시판과 자주 하는 질문(링크)을 먼저 확인해주세요.(자주 하는 질문 링크: https://bit.ly/3fX6ygx)3. 질문 잘하기 메뉴얼(링크)을 먼저 읽어주세요.(질문 잘하기 메뉴얼 링크: https://bit.ly/2UfeqCG)질문 시에는 위 내용은 삭제하고 다음 내용을 남겨주세요.=========================================[질문 템플릿]1. 강의 내용과 관련된 질문인가요? (예/아니오)2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? (예/아니오)3. 질문 잘하기 메뉴얼을 읽어보셨나요? (예/아니오)[질문 내용]여기에 질문 내용을 남겨주세요.MemberServiceTest 하려고 하는데 처음부터 오류뜨고 안돼요Cannot resolve symbol 'junit', Cannot resolve symbol 'Test', Identifier or type expected 이렇게 오류가 3개가 뜹니다. @Test 자체도 안되네요.. 사진첨부 같이 하겠습니다!
-
해결됨실전! 스프링 부트와 JPA 활용1 - 웹 애플리케이션 개발
양방향 @OneToOne 조회에 대해 질문 있습니다.
@Entity public class Delivery { @Id @Column(name = "delivery_id") @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; @OneToOne(fetch = FetchType.LAZY, mappedBy = "delivery") private Order order; private Address address; @Enumerated(EnumType.STRING) private DeliveryStatus status; public Long getId() { return id; } public void setId(Long id) { this.id = id; } public Order getOrder() { return order; } public void setOrder(Order order) { this.order = order; } public Address getAddress() { return address; } public void setAddress(Address address) { this.address = address; } public DeliveryStatus getStatus() { return status; } public void setStatus(DeliveryStatus status) { this.status = status; } }@Entity @Table(name = "orders") public class Order { @Id @Column(name = "order_id") @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; @OneToOne(fetch = FetchType.LAZY) @JoinColumn(name = "delivery_id") private Delivery delivery; private LocalDateTime orderDate; @Enumerated(EnumType.STRING) private OrderStatus status; public Long getId() { return id; } public void setId(Long id) { this.id = id; } public Delivery getDelivery() { return delivery; } public void setDelivery(Delivery delivery) { this.delivery = delivery; } public LocalDateTime getOrderDate() { return orderDate; } public void setOrderDate(LocalDateTime orderDate) { this.orderDate = orderDate; } public OrderStatus getStatus() { return status; } public void setStatus(OrderStatus status) { this.status = status; } }public class Test2 { public static void main(String[] args) { EntityManagerFactory emf = Persistence.createEntityManagerFactory("my-pu"); EntityManager em = emf.createEntityManager(); EntityTransaction tx = em.getTransaction(); try { tx.begin(); Delivery delivery = new Delivery(); delivery.setStatus(DeliveryStatus.READY); delivery.setAddress(new Address("city", "street", "zipcode")); em.persist(delivery); Order order = new Order(); order.setOrderDate(LocalDateTime.now()); order.setStatus(OrderStatus.ORDER); order.setDelivery(delivery); em.persist(order); // Order 에 fetch = FetchType.LAZY 설정 , delivery 실제 값 사용 { em.flush(); em.clear(); Order findOrder = em.find(Order.class, order.getId()); Delivery findDelivery = findOrder.getDelivery(); System.out.println("findDelivery : " + findDelivery.getStatus()); } tx.commit(); }finally { em.close(); } } }실행결과Hibernate: /* insert for com.mycom.myapp.ex.Delivery */insert into Delivery (city, street, zipcode, status) values (?, ?, ?, ?) Hibernate: /* insert for com.mycom.myapp.ex.Order */insert into orders (delivery_id, orderDate, status) values (?, ?, ?) Hibernate: select o1_0.order_id, o1_0.delivery_id, o1_0.orderDate, o1_0.status from orders o1_0 where o1_0.order_id=? Hibernate: select d1_0.delivery_id, d1_0.city, d1_0.street, d1_0.zipcode, d1_0.status from Delivery d1_0 where d1_0.delivery_id=? Hibernate: select o1_0.order_id, o1_0.delivery_id, o1_0.orderDate, o1_0.status from orders o1_0 where o1_0.delivery_id=? findDelivery : READY 강의에서 진행한 Order와 Delivery를 가지고 조회 테스트를 해봤습니다. 우선 Order와 Delivery를 양방향으로 OneToOne 관계를 설정했습니다. 그리고 둘다 각각 지연로딩으로 설정했습니다.em.flush(); em.clear(); Order findOrder = em.find(Order.class, order.getId()); Delivery findDelivery = findOrder.getDelivery(); System.out.println("findDelivery : " + findDelivery.getStatus());그리고 이 부분에 대해 아래와 같이 이해를 했습니다.맨처음 em.find()를 해서 Order에 대해 DB에 select문을 보냅니다. 이때 delivery와는 지연로딩이므로 추가 select가 발생하지 않습니다. 그리고 findDelivery.getStatus()); 에서 delivery의 실제 값을 사용하므로 이때 delviery에 대한 select문이 발생합니다. 정리하면 처음에는 order에 대한 select문 그리고 실제 delevery 값을 사용할때 delivery에 대한 select문 해서 총 두번의 select문이 발생할꺼라고 예상을 했습니다.근데 실제 실행결과를 보니 총 세번의 select문이 발생했습니다. 실행결과에서 첫번째 select문과 두번째 select문이 출력된거는 이해가 되는데 마지막 select문은 왜 발생했는지 모르겠습니다.
-
미해결실전! 스프링 부트와 JPA 활용1 - 웹 애플리케이션 개발
MemberRepositoryTest 실행함에 있어 오류
학습하는 분들께 도움이 되고, 더 좋은 답변을 드릴 수 있도록 질문전에 다음을 꼭 확인해주세요.1. 강의 내용과 관련된 질문을 남겨주세요.2. 인프런의 질문 게시판과 자주 하는 질문(링크)을 먼저 확인해주세요.(자주 하는 질문 링크: https://bit.ly/3fX6ygx)3. 질문 잘하기 메뉴얼(링크)을 먼저 읽어주세요.(질문 잘하기 메뉴얼 링크: https://bit.ly/2UfeqCG)질문 시에는 위 내용은 삭제하고 다음 내용을 남겨주세요.=========================================[질문 템플릿]1. 강의 내용과 관련된 질문인가요? (예/아니오)2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? (예/아니오)3. 질문 잘하기 메뉴얼을 읽어보셨나요? (예/아니오)[질문 내용]application.ymlspring: datasource: url: jdbc:h2:tcp://localhost/~/jpashop username: sa password: driver-class-name: org.h2.Driver jpa: hibernate: ddl-auto: create properties: hibernate: # show-sql: true format_sql: true logging.level: org.hibernate.SQL: debug # org.hibernate.type:trace org.hibernate.orm.jdbc.bind: tracebuild.gradleplugins { id 'java' id 'org.springframework.boot' version '3.2.0' id 'io.spring.dependency-management' version '1.1.4' } group = 'jpabook' version = '0.0.1-SNAPSHOT' java { sourceCompatibility = '17' } configurations { compileOnly { extendsFrom annotationProcessor } } repositories { mavenCentral() } dependencies { implementation 'org.springframework.boot:spring-boot-starter-data-jpa' implementation 'org.springframework.boot:spring-boot-starter-thymeleaf' implementation 'org.springframework.boot:spring-boot-starter-validation' implementation 'org.springframework.boot:spring-boot-starter-web' implementation 'com.github.gavlyukovskiy:p6spy-spring-boot-starter:1.9.0' compileOnly 'org.projectlombok:lombok' runtimeOnly 'com.h2database:h2' annotationProcessor 'org.projectlombok:lombok' testImplementation 'org.springframework.boot:spring-boot-starter-test' //JUnit4 추가 testImplementation("org.junit.vintage:junit-vintage-engine") { } test { useJUnitPlatform() }MemberRepositoryTest.javapackage jpabook.jpashop; import jpabook.jpashop.Entity.Member; import jpabook.jpashop.Repository.MemberRepository; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.test.annotation.Rollback; import org.springframework.test.context.junit.jupiter.SpringExtension; import org.springframework.transaction.annotation.Transactional; import static org.assertj.core.api.Assertions.assertThat; @ExtendWith(SpringExtension.class) @SpringBootTest class MemberRepositoryTest { @Autowired MemberRepository memberRepository; @Test @Transactional @Rollback(false) public void testMember() throws Exception { //given Member member = new Member(); member.setUsername("memberA"); //when Long savedId = memberRepository.save(member); Member findMember = memberRepository.find(savedId); //then assertThat(findMember.getId()).isEqualTo(member.getId()); assertThat(findMember.getUsername()).isEqualTo(member.getUsername()); System.out.println("findMember == member: " + (findMember == member)); } }테스트 실행 시 No matching tests found in any candidate test task. Requested tests: Test pattern jpabook.jpashop.Repository.MemberRepositoryTest in task :test* Try:> Run with --stacktrace option to get the stack trace.> Run with --info or --debug option to get more log output.> Run with --scan to get full insights.> Get more help at https://help.gradle.org.Deprecated Gradle features were used in this build, making it incompatible with Gradle 9.0.You can use '--warning-mode all' to show the individual deprecation warnings and determine if they come from your own scripts or plugins.For more on this, please refer to https://docs.gradle.org/8.8/userguide/command_line_interface.html#sec:command_line_warnings in the Gradle documentation.BUILD FAILED in 1s4 actionable tasks: 1 executed, 3 up-to-date오류가 발생합니다.
-
미해결실전! 스프링 부트와 JPA 활용1 - 웹 애플리케이션 개발
order.cancel();의 더티체킹에 대해 질문 있습니다.
@Entity @Getter @Setter @DiscriminatorColumn(name = "dtype") @Inheritance(strategy = InheritanceType.SINGLE_TABLE) public abstract class Item { @Id @Column(name = "item_id") @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; private String name; private int price; private int stockQuantity; @ManyToMany(mappedBy = "items") private List<Category> categories = new ArrayList<>(); //== 비즈니스 로직 ==// public void addStock(int quantity) { this.stockQuantity += quantity; } public void removeStock(int quantity) { int restStock = this.stockQuantity - quantity; if (restStock < 0) { throw new NotEnoughStockException("need more stock"); } this.stockQuantity = restStock; } }@Entity @Getter @Setter @NoArgsConstructor(access = AccessLevel.PROTECTED) public class OrderItem { @Id @Column(name = "order_item_id") @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name = "order_id") private Order order; @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name = "team_id") private Item item; private int orderPrice; private int count; //==생성 메서드==// public static OrderItem createOrderItem(Item item, int orderPrice, int count) { OrderItem orderItem = new OrderItem(); orderItem.setItem(item); orderItem.setOrderPrice(orderPrice); orderItem.setCount(count); item.removeStock(count); return orderItem; } //==비즈니스 로직==// /* * 재고 수량을 복구한다. * */ public void cancel() { getItem().addStock(count); } //==조회 로직==// public int getTotalPrice() { return getOrderPrice() * getCount(); } }@Entity @Getter @Setter @Table(name = "orders") @NoArgsConstructor(access = AccessLevel.PROTECTED) public class Order { @Id @Column(name = "order_id") @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name = "member_id") private Member member; @OneToMany(mappedBy = "order", cascade = CascadeType.ALL) private List<OrderItem> orderItems = new ArrayList<>(); @OneToOne(fetch = FetchType.LAZY, cascade = CascadeType.ALL) @JoinColumn(name = "delivery_id") private Delivery delivery; private LocalDateTime orderDate; @Enumerated(EnumType.STRING) private OrderStatus status; //== 연관관계 메서드 ==// public void addMember(Member member) { this.member = member; member.getOrders().add(this); } public void addOrderItem(OrderItem orderItem) { orderItems.add(orderItem); orderItem.setOrder(this); } public void addDelivery(Delivery delivery) { this.delivery = delivery; delivery.setOrder(this); } // 생성하는 지점을 변경해야 되면 아래 생성 메서드만 바꾸면 된다. 이게 중요한 포인트다 이것저것 찾아다닐 필요없고 //== 생성 메서드==// public static Order createOrder(Member member, Delivery delivery, OrderItem... orderItems) { Order order = new Order(); order.setMember(member); order.setDelivery(delivery); for (OrderItem orderItem : orderItems) { order.addOrderItem(orderItem); } order.setStatus(OrderStatus.ORDER); order.setOrderDate(LocalDateTime.now()); return order; } //==비즈니스 로직==// /* * 주문 취소 * */ public void cancel() { if (delivery.getStatus() == DeliveryStatus.COMP) { throw new IllegalStateException("이미 배송 완료된 상품은 취소가 불가능합니다."); } this.setStatus(OrderStatus.CANCEL); for (OrderItem orderItem : orderItems) { orderItem.cancel(); } } //==조회 로직==// /* * 전체 주문 가격 조회 * */ public int getTotalPrice() { int totalPrice = 0; for (OrderItem orderItem : orderItems) { totalPrice += orderItem.getTotalPrice(); } return totalPrice; } }@Service @Transactional(readOnly = true) @RequiredArgsConstructor public class OrderService { private final OrderRepository orderRepository; private final MemberRepository memberRepository; private final ItemRepository itemRepository; // 주문 @Transactional public Long order(Long memberId, Long itemId, int count) { // 엔티티 조회 Member member = memberRepository.findOne(memberId); Item item = itemRepository.findOne(itemId); // 배송정보 생성 Delivery delivery = new Delivery(); delivery.setAddress(member.getAddress()); // 주문상품 생성 OrderItem orderItem = OrderItem.createOrderItem(item, item.getPrice(), count); // 주문 생성 Order order = Order.createOrder(member, delivery, orderItem); // 주문 저장 orderRepository.save(order); return order.getId(); } // 취소 @Transactional public void cancelOrder(Long orderId) { Order order = orderRepository.findOne(orderId); order.cancel(); } // 검색 // public List<Order> findOrders() { // return orderRepository.f // } }OrderService에서 cancelOrder()을 할 경우 @Transactional에 의해 자동으로 트랜잭션을 시작하고 커밋을 보내고 커밋을 보낼때 플러시가 발생하고 더티체킹이 발생해 직업 update를 안해도 알아서 update 쿼리가 날라가는 부분에 대해서는 이해를 했습니다.궁금한 부분은 현재 Order order = orderRepository.findOne(orderId); 를 통해 order 엔티티만 조회 했으니 영속성 컨텍스트에는 order 엔티티만 존재하므로 Item 엔티티는 영속성 컨텍스트에 없는데 어떻게 더티체킹에 들어갈까가 저의 의문입니다.이 부분에 대해서 아래와 같이 생각해봤는데 맞게 생각한건지 궁금합니다. 잘못된 부분에 대해서 알려주시면 감사하겠습니다.order.cancel();의 cancel() 메서드를 보면 orderItem.cancel(); 부분이 존재한다.orderItem.cancel() 의 cancel() 메서드를 보면 getItem().addStock(count); 부분이 존재한다.여기서 getItem()을 사용해서 (현재 Order와 OrderItem은 지연로딩 관계) 실제 orderItem 값을 사용하므로 DB에서 orderItem 엔티티를 조회해서 영속성 컨텍스트에 저장한다.다시 orderItem.cancel() 의 cancel() 메서드에서 addStock(count) 메서드를 들어가 보면 Item의 addStock() 메서드로 이동한다. 여기서 this.stockQuantity += quantity; 를 통해 Item의 실제 값을 사용하므로 Item 엔티티도 DB에서 조회해서 영속성 컨텍스트에 저장한다.결과적으로 OrderService의 cancelOrder() 메서드에서 order.cancel();가 호출되면 Item과 OrderItem 엔티티도 영속성 컨텍스트에 저장되서 더티체킹 범위에 들어가게 된다.
-
해결됨실전! 스프링 부트와 JPA 활용1 - 웹 애플리케이션 개발
빌더 패턴 vs 정적 팩토리 메서드
빌더 패턴을 사용하여 객체를 생성하는 방법과 정적 팩토리 메서드를 사용하여 객체를 생성하는 방법을 각각 언제 사용하면 좋을지 궁금합니다.구글링해서 찾아보니 빌더 패턴은 파라미터가 많을때 사용하고 정적 팩토리 메서드는 파라미터가 적을때 사용한다고 하는데 파라미터가 많고 적음의 기준도 잘 모르겠고 명확하게 언제 사용하면 좋을지에 대한 글을 찾지 못해 질문글을 작성합니다.
-
해결됨실전! 스프링 부트와 JPA 활용1 - 웹 애플리케이션 개발
테스트 코드에서 @Transactional과 @AfterEach
강의에서 @Transactional 을 테스트코드에 붙여서 테스트를 진행하였는데요 @AfterEach 어노테이션으로 void clean() {메서드를 만들어 리파지토리를 정리하는거랑 차이가 있나요?코드가 간결해지는 이점으로 @Transactional 를 자주 사용하게 되는건가요?실무에서 어떻게 쓰이는지 궁금합니다.
-
미해결실전! 스프링 부트와 JPA 활용1 - 웹 애플리케이션 개발
H2 데이터베이스 member 테이블 생성이 안 돼요
테스트 코드는 오류 없이 초록불이 뜨는데 DB 내 테이블 생성이 안 됩니다. 강사님의 다른 강의와, 응용 프로젝트를 만들어 볼 땐 잘 됐어서 자주 묻는 질문들을 참고해도 어느 곳이 문제인지 잘 모르겠네요ㅠㅠ.. 일단 올려두고 계속 방법을 찾아보겠습니다! package jpabook.jpashop; import org.assertj.core.api.Assertions; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.test.annotation.Rollback; import org.springframework.test.context.junit4.SpringRunner; import org.springframework.transaction.annotation.Transactional; import static org.junit.Assert.*; @RunWith(SpringRunner.class) @SpringBootTest public class MemberRepositoryTest { @Autowired MemberRepository memberRepository; @Test @Transactional @Rollback(false) public void testMember() throws Exception{ //given Member member = new Member(); member.setUsername("memberA"); //when //ctrl+alt+v 변수 뽑기 Long saveId = memberRepository.save(member); Member findMember = memberRepository.find(saveId); //then Assertions.assertThat(findMember.getId()).isEqualTo(member.getId()); Assertions.assertThat(findMember.getUsername()).isEqualTo(member.getUsername()); Assertions.assertThat(findMember).isEqualTo(member); //JPA 엔티티 동일성 보장 } }spring: application: name: jpashop #port번호 설정 server: port: 8050 #DB datasource: url: jdbc:h2:tcp://localhost/~/jpashop username: sa password: driver-class-name: org.h2.Driver #JPA jpa: hibernate: ddl-auto: create properties: hibernate: show_sql: true format_sql: true logging: level: org.hibernate.SQL: debug org.hibernate.orm.jdbc.bind: trace
-
미해결실전! 스프링 부트와 JPA 활용1 - 웹 애플리케이션 개발
타임리프 사용 관련 문의 드립니다.
안녕하세요. 타임리프 렌더링 관련해서 질문이 있습니다.현재 스프링부트랑 타임리프 버전이 3.3.2입니다.html에서 사용하면 아래와 같이 렌더링이 안되어 있는 거 같습니다.버전에 문제일까요?
-
미해결실전! 스프링 부트와 JPA 활용1 - 웹 애플리케이션 개발
프로젝트 실행 시, ClassNotFoundException: lombok.Setter 에러 발생
학습하는 분들께 도움이 되고, 더 좋은 답변을 드릴 수 있도록 질문전에 다음을 꼭 확인해주세요.1. 강의 내용과 관련된 질문을 남겨주세요.2. 인프런의 질문 게시판과 자주 하는 질문(링크)을 먼저 확인해주세요.(자주 하는 질문 링크: https://bit.ly/3fX6ygx)3. 질문 잘하기 메뉴얼(링크)을 먼저 읽어주세요.(질문 잘하기 메뉴얼 링크: https://bit.ly/2UfeqCG)질문 시에는 위 내용은 삭제하고 다음 내용을 남겨주세요.=========================================[질문 템플릿]1. 강의 내용과 관련된 질문인가요? (예/아니오)2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? (예/아니오)3. 질문 잘하기 메뉴얼을 읽어보셨나요? (예/아니오)[질문 내용]여기에 질문 내용을 남겨주세요.엔티티 클래스 작성 후 프로젝트 실행 시 아래와 같은 에러 메세지가 출력됩니다.lombok 설정은 아래와 같이 설정된 것을 확인했고, 엔티티 클래스 작성 전에 테스트에서 잘 실행되었습니다.세팅 관련 설정도 아래와 같이 확인했습니다. @Getter, @Setter도 잘 인식하는데, lombok 클래스를 발견할 수 없다는 에러가 계속 발생하는데, 뭐가 문제일까요?
-
미해결실전! 스프링 부트와 JPA 활용1 - 웹 애플리케이션 개발
Result.hasErrors()로 처리를 해도
학습하는 분들께 도움이 되고, 더 좋은 답변을 드릴 수 있도록 질문전에 다음을 꼭 확인해주세요.1. 강의 내용과 관련된 질문을 남겨주세요.2. 인프런의 질문 게시판과 자주 하는 질문(링크)을 먼저 확인해주세요.(자주 하는 질문 링크: https://bit.ly/3fX6ygx)3. 질문 잘하기 메뉴얼(링크)을 먼저 읽어주세요.(질문 잘하기 메뉴얼 링크: https://bit.ly/2UfeqCG)질문 시에는 위 내용은 삭제하고 다음 내용을 남겨주세요.=========================================[질문 템플릿]1. 강의 내용과 관련된 질문인가요? (예/아니오)2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? (예/아니오)3. 질문 잘하기 메뉴얼을 읽어보셨나요? (예/아니오)[질문 내용]Result.hasErrors()로 처리를 해도 등록페이지에 아무것도 안적고 제출누르면 회원 이름은 필수입니다가 떠야 하는데 안뜹니다 왜 그런걸까요??
-
미해결실전! 스프링 부트와 JPA 활용1 - 웹 애플리케이션 개발
main 함수 실행 에러
첫번째 스크린샷 build ~ using을 인텔리제이로 썼을 땐 에러가 안 나는데 이번 강의에서 gradle(default)로 설정한 후 main함수 실행 시 에러가 뜨며 실행이 되지 않습니다. 다른 질문들 참고해봤는데 다른 건 없고 계속 똑같은 오류가 뜨더라구요.. 해결 방법이 있을까요?
-
미해결실전! 스프링 부트와 JPA 활용1 - 웹 애플리케이션 개발
@NotEmpty 어노테이션
학습하는 분들께 도움이 되고, 더 좋은 답변을 드릴 수 있도록 질문전에 다음을 꼭 확인해주세요.1. 강의 내용과 관련된 질문을 남겨주세요.2. 인프런의 질문 게시판과 자주 하는 질문(링크)을 먼저 확인해주세요.(자주 하는 질문 링크: https://bit.ly/3fX6ygx)3. 질문 잘하기 메뉴얼(링크)을 먼저 읽어주세요.(질문 잘하기 메뉴얼 링크: https://bit.ly/2UfeqCG)질문 시에는 위 내용은 삭제하고 다음 내용을 남겨주세요.=========================================[질문 템플릿]1. 강의 내용과 관련된 질문인가요? (예/아니오)2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? (예/아니오)3. 질문 잘하기 메뉴얼을 읽어보셨나요? (예/아니오)[질문 내용]@NotEmpty어노테이션이 임포트가 안됩니다 혹시 버전차이때문에 그런건가요?
-
미해결실전! 스프링 부트와 JPA 활용1 - 웹 애플리케이션 개발
slf4j 보안에 대해 질문
학습하는 분들께 도움이 되고, 더 좋은 답변을 드릴 수 있도록 질문전에 다음을 꼭 확인해주세요.1. 강의 내용과 관련된 질문을 남겨주세요.2. 인프런의 질문 게시판과 자주 하는 질문(링크)을 먼저 확인해주세요.(자주 하는 질문 링크: https://bit.ly/3fX6ygx)3. 질문 잘하기 메뉴얼(링크)을 먼저 읽어주세요.(질문 잘하기 메뉴얼 링크: https://bit.ly/2UfeqCG)질문 시에는 위 내용은 삭제하고 다음 내용을 남겨주세요.=========================================[질문 템플릿]1. 강의 내용과 관련된 질문인가요? (예/아니오)2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? (예/아니오)3. 질문 잘하기 메뉴얼을 읽어보셨나요? (예/아니오)[질문 내용]혹시 slf4j가 보안에 취약하다고 Logback를 사용하라는 블로그글을 본 적이 있는데 혹시 사실인가요??보안이 뚫렸다고 표현을 해서 궁금합니다
-
해결됨실전! 스프링 부트와 JPA 활용1 - 웹 애플리케이션 개발
'회원 이름 필수 입력' 기능
안녕하세요. 웹계층 회원등록 부분 강의 따라서 코딩하고, HTML 파일도 복붙했는데홈페이지에 이름을 입력 안 해도 '회원 이름을 필수입니다' 메세지가 뜨는 반응이 없이 redirect됩니다. h2에는 이름이 비어 있는 상태로 데이터가 들어와 있습니다. @NotEmpty가 왜 작동하지 않는지 질문드립니다. https://drive.google.com/file/d/1jvu4wiWz3GwoZ3YazNDJWsFTOxgSqt-M/view?usp=sharing