30%
61,600원
다른 수강생들이 자주 물어보는 질문이 궁금하신가요?
- 미해결실전! 스프링 데이터 JPA
상황에 따라 DB table 칼럼이 추가 또는 변경시 jpa 에서 어떻게 다룰수 있나요?
안녕하세요 김영한님 오랜만에 질문을 남깁니다. 프로젝트 중간중간 jpa 관련 의문점이 들때마다 다시한번 책과 이 강좌가 많은 참고가 됩니다. 이 자리를 빌어 다시한번 감사드립니다^^ 제목에서처럼 테이블명과 기본 구조 칼럼은 그대로이나 상황에 따라 아래의 code000 칼럼의 갯수가 추가 또는 삭제가 되는 그런 구조인데 jpa에서 어떻게 다룰 수 있는지 궁금합니다.
- 미해결실전! 스프링 데이터 JPA
LazyInitializationException 에러 관련 질문 드립니다.
안녕하세요. LazyInitializationException 예외 관련 질문 드립니다. 우선 Employee 와 Company 라는 엔티티가 N:1 관계로 셋팅 되어 있고(ManyToOne으로 설정 했고 조인 컬럼도 명시 했으며, OneToMany쪽에는 mappedBy도 맞게 설정 하였습니다. 양쪽 다 모두 Lazy로딩으로 해놨구요), JpaRepository도 각각 적절히 셋팅되어 있으며, 다음과 같은 서비스 클래스가 있다고 가정했을 때, @Service class CompanyService { @Autowired EmployeeRepository employeeRepository; // JpaRepository를 상속한 인터페이스 @Transactional public test() { Employee employee = employeeRepository.findById(1L); // LazyInitializationException 예외 발생 Company company = employee.getCompany(); // could not initialize proxy - no session 예외 발생 } } Employee employee = employeeRepository. findById(1L) 을 호출 하면, 디버거에서 보이는 employee 객체 내의 company 값은 실제 객체 대신 다음과 같은 예외가 보입니다. method threw 'org.hibernate.LazyInitializationException' exception. Can not evaluate com....$HibernateProxy$lfgdgjt.toSting() 그리고 employee의 getCompany를 호출 하는 순간, could not initialize proxy - no session 이라는 예외가 발생합니다. 지연 로딩 시 영속성이 유지 되어야 하지만 findById 의 호출이 끝나는 순간 트랜잭션이 종료 되고 세션이 닫히는 게 이유가 아닐까 싶어, 트랜잭션 어노테이션을 서비스 레이어의 메소드에 추가도 해보고 전파 속성도 여러가지로 바꾸어 봤지만 문제가 해결되지 않았구요.. EAGER 로딩으로 바꾸 거나, 아래 속성을 줄 경우에 해결이 되었습니다.. enable_lazy_load_no_trans=true enable_lazy_load_no_trans속성이 자칫 N+1 문제를 야기할 수 있어 안티 패턴인 것 같아 근본 원인을 알고 싶은데요.. 물론 페치 조인으로도 해결 할 수 있지만, 위의 예제 코드도 당연히 동작을 해야 할 것 같은데 왜 트랜젝션 어노테이션을 주었음에도 영속성 세션이 test() 메소드 내에서 지속 되지 않는지 궁금합니다. --- 추가로 트랜잭션 로그를 찍어 보았는데 이벤트 순서가 아래와 같습니다.. test() 메소드의 트랜잭션 생성, EntityManager 열림 => findById() 가 호출 => SimpleJpaRepository의 inner transaction이 생성 및 새로운 EntityManager열림 => findById 메소드 호출 종료 => commit & inner transaction 종료 => EntityManager 닫힘 => test()메소드의 트랜잭션 resume 결국 inner트랜잭션이 별도로 생성되는게 문제인 것 같은데 이게 트랜잭션 propagation을 REQUIRE로 해도 각각 별도의 트랜잭션을 생성하고 있습니다. 어떤 부분을 더 의심하고 디버깅 해봐야 할까요?
- 미해결실전! 스프링 데이터 JPA
unable to locate persister 에러 관련 질문 드립니다.
JpaRepository 를 상속 하지 않고 아래와 같은 클래스를 만들어 entityManager로 데이터를 가져오는 테스트를 하려고 하는데요. @Repository public class Test Repository { @PersistContext EntityManager entityManager; public Employee findEmployee(Long id) { return entityManager.find(Employee.class, id); } 아래와 같은 에러가 발생 합니다. (stack trace의 가장 아랫 부분만 발췌 했습니다.) org.hibernate.UnknownEntityTypeException: Unable to locate persister: com.xxx.xxx.... persister는 spring-boot-starter-data-jpa를 의존성에 추가 해 줬을때 hibernate도 하위 의존성으로 따라서 추가되면서 자동으로 persister 로 등록 되는게 아닌가 생각했었는데요.. 왜 이런 에러가 나는 걸 까요?
- 미해결실전! 스프링 데이터 JPA
Pageable
영한님 안녕하세요. 강의를 듣다가 궁금한 점이 생겨 질문드립니다. @GetMapping("/members") public Page<Member> list(Pageable pageable) { ... } Pageable을 컨트롤러 메소드의 인자로 받으면 sort 조건에서 entity 필드명을 사용해야 되는데 이 부분도 엔티티가 드러나면 안되는거 아닌가요? - /members?page=0&size=3&sort=username,desc - 조인 한 경우, 조인된 테이블을 기준으로 정렬 할 때 ?sort=m.user.id
- 해결됨실전! 스프링 데이터 JPA
@Transaction에 대한 궁금중
안녕하세요 영한님. 강의를 들으면서 문득 @Transaction의 위치와 중첩에 대해서 궁금중이 들어서 제 나름대로 몇가지 테스트를 해봤습니다. 첫 번째로, 리포지토리 레이어에 트랜잭션이 적용되어 있고 해당 리포지토리의 메서드를 사용하는 서비스 레이어에도 트랜잭션이 적용되어 있다면 flush는 두 레이어 중 어느 시점에 발생할까 궁금했습니다. 그래서 테스트를 해본 결과 최종적으로 서비스 레이어의 트랜잭션이 끝나는 순간에 모든 쿼리가 적용되는 것을 볼 수 있었습니다. 두 번째로, 위와 동일한 상황에 서비스 레이어의 트랜잭션 옵션만 readOnly라면 리포지토리의 save 메서드는 실제 db에 저장을 할까 궁금해서 테스트해봤습니다. 결과는 물론 서비스 레이어 트랜잭션이 우선이기에 insert 쿼리는 발생하지 않았습니다. 두 테스트를 통해서 트랜잭션 우선권은 좀 더 넓은 범위(?), 즉 요청과 응답에 가까운 레이어의 트랜잭션을 따라간다고 이해가 됩니다. 그렇다면 제 생각에는 컨트롤러에 트랜잭션을 적용한다면, OSIV를 사용하지 않아도 영속성 컨텍스트가 화면을 띄울 때까지 유지될 것 같은데 막상 해보면 no Session 에러를 뿜내요.. 컨트롤러에서 html 파일을 렌더링해서 반환하는게 아니라 컨트롤러에서 정적 파일로 일단 반환하고 트랜잭션이 종료된 후에 따로 렌더링하는 작업을 거쳐서 그런걸까요? 쓰다보니 말이 길어져서.. 죄송합니다 ㅎㅎ..
- 해결됨실전! 스프링 데이터 JPA
@Modifying에 관한 질문
안녕하세요 영한님!이번 강의로 Modifying 어노테이션의 clearAutomatically 옵션이 왜 필요한건지 잘 이해했습니다. 그런데 다른 옵션인 flushAutomatically는 제가 아는 상식과 충돌이 되서 질문드립니다.기본적으로 createQuery를 날리면 db에 직접 접근하여 처리하기 때문에 현재 영속성 컨텍스트의 1차 캐시에 있는 것들을 강제로 flush하고 작성한 쿼리를 날리는 것으로 이해를 하고 있습니다.벌크연산 역시 createQuery의 일종이라고 생각하기 때문에 flushAutomatically 옵션의 기본값은 true일 거라고 예상했는데 false로 되어있어서 헷갈립니다.1. Modifying에서 제공하는 자동 flush 옵션과 벌크 연산전에 자동으로 일어나는 flush는 의미가 서로 다른건가요?//추가: 구글링을 해본 결과, 두 flush는 같은 의미가 맞고 @Modifying 옵션 값과 상관없이 hibernate에서 강제로 flush를 해준다고 합니다.그리고 이건 질문은 아니고 제가 정리한게 맞는지 여쭤봅니다.강의 영상처럼 테스트 클래스의 한 @Transaction 안에서 멤버를 생성하고 벌크연산으로 변경하고 조회하는 것이 아니라서비스 레이어에서 각각의 @Transaction가 있는 메서드로 분리해서 테스트를 해봤는데, 여전히 동일한 현상이 일어나더라구요.2. 이것은 OSIV에 의해서 영속성 컨텍스트의 생명주기가 트랜잭션의 종료시점이 아닌 최종적으로 response를 뱉을때까지 유지되고, 1차 캐시 역시 유지되기 때문에 각각의 트랜잭션에서 실행되는 서비스 메서드 간에서도 1차 캐시가 공유된다는 뜻으로 이해하면 될까요?
- 미해결실전! 스프링 데이터 JPA
javascript의 submit에서 controller 호출이 안되고 403 에러가 나요.
javascript를 이용하여 삭제에 대해 다시한번 확인을 요청하려 합니다. 기존에 form에 직접 method, action을 입력했을때는 controller의 delete함수가 잘 호출되었으나, javascript로 form을 작동시에는 controller의 delete함수가 호출되지 않고, 403 에러가 발생합니다. <form id = "deleteForm" > <input type="hidden" name="sdkVer" class="form-control" th:value="${item.sdkVer}" readonly> <input type="hidden" name="plfmCode" class="form-control" th:value="${item.plfmCode}" readonly> <input type="hidden" name="cntryCode" class="form-control" th:value="${item.cntryCode}" readonly> <input type="hidden" name="epgSettingId" class="form-control" th:value="${epg.epgSettingId}" readonly> <td> <button class="btn btn-primary " onclick="checkDelete()" >삭제</button> </td> <script type="text/javascript"> function checkDelete() { var check = confirm("삭제를 하시겠습니까?"); if(check == true){ var deleteForm = document.getElementById("deleteForm"); deleteForm.action='/delete'; deleteForm.method = 'post'; deleteForm.submit(); } else if(check == false){ document.write("취소를 눌렀습니다."); } } </script></form> @PostMapping("/delete")public String delete(Model model, @RequestParam Map<String , String> attributes) throws IOException { System.out.println("HomeController.delete"); System.out.println("attributes.get(\"plfmCode\") = " + attributes.get("plfmCode")); EpgId originalEpgId = new EpgId(attributes.get("epgSettingId"), attributes.get("plfmCode"), attributes.get("sdkVer"), attributes.get("cntryCode"), "N"); itemService.delete(originalEpgId); return post_detail(new Item( attributes.get("plfmCode"), attributes.get("sdkVer"), attributes.get("cntryCode")), model);}
- 미해결실전! 스프링 데이터 JPA
EntityGraph 메서드 이름으로 쿼리 생성 질문
안녕하세요! 복습하다가 조금 의아한 부분이 있어서 질문드립니다. 19:20 초 메서드 이름으로 쿼리 생성에 페치 조인을 시켜주기 위해 @EntityGraph를 붙여주신 부분에서 질문입니다. 여기서 파라미터에 @Param을 붙여주는 이유가 뭔가요? @Param은 @Query방식에서 파라미터 바인딩하려고 사용했는데 메서드 이름으로 쿼리 생성해주는 경우에는 사용할 필요가 없는게 아닌가 해서 질문드립니다. 만약 여기서 @Param을 붙여줘야 하는게 맞다면 메서드 이름으로 쿼리 생성에서 설명해주셨던 List<Member> findByUsernameAndAgeGreaterThan(String username, int age); 에서는 @Param을 붙이지 않으셨는데 어떤게 맞는 걸까요?
- 미해결실전! 스프링 데이터 JPA
query가 너무 힘든에ㅛ
@Repositorypublic interface ItemRepository extends JpaRepository<Epg, EpgId> , JpaSpecificationExecutor<Epg> { List<Epg> findByPublishFlag(String publishFlag); @Query ("SELECT new com.example.demo.model.Item (epg.plfmCode, epg.sdkVer,epg.cntryCode) FROM Epg epg group by epg.plfmCode, epg.sdkVer, epg.cntryCode where epg.publishFlag = 'N'") Page<Item> getGroupByItem(Pageable pageable);} new의 개념은 알겠으나... 제가 힘든부분은 저 where절이 꼭 필요하다는 부분입니다. where 절을 빼면 잘작동하는데 where절을 꼭넣어야합니다. 오늘 하루종일 시도해보았으나... 쿼리문을 짜기가 힘드네요.... nativeSQL로도 해봤으나 잘되지않네요
- 미해결실전! 스프링 데이터 JPA
getResultList에 대한 질문
interface repository를 사용하다가 select distinct 쿼리가 필요하여 직접 repository를 새로 만들었습니다. private final EntityManager em;public List<Item> getGroupByItem() { List<Item> items = (List<Item>) em.createQuery("SELECT distinct plfmCode, sdkVer,cntryCode FROM Epg epg where epg.publishFlag = 'N'").getResultList(); return items;} 쿼리가 잘 수행되어 items를 잘받아오나, Object[] 가 List<Item>으로 자동casting이 되지않더라구요.. 이방법 저방법 찾아봐서 바꾸어봤지만 되질 않네요;;;;
- 미해결실전! 스프링 데이터 JPA
group by multiple columns
혹시 entity의 일부변수로 grouping한 Dto가 팔요한데.. 스프링부트에서 자동으로 매핑해주는 방법이 있나요? 아니면 queryDSL로 가져와서 mapping해야하나요? public class Item { private String plfmCode; private String sdkVer; private String cntryCode; //private List<Epg> epgs;}
- 미해결실전! 스프링 데이터 JPA
userRepository가 수정시 값을 가져오지 못합니다.
안녕하세요. 선생님강의를 벌써 4개 수강하고 있습니다. 제가 회사에서 맡은 프로젝트 중에 @createBy, @lastModifiedBy 값을 사용하여 사용자 정보를 itemRepository에 넣어야하는 게 있습니다. 선생님 강의 auditing과 듣고 마찬가지로 헀는데... 이게 이상한것은 insert시는 user repository에서 user의 정보를 잘 가져오는데... update시는 user repository의 값을 가져오지 못하고 nullable을 에러가 납니다. auditing기능은 잘 작동하는데.. 아무래도 item repository가 연결되어있어서 user repository값을 가져오지 못하나라는 생각이 들다가.... insert시에는 유저 아이디를 잘 가져와 넣는데 수정시에만 유저아이디 찾는 로직이(user.findByuserName)이 nullpoint에러가 난다는 것입니다. 며칠째 삽집할다가 여쭤봐요 ㅠㅠ
- 미해결실전! 스프링 데이터 JPA
insert에 대해서 문의드립니다.
안녕하세요 김영한님:) 실무 적용 중에 궁금한게 있어서 문의 드리는데요. 보통 entity내에 joinColumn이든 mappedBy든 연관관계를 성립 시켜주는데요 그냥 단순히(?) 주문생성(주문관련된 테이블들에 insert이 이루어짐)만 이루어진다면 굳이 연관관계 맵핑을 하지 않고 각 주문관련 테이블들에 하나씩 컨트롤 하면서 insert 하는게 편리할 것 같다는 생각이 들어서.. 이런 접근 방법이 맞을까요? 물론 테이블 간 FK로 묶여 있는 테이블들도 있긴 한데 이런 경우는 위 처럼 하면 JPA의 객제관점으로 테이블에 접근 하는 관점에서는 어긋나는것 같기도 하고...영한님의 의견은 어떠실까요? 참고로 이 서비스는 사실상 주문관련 테이블은 insert만 이루어지고 select는 상태값 정도 조회하는 신규 api 입니다. 쿼리가 아닌 JPA 관점에서 접근하는 게 생각보다 딱 이거다 이런게 명확하지 않으닌까 생각이 진짜 많아지는것 같아요 ㅠㅠ 감사합나다.
- 미해결실전! 스프링 데이터 JPA
안녕하세요 궁금한게 있어서 질문 하나 드려봅니다!!!
강사님 언제나 강의 잘듣고 있습니다 감사합니다.다름이 아니라 Item 의 @Id 타입이String 으로 변경되었는데ItemRepository 안 JpaRepository 값을 Long -> String 으로 바꿔야 하지 않나요?? 바꾸지 않고 진행을 해도 save 는 잘돌아 가던데 (그외 Id 의 타입이 필요한 method 호출시는 오류가 뜨지만..)그럼 실질적으로 PK 값으로 굳이 넣지 않아도 되는건가요??
- 미해결실전! 스프링 데이터 JPA
엔티티 매핑 default 값
영한님 안녕하세요! 영한님은 엔티티 매핑시 default 값을 어떻게 넣는지 궁금해서 질문 드립니다 몇 가지 방법을 생각해 보았는데 1. @Prepersist를 통해 넣는다. 2.밑과 같이 그냥 값을 넣어준다. 제가 생각나는건 2개정도인데 영한님은 어떤식으로 default값을 넣어주시나요?
- 미해결실전! 스프링 데이터 JPA
update 관련해서 질문 드립니다.
안녕하세요. 김영한님:) 영한님의 JPA강의를 들으면서 실무에 바로바로 적용하는 중에 있는데요. 1. 엔티티에 setter를 사용 하지 않고 수정 및 데이터 저장시 entity내에 메소드를 만들어서 사용하는걸 권장해주셨는데, 큰 덩어리(?)에 entity에서 하나의 컬럼만 수정이 될 때도 말씀주신 메소드를 만들어서 사용 하는게 좋을까요? 2. prodQty = prodQty + 1 이렇게 바로 DB 컬럼만으로 update가 가능한것도 select한 것을 param으로 넘겨서 메소드로 만들어서 하는게 좋은걸까요? 개인적으로 repository내에 @Modifying을 이용해서 만드는게 더 가식적인고, 한개의 업데이트를 사용하기에도 더 편리해보인다는 라는 생각도 들어서요(물론 @Modifying은 벌크성 update에 주로 이용한다고 하셨지만...) JPA에 익숙하지 않는 습성(?)때문에 그렇게 느껴지는 부분일까요? 더티체킹이라는 JPA는 장점을 살리지 못한 생각일까요? 강의 들을때 이해가 퐉퐉! 되었는데 막상 실무에선 작은것도 많은 고민을 하게 되네요 ㅠㅠ 감사합니다.
- 해결됨실전! 스프링 데이터 JPA
Update관련 질문드립니다
안녕하세요 영한님 강의 항상 잘 보고있습니다. 강의를 보면서 Update는 Dirty Checking을 통해서 해라!(단건) 라고 이해를했는데요 궁금한 부분은 정말 단순하게 컨트롤러로 DB에 있는 어떤 값을 변경하는 API가 있다고 하면 해당 엔티티를 조회하고 이 엔티티에 값을 바꾸면 select 쿼리 한번 update 쿼리 한번이 나가게 되는데 다른 JDBCTemplate 이나 Mybatis 쓰면 update 쿼리한번이면 될텐데 라는 생각이 들더라구요 물론 DB에 데이터를 있는지 없는지 체크도 되는 이점도 있긴하겠지만 만약에 엄청 복잡해서 update를 하기위한 select를 해야하는 경우가 많다고 한다면 이부분이 성능에 미치는 영향이 크지는 않는건지랑 대비 이점?이 무엇인지 궁금합니다~
- 미해결실전! 스프링 데이터 JPA
entity listener 관련 질문드립니다.
안녕하세요, 강의 자체와 밀접한 관련은 아니지만, entity listener을 사용해보려던 중 궁금한 점이 생겨 질문드립니다. postUpdate, preUpdate ... 등등 엔티티가 변경되거나 등록되거나 삭제된 전후로 감시하는 것이 아니라, 항시 감시하려고 할 때도 entity listener을 이용하나요? 원하는 로직은, 상품 엔티티가 있고, 유통기한 컬럼을 감시해서 날짜가 지났을 시 삭제하는 등의 처리를 하고 싶습니다. 이러한 경우에는 어떤식으로 사용할 수 있을지 질문드립니다. 항상 좋은 강의 감사합니다.
- 해결됨실전! 스프링 데이터 JPA
@Trasacntion 롤백 관련 질문있습니다.!
안녕하세요 ~ 강사님. JPA는 트랜잭션 단위에서 RuntimeException이 발생하면 롤백을 진행한다고 배웠는데요~ 실습중에 예외 케이스를 발견해서 질문 드립니다.!! @SpringBootTest@Transactional@Rollback(value = false)class HumanTest { @Autowired HumanRepository humanRepository; @Autowired EntityManager em; @BeforeEach void setup() { Human human = new Human(); human.setName("human"); humanRepository.save(human); } @Test void t1() { List<Human> all = humanRepository.findAll(); Human human = all.get(0); human.setName("person"); throw new IllegalArgumentException(); // rollback }} 테스트에서 분명 예외가 발생했기 때문에 db에 human을 조회하면 name이 `human`이 나올거라 예상했는데, person이 나오더라고요..!! 이거 관련해서 답변을 얻을 수 있을까요? 좋은 강의 항상 감사합니다.
- 미해결실전! 스프링 데이터 JPA
@MappedSuperclass대신 임베디드 타입
안녕하세요 영한님! 강의 정말 잘 듣고 있어요! 이번강의를 듣다고 궁금한 점이 생겼는데요 등록일이나 수정일을 임베디드 타입으로 처리하지 않고 @MapperSuperclass로 채택해 구현한 이유가 단순히 수정일과 등록일은 데이터 참고용 컬럼이라 그런건가요? 임베디드 타입보다 등록,수정일을 @MapperSuperclass로 구현한 부분에대한 장점이 따로 있을까요?