묻고 답해요
161만명의 커뮤니티!! 함께 토론해봐요.
인프런 TOP Writers
-
해결됨스프링 입문 - 코드로 배우는 스프링 부트, 웹 MVC, DB 접근 기술
Autowired순서
안녕하세요 강의를 듣던 중 궁금한점이 생겨 질문드리게되었습니다. MemberService에서 @Autowired 를 통해 MemberRepository를 주입시키는 과정에서 MemberRepository가 MemberService 보다 먼저 빈등록이 되어있다면 문제가 없겠지만 MemberRepository가 MemberService 보다 늦게 빈등록이 될경우 문제가 생길것 같은데 어떻게 작동하나요? 즉, 빈등록되는 순서가 궁금합니다. 읽어주셔서 감사합니다
-
미해결자바 ORM 표준 JPA 프로그래밍 - 기본편
스프링 커뮤니티
스프링 커뮤니티에 자주 올라오는 질문 이라고 하셨는데 따로 이용하시는 스프링 커뮤니티가 있나요?
-
미해결스프링 입문 - 코드로 배우는 스프링 부트, 웹 MVC, DB 접근 기술
안녕하세요 강사님
안녕하세요 강사님 질문있습니다. 강의 목록 중에 "실전! 스프링 웹 MVC 출시 예정 - 2월" 인 부분이 있는데 언제 나오는지 알 수 있을까요??
-
해결됨자바 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표시), 혹시 이렇게 표시되는게 정상적인 것인지 혹은 맵핑 과정에서 실수가 있었던지 궁금하여 질문 드립니다!
-
해결됨실전! 스프링 부트와 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이 아니어야 하는 게 맞나 싶기도 해서요;;
-
미해결스프링 입문 - 코드로 배우는 스프링 부트, 웹 MVC, DB 접근 기술
의존성 주입 방식, 컴포넌트스캔과 자바설정방식 관련질문입니다
안녕하세요! 강의 너무 잘 보고 있습니다. 스프링 혼자 공부해보려다가 넘 어려워서 안하게 됬는데, 흥미롭게 진행해주시는 강의듣고 조금씩 알아가는 것 같아 스스로도 기쁘고 감사합니다.ㅎㅎ 질문1 [스프링 빈과 의존관계]-[자바 코드로 직접 스프링 빈 등록 하기] 강의 7분 26초 에서 setter 주입 방식의 단점으로... 어플리케이션 로딩 시점에 한번 세팅되고 나면 이 멤버변수는 바꿀 일이 없는데 public으로 노출되게 된다는 점이 단점이라고 설명해주셨습니다. 그런데 6분 0초 필드 주입방식을 설명해주실 때 단점으로... 스프링이 시작될 때, 초기에만 설정되고 개발자가 동적으로 바꿀 수 없어서 추천하지 않는 방식이라고 설명해주셨는데요! 질문은! 어플리케이션 로딩 시점에 한번만 세팅되면 되는 거면, 필드 주입방식에서 초기만 설정되고 나중에 바꿀 수 없다는 점이 왜 단점이 되는 건지 이해가 잘 안됩니다! 한번 더 단점을 정리해주실 수 있을까요? 질문2 [스프링 빈과 의존관계]-[자바 코드로 직접 스프링 빈 등록 하기] 강의 2분 40초 에서 memberRepository() 메소드 반환형을 왜 MemoryMemberRepository 타입으로 하지 않고, 인터페이스 타입으로 하신 건지 궁금합니다. + 11분 25초 부분까지 강의를 들으니 알겠네요. ^^상황에 따라 다른 데이터베이스를 연결하는 내용의 리포지토리를 연결할 때, 서비스나 컨트롤러 코드를 변경하지 않고, 아래 파일에서 new 하는 객체만 원하는 리포지토리로 바꿔주면 되니까 그런거군요! package hello.hellospring.service;import hello.hellospring.repository.MemberRepository;import hello.hellospring.repository.MemoryMemberRepository;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;@Configurationpublic class SpringConfig { // @Bean : spring bean을 등록할 거라는 의미 @Bean public MemberService memberService(){ return new MemberService(memberRepository()); } @Bean public MemberRepository memberRepository(){ return new MemoryMemberRepository(); }} 질문3 : 컴포넌트스캔방시과 직접자바설정방식 차이 잘 이해한건지 확인부탁드립니다. 컴포넌트 스캔방식 : 스프링은 @Controller, @Service, @Repository 어노테이션이 붙은 것들을 빈으로 등록해 관리한다. @Autowired로 각 빈들을 연결해준다. 직접자바설정 방식 : @Configuration과 @bean으로 스프링에 빈을 등록한다. @Autowired로 각 빈들을 연결해준다. 그런데, 이 강의에서 직접 자바 config를 만들때, @Service, @Repository, @Autowired는 지웠는데, @Controller 은 지우지 않았습니다. 이유가 무엇인가요?
-
미해결실전! 스프링 부트와 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);}
-
미해결더 자바, Java 8
자바8 static 변수
안녕하세요 백기선님! static변수에 관한 질문이 있습니다 static 변수는 컴파일 시점에 메모리에 안착되어 프로그램이 종료될때 까지 살아있다. 그러므로 static 변수가 점유하고 있는 메모리는 가비지컬렉터에 의해 회수되지 않는다. 로 알고 있습니다. https://openjdk.java.net/jeps/122 아래는 해당링크의 일부 내용을 발췌한 것입니다. Class metadata, interned Strings and class static variables will be moved from the permanent generation to either the Java heap or native memory. The code for the permanent generation in the Hotspot JVM will be removed. Application startup and footprint will not regress more than 1% as measured by a yet-to-be-chosen set of benchmarks. 1. java8 부터는 static 변수/함수를 남발한다는 이유만으로 메모리 부족 문제가 생길 가능성이 희박해 진걸가요? 'static 변수를 남발해도 시스템에 크게 지장이없다?' 2. heap 영역으로 옮겼다면 GC의 관리영역으로 들어와서 mark & swap 인 가능해 진 건가요? 개발자 꿈나무입니다 ! 답변의 수준이 낮더라도 이해 부탁드리겠습니다 ㅠㅠ!