묻고 답해요
161만명의 커뮤니티!! 함께 토론해봐요.
인프런 TOP Writers
-
해결됨실전! 스프링 데이터 JPA
즐겁게 듣겠습니다~~~
어느덧 여기까지 왔어요 ㅎㅎ 이번 강의도 즐겁게 듣겠습니다. 항상 잘 듣고있어요
-
미해결실전! 스프링 부트와 JPA 활용1 - 웹 애플리케이션 개발
주문내역 검색 form 관련해서 질문입니다...
안녕하세요 강의 정말 재미있게 스프링핵심 원리, JPA 잘 듣고 있습니다. 주문 목록 검색 form 태그에 action 속성이 없는데 submit을 할경우 어떤식으로 작동하는지 이해가 잘 안가여 질문드립니다.
-
미해결실전! 스프링 부트와 JPA 활용1 - 웹 애플리케이션 개발
공부를 하면서..
spring 핵심 원리에서 배웠던 DI, interface를 이용해서 추상화하는 방식이 사용되고 있지않고. 그냥 private final ItemService itemService 이런식으로 진행하고 계시는데 jpa 강의라서 이렇게 간단하게 설계 하시는건가요?? 실무에서 프로젝트 사이즈가 커지다보면 자연스레 추상화하게 되나요?? 질문 자체가 이상했으면 죄송합니다..
-
미해결자바 ORM 표준 JPA 프로그래밍 - 기본편
스프링 커뮤니티
스프링 커뮤니티에 자주 올라오는 질문 이라고 하셨는데 따로 이용하시는 스프링 커뮤니티가 있나요?
-
해결됨자바 ORM 표준 JPA 프로그래밍 - 기본편
일반 조인과 fetch join 테스트를 해봤는데, 질문이 생겼습니다.
복습을 하면서 예제 코드를 이리저리 건드려 보고 있습니다. 그런데 문득 이런 생각이 들었습니다. fetch 조인 대신 그냥 join문을 써서 같은 효과를 낼 수 있지 않을까? 그래서 예제 코드를 약간 수정해서 아래 코드를 돌려봤습니다. Team teamA = new Team(); teamA.setName("팀A"); em.persist(teamA); Team teamB = new Team(); teamB.setName("팀B"); em.persist(teamB); Member member1 = new Member(); member1.setUsername("회원1"); member1.setAge(10); member1.changeTeam(teamA); em.persist(member1); Member member2 = new Member(); member2.setUsername("회원2"); member2.setAge(15); member2.changeTeam(teamA); em.persist(member2); Member member3 = new Member(); member3.setUsername("회원3"); member3.setAge(15); member3.changeTeam(teamB); em.persist(member3); em.flush(); em.clear(); String query = "select m,t From Member m join m.team t"; List<Object[]> resultList = em.createQuery(query).getResultList(); for (Object[] o : resultList) { System.out.println(Arrays.toString(o)); } 그러면 다음과 같은 결과를 볼 수 있습니다. (아 참고로, Member와 Team 클래스에 toString을 미리 설정했습니다. 연관관계만 뺀 나머지 필드는 모두 출력합니다) fetch join을 안 썼지만, 한 방 쿼리가 날렸고, 같은 효과를 내는 걸 확인 했습니다. 이렇게 일반 join을 쓰면 되는데 어떤 차이 때문에 fetch join을 써야 되는 건가요? 아니면 제가 뭔가 놓친 게 있는 걸까요?
-
미해결자바 ORM 표준 JPA 프로그래밍 - 기본편
왜 final 을 사용하면 안될까요!?
@Entity에는 final 클래스를 필드에도 사용하지 말라고 하셨는데 이유가 뭔지 궁금합니다.
-
미해결자바 ORM 표준 JPA 프로그래밍 - 기본편
다대일 양방향 질문입니다.
안녕하세요. 다대일 양방향 관계에 대해 질문 드립니다. Member 엔티티와 Team 엔티티가 다대일 양방향 맵핑 되어있고, package hellojpa; import javax.persistence.*; import java.util.ArrayList; import java.util.List; @Entity public class Member { @Id @GeneratedValue @Column(name= "MEMBER_ID") private Long id; private String name; private int age; @OneToMany(mappedBy = "member") private List<Order> orders = new ArrayList<Order>(); @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name = "TEAM_ID") private Team team; public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public void setTeam(Team team) { this.team = team; team.getMembers().add(this); } } package hellojpa; import javax.persistence.*; import java.util.ArrayList; import java.util.List; @Entity public class Team { @Id @GeneratedValue @Column(name = "TEAM_ID") private Long id; private String name; @OneToMany(mappedBy = "team",fetch = FetchType.LAZY) private List<Member> members = new ArrayList<>(); public Long getId() { return id; } public void setId(Long id) { this.id = id; } public String getName() { return name; } public List<Member> getMembers() { return members; } public void setName(String name) { this.name = name; } } 팀에서 getMembers 메소드를 통하여 해당 팀에 소속된 멤버들을 조회할 때 public class hellojpa { public static void main(String[] args) { EntityManagerFactory emf = Persistence.createEntityManagerFactory("hello"); EntityManager em = emf.createEntityManager(); EntityTransaction transaction = em.getTransaction(); transaction.begin(); try { Member member =new Member(); member.setName("member1"); member.setAge(20); Team team = new Team(); team.setName("team a"); em.persist(team); member.setTeam(team); em.persist(member); Member member2 = new Member(); member2.setName("member222"); member2.setTeam(team); em.persist(member2); em.flush(); em.clear(); List<Member> memberList = em.find(Team.class, team.getId()).getMembers(); for (Member member1 : memberList) { System.out.println(member1.getName()); } } catch (Exception e) { transaction.rollback(); } finally { em.close(); } emf.close(); } } 저는 select member0_.MEMBER_ID members0_.TEAM_ID members0_.age members0_.name from Member members0_ where members0_.TEAM_ID=? 이러한 쿼리가 생성될 것으로 예상했습니다. 하지만 실제 쿼리가 나간것을 확인해보니 select members0_.TEAM_ID as team_id4_0_0_, members0_.MEMBER_ID as member_i1_0_0_, members0_.MEMBER_ID as member_i1_0_1_, members0_.age as age2_0_1_, members0_.name as name3_0_1_, members0_.TEAM_ID as team_id4_0_1_ from Member members0_ where members0_.TEAM_ID=? select문에서 특정 컬럼들이 중복되어 표시되는데(bold표시), 혹시 이렇게 표시되는게 정상적인 것인지 혹은 맵핑 과정에서 실수가 있었던지 궁금하여 질문 드립니다!
-
해결됨자바 ORM 표준 JPA 프로그래밍 - 기본편
doma Seasar 라는 것에 대해~
안녕하세요. 강의 진행 자체와는 무관한 질문일 수도 있으니, 영한님 여유 되실 때 간단히(?) 답변 부탁드립니다. JAVA ORM 표준이 JPA인데 그 구현체로 많이 쓰이고, 강사님도 강의 때 소개해 주신 것으로 Hibernate가 있음을 압니다. 회사에서 타 프로젝트(협업사가 일본임, Maven prj) 소스를 받아 빌드 시도 중, doma ... 라는 것 부근에서 약간의 트러블이 있어서 뒤져 보니 doma seasar 라는 것 역시도 JPA 구현체가 아닌가 생각하게 되었습니다. (예: https://doma.readthedocs.io/en/latest/ ) 즉, Hibernate와 유사한 역할을 하는 framework library로 저는 추측하고 있습니다만, 혹 경험 많으신 영한님은 이것에 대해 알고 계시리라 생각하고 여쭙습니다. 혹, Doma Seasor 라는 것에 대해 간단한 소개나 평 등을 가능한 대로 말씀해 주실 수 있을까요? 다른 수강생들 입장에서도 인식의 지평을 넓히는 데 도움이 되실 것으로 믿습니다.^^ 감사합니다.
-
해결됨실전! 스프링 부트와 JPA 활용2 - API 개발과 성능 최적화
양방향 연관관계일 때 한쪽을 끝는거에 대해 질문드립니다.
@JsonIgnore 어노테이션을 사용하면 지금 상태로는 꼭 하이버네이트5모듈을 사용해야 하는거죠? 일단 지금은 그렇게 알고있으면 될까요? 감사합니다.
-
미해결자바 ORM 표준 JPA 프로그래밍 - 기본편
의문점 + 질문
(의문점) 단일참조가 아닐 경우 orphanRemoval을 사용하지 말아야 하는 이유에 대해서는 이해가 됩니다만.. 부모가 여럿이 있는 자식 객체가 있다고 했을 때, 하나의 부모가 없어진다해도 다른 부모쪽에는 참조가 되어있으니 아직 고아가 아닌 거 아닌가요?; 마치 아버지가 사망했다고 모자관계까지 끊어버리는 느낌..? 이상하네요; 너무 쓸 데 없이 Real World에 대입해서 생각하는걸까요? (질문) orphanRemoval = true를 사용한다는 게 결국 CascadeType.REMOVE와 똑같은 말 아닌가요? 그럼 CascadeType.ALL을 사용하면 굳이 orphanRemoval = true는 사용할 필요가 없는 것 아닌가 싶습니다. 자식의 생명주기를 부모가 관리하기 위해서 꼭 저 두 속성을 함께 써야하는 이유가 무엇인지 궁금합니다. 감사합니다.
-
미해결실전! Querydsl
Q Class 생성 시 extends 상속 질문
안녕하세요. Entity class에 extends DefualtEntity 를 할 경우 Q class 생서 시 DefualtEntity 의 값은 Q Class에 누락되는 현상이 있던데 상속을 해서 구성하면 안되는 걸까요? DefualtEntity 에는 @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss", timezone = "Asia/Seoul") private LocalDateTime regDate; @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss", timezone = "Asia/Seoul") private LocalDateTime udtDate; @PrePersist public void prePersist() { LocalDateTime now = LocalDateTime.now(); regDate = now; udtDate = now; } @PreUpdate public void preUpdate() { udtDate = LocalDateTime.now(); } 이런 공통적인 내용을 넣어보려합니다.
-
미해결자바 ORM 표준 JPA 프로그래밍 - 기본편
프록시 객체의 비교방법 질문
안녕하세요 강사님, 질문 드리겠습니다. 일반 객체와 프록시 객체의 비교에 대해 정확하게 이해되지 않습니다. 처음에 소개하실 때는 항상 == 대신에 instanceof로 비교해야 정확한 결과를 얻을 수 있다고 하셨었는데요, 그 이후(26:50)에서 말씀하시는 내용을 보면 "==비교에 대해서 같은 영속성 컨텍스트 레벨 안에서는 항상 같다라고 나와야한다." 라고 하십니다. m1, reference 둘 다 getClass가 Member를 반환하고요. 두 상황에 어떤차이가 있길래 앞에선 ==을 사용하면 안 되고 뒤에선 ==이 가능한 것인지 이해가 안 되네요;; 첫번쨰 상황에서도 em.find, em.getReference을 한 후에 logic()으로 비교를 했으니 이떄도 같은 영속성 컨텍스트 레벨에 있는 것 아닌가요?
-
해결됨실전! 스프링 부트와 JPA 활용2 - API 개발과 성능 최적화
모든 주문리스트 조회하는 타임리프 올려봅니다.
<!DOCTYPE HTML><html xmlns:th="http://www.thymeleaf.org"><head th:replace="fragments/header :: header"></head><body><div class="container"> <div th:replace="fragments/bodyHeader :: bodyHeader"></div> <div> <div> <form th:object="${orderSearch}" class="form-inline"> <div class="form-group mb-2"> <input type="text" th:field="*{memberName}" class="form- control" placeholder="회원명"/> </div> <div class="form-group mx-sm-1 mb-2"> <select th:field="*{orderStatus}" class="form-control"> <option value="">주문상태</option> <option th:each="status : ${T(jpabook.jpashop.domain.OrderStatus).values()}" th:value="${status}" th:text="${status}">option </option> </select> </div> <button type="submit" class="btn btn-primary mb-2">검색</button> </form> </div> <table class="table table-striped"> <thead> <tr> <th>#</th> <th>회원명</th> <th>대표상품 이름</th> <th>대표상품 주문가격</th> <th>대표상품 주문수량</th> <th>상태</th> <th>일시</th> <th></th> </tr> </thead> <tbody> <span th:each="item : ${orders}"> <tr th:each="orderItem : ${item.orderItems}"> <td th:text="${orderItem.item.id}"></td> <td th:text="${item.member.name}"></td> <td th:text="${orderItem.item.name}"></td> <td th:text="${orderItem.orderPrice}"></td> <td th:text="${orderItem.count}"></td> <td th:text="${item.status}"></td> <td th:text="${item.orderDate}"></td> <td> <a th:if="${item.status.name() == 'ORDER'}" href="#" th:href="'javascript:cancel('+${orderItem.order.id}+')'" class="btn btn-danger">CANCEL</a> </td> </tr> </span> </tbody> </table> </div> <div th:replace="fragments/footer :: footer"></div></div> <!-- /container --></body><script> function cancel(id) { var form = document.createElement("form"); form.setAttribute("method", "post"); form.setAttribute("action", "/orders/" + id + "/cancel"); document.body.appendChild(form); form.submit(); }</script></html> 구글 뒤져가면서 왜 이중 each를 쓰는데 인텔리제이가 빨간줄 긋지...싶었는데 tr을 두번으로 each하면 안되나봅니다. ㅠㅠ 바깥의 each를 span태그로 바꿔주니까 잘되는거같네요! 혹시나 막히시는 분들은 참고하셔요! 이거 만드는데 1시간넘게걸렸네요 .. ㅠㅠㅠㅠㅠㅠ
-
미해결실전! 스프링 부트와 JPA 활용1 - 웹 애플리케이션 개발
DTO 사용에대해 궁금합니다.
안녕하세요 영한님. 항상 좋은강의 보면서 이미 완강을 하였지만 궁금한점이 이 강의내용에 해당되는것 같아 질문을 남깁니다. 컨트롤러에서 (API) 개발을 할때 Entity를 바로 접근하지 말고 DTO를 권장하셔서 DTO를 사용하던 찰나에 문제가 생겼습니다. Entity에 Setter를 사용하는건 지양한다고 하셔서 생성자로 값을 넣어주고 있는데 DTO에서도 값을 생성자로 넣어줘야 하나요? 백을 먼저 개발하고 프론트를 개발하기위해 타임리프로 하고 있는데 DTO 를 생성자로 만들어 놓으니 값을 계속 못받아와서요. 한참 헤매다가 설마 하고 LOMBOK @Setter 로 하니 값이 넘어오더라고요. DTO는 Setter로 하여도 문제가 없을까요? 제 생각에도 DTO는 단순 값을 전달 받는 Form(?)이라고 생각되어 Entity에서의 Setter를 지양해야하는 문제에 와는 달리 큰 영향은 없을 것 같아서요. 감사합니다.!
-
미해결실전! Querydsl
BooleanBuilder와 BooleanExpression의 차이점이 궁금합니다.
안녕하세요. 강사님. 강의를 보는 도중 궁금한 점이 생겨 문의글 남깁니다. where 다중 조건을 사용하면 좋은 점이 메소드를 사용할 수 있어 재사용이 용이하다고 하셨는데요, BooleanBuilder를 메소드로 빼서 사용하는 것과의 차이점이 궁금합니다.
-
미해결실전! 스프링 부트와 JPA 활용2 - API 개발과 성능 최적화
API 설계시 게시글과 댓글
안녕하세요 강사님. http, 스프링, jpa 모두 강사님 수업을 듣고 인생 첫 스프링 프로젝트로 게시판 API를 구현 해 보려고 하는 대학생입니다. 그래서 현재 아래와 같이 요청경로와 요청법, 응답 본문, 에러응답 등을 문서화 하고 있습니다. 경로를 올바르게 설계했는지는 잘 모르겠지만, 게시글 정보 반환시 게시글과 댓글관계에 대해 궁금해서 질문 드립니다. GET /boards/{board-id}/posts/{post-id} 으로 요청시 게시글의 작성자id, 제목, 내용등이 반환되는데, 댓글들의 목록도 포함시킬지 고민입니다. 보통 게시글이 댓글을 가지고 있으니깐 처음에는 댓글 요청경로를 빼고 게시글 요청에 당연히 포함시켜야 하지 않나? 생각을 했습니다.그런데 댓글에 페이징 기능까지 넣으려고 생각하니깐 게시글과 댓글을 분리해서 게시글정보와 댓글 정보를 각각 받아오도록 하는게 좋을 것 같다는 생각이 들었는데, 혹시 현업에서도 댓글과 게시글은 분리해서 각각 따로 가져오게 설계를 하는지 궁금합니다. 추가적으로, 이건 강사님의 HTTP수업과 관련된 질문이긴한데 게시글,유저 등록같은 POST /boards/{id}/posts 의 201 응답 Location 헤더에 생성된 자원의 주소(예를들어 http://localhost:8080/boards/1/posts/1)가 어차피 포함되어 오는데, 응답 본문에 생성된 자원(게시글)을 다시 보내주는게 RESTful API에 더 가까운가요? 생각해보면 생성된 자원의 위치를 어차피 알려주는데 의미없는 오버헤드인 것 같더라구요.
-
미해결자바 ORM 표준 JPA 프로그래밍 - 기본편
abstract
안녕하세요 강사님, 질문 드리겠습니다. 세 가지 방법 모두 부모를 abstract로 생성해야 하나요? 조인 전략은 Item이 따로 존재하면서 조인을 통회 조회하는 것이니 abstract이 아니어야 하는 게 맞나 싶기도 해서요;;
-
미해결실전! 스프링 부트와 JPA 활용1 - 웹 애플리케이션 개발
안녕하세요 제가 이해한게 맞는지 애매합니다.
저는 기존에 spring과 mybatis를 사용하다 강의를 듣게되어서 service와 mapper의 역할이 딱 나뉘어진 코드에 익숙했는데 엔티티에 로직이 들어가니 조금 당황스럽네요 ㅎㅎㅎ... 각설하고 다른 질문들을 보았지만 명쾌하게 이해되지는 않아서 강의 내용과 제가 생각한 내용들로 이해해봤는데 맞는지 확신이 안서서 질문드려요 1. 회원 파트와 주문파트의 엔티티 구성방식이 다른 것(생성메서드,비즈니스 로직등의 유무) 은 회원은 기능구현시 타 엔티티와 상호작용하는 부분이 없어 간단한 구현이라는 판단아래에 별 로직이 없고 주문파트는 상호작용하는 부분(주문 취소시 수량 복구, 주문이라는 행위시 연관되는 엔티티정보들) 이 있기에 많은 로직이 있다는 걸로 받아들이면 될까요? 2. 주문 취소의 경우 서비스 부분에 들어가는게 맞다고 생각했는데 엔티티에 구현하셔서 질문들을 찾아보니 취소가 되기 위해선 주문엔티티의 배달상태의 정보가 바뀌고,수량 복구가 되어야하고 해당하는 정보들이 가장 가까운 Order와 OrderItem엔티티에서 로직을 수행한다는 말씀이시고 이게 객체지향 스럽다? 라고 이해하면 될까요?
-
미해결실전! Querydsl
@Transaction에 대해서 질문드드립니다.
안녕하세요? 강사님. 항상 좋은 강의 잘 보고 있습니다. 이번강의를 보면서 에러가 발생하였습니다. Member member = new Member("member1", 10);memberRepository.save(member);Member findMember = memberRepository.findById(member.getId()).get();assertThat(findMember).isEqualTo(member); assertThat부분에서 <"Member(id=1, username=member1, age=10) (Member@1b444b5)"> to be equal to: <"Member(id=1, username=member1, age=10) (Member@5a1a20ae)"> but was not. Expected :Member(id=1, username=member1, age=10) Actual :Member(id=1, username=member1, age=10) 이러한 에러가 발생했습니다. 알고보니 @Transaction 어노테이션을 선언을 안해서 그랬습니다. member와 findMember의 메모리 주소가 달라서 에러가 발생한것 같은데 메모리가 주소가 왜 다른지 잘 이해가 안됩니다. meber객체를 save 하면서 영속성 컨텍스트에 담기고 findMember는 영속성컨텍스트에 담겨있는 member인것이 아아니라 새로 select문을 날려서 디비에서 조회한 값이더라구요( @Transactional이 없을 때 로그를 통해서 확인하였습니다) @Transactional을 선언 하고 save 후 em.flush(); em.clear();를 해준것과 같은 현상이 나더라구요. @Transactional이 롤백외에도 어떠한 기능이 있길래 이러한 현상이 나타나는지 알고 싶습니다. 감사합니다.
-
해결됨자바 ORM 표준 JPA 프로그래밍 - 기본편
선생님 함수 타입 질문입니다.
선생님 약간 논외질문이긴한데 ㅜㅜ count나 알려주셨던 기본 함수들의 반환형을 어떻게 확인해야할지 모르겠습니다. count함수를 이용해서 뽑아보려고하는데 결국 구글검색으로 long 타입으로 뽑으면 알 수 있다고 해서 알았습니다. 혹시 count나 다른 기본함수들에 대해서 제가 반환형을 알 수 있는 방법이 있을까요? 이런식으로 계속 object 타입으로 호출했습니다... String query= "select count(m) from Member m";Query emQuery = em.createQuery(query);List resultList = emQuery.getResultList();for (Object o : resultList) { System.out.println("object= " + o);}