25%
66,000원
다른 수강생들이 자주 물어보는 질문이 궁금하신가요?
- 미해결실전! 스프링 데이터 JPA
h2 In-Memory에서 rollback
안녕하세요! 강의를 듣고 강의를 토대로 혼자 이것 저것 해보고 있는 학생입니다! 다름이 아니라 강의와 다르게 h2를 spring boot 가 실행 될 때 메모리에서만 동작하게 하고싶어서 JDBC URL 을 jdbc:h2:mem/test 라고 지정을 했습니다. 그리고 문제는 @Test 어노테이션이 붙은 테스트 클래스에서 발생하였는데요, RepositoryTest 에서 @Transactional과 @Rollback(false) 를 추가시켰음에도 불구하고 spring boot가 돌아가는 8080/h2-console 에서는 자동으로 rollback이 되는데, 혹시 어떤게 문제인지 알 수 있을까요? // MemberRepositoryTest @SpringBootTest @Transactional @Rollback(false) class MemberRepositoryTest { @Autowired private MemberRepository memberRepository; @Test @DisplayName("이메일로 조회") void read() { // given String email = "dhslrl321@gmail"; String password = "hwi199"; String nickname = "dhslrl321"; Member member = Member.builder() .email(email) .password(password) .nickname(nickname) .build(); memberRepository.save(member); // when Optional<Member> memberOptional = memberRepository.findByEmail(email); // then memberOptional.ifPresentOrElse( m -> assertEquals(nickname, m.getNickname()), Assertions::fail ); } } // application.yml spring: h2: console: path: /h2-console enabled: true settings: web-allow-others: true datasource: driver-class-name: org.h2.Driver url: jdbc:h2:mem:auth username: sa password: jpa: hibernate: ddl-auto: create-drop properties: show_sql: true format_sql: true
- 미해결실전! 스프링 데이터 JPA
jpa merge 관련 문의 드립니다.
안녕하세요. 항상 좋은 강의 감사드립니다. 새로운 엔터티를 구별하는 방법에서 궁금한 부분이 있어 질문 드립니다. 일반적으로 수정을 위해 findById를 통해 Entity 객체를 영속화 시킨 후 필요한 칼럼을 변경처리 하고 있습니다. 이러면 변경감지를 통해 트랜잭션 종료 구간에서 자동 update 쿼리가 발생이 되는데요... 만약 이 상태에서 repository.save(entity)를 수행하게 되면 혹시 문제가 발생할 만한 포인트가 있는지 궁금합니다. 내부 로직을 보면 아마도 save()에서 SPring Data JPA가 merge를 수행할것 같은데요... 보통 준영속성 상태 객체를 merge하는건 좋은 방법이 아닌것 같지만 이 처럼 findById를 통해 영속화 되어 있는 객체를 merge 하게 되면 혹시나 별도 주의사항이 있지는 않는지 문의 드립니다. 감사드립니다.
- 미해결실전! 스프링 데이터 JPA
안녕하세요 선생님!
안녕하세요 선생님 강의 잘 듣고 있습니다. 어느새 선생님 강의를 다 듣고 이제 데이터 JPA, 쿼리dsl만 남겨놓고 있습니다. 지금 데이터JPA를 들으면서, 제가 과연 데이터 JPA를 이용해서 생략한 코드들을 제가 자유자재로 짤 수 있을까에 대한 의문이 생깁니다. 실무에서 당연히 data jpa를 사용한다고 하지만 저 혼자서 jpa코드도 짜본적 없이 data jpa를 사용해도 될지 잘 모르겠습니다. 원래는 jpa 실전1까지 강의를 듣고 토이프로젝트를 바로 시작하려다가 다른 분께서 똑같은 질문을 남긴것에 대한 선생님의 답변을 봤었는데, 그때 선생님께서 강의를 다 듣고나서 진행해야 시간낭비가 덜 하다고 하셨습니다. 그래서 강의를 다 듣고 토이프로젝트를 진행하려고 계획을 했지만, 지금 data jpa 강의를 들으면서 앞서 언급드린 의문이 생깁니다. 그래서 제 생각에는 동적쿼리 문제는 결국 쿼리dsl로만 해결하는것이 국룰이니까 쿼리dsl까지만 듣고 토이프로젝트를 시작하는 것이 좋지 않을까 합니다. data jpa는 실무에서 필수이긴 하지만 당장 배우지 않는다고 엄청나게 큰 손해를 보는 것은 아닌것 같습니다. 그래서 제 결론은 1. data jpa, 쿼리dsl 강의만 남겨놓은 상황에서 바로 토이프로젝트(동적쿼리를 사용하지 않는 토이프로젝트) 진행 후 남은 두 개의 강의를 진행하는것 2. 쿼리dsl까지 듣고 토이프로젝트 진행 후 데이터 jpa를 진행하는 것 3. 그냥 강의를 다 듣고 지금까지 배운 기술들을 합친 토이프로젝트를 진행하는것 중에 선생님께서는 어느것을 추천하시는지 여쭙고싶습니다! 긴글 읽어주셔서 감사합니다!!
- 미해결실전! 스프링 데이터 JPA
MySQL의 JSON타입에 관해서
강의 재밌게 잘 보았습니다. 감사합니다. 한가지 문의 드리고 싶은 내용이 있어 여기에 글 올려봅니다. Entity중 객체 타입 속성을 json으로 변환해서 MySQL db의 json타입 컬럼으로 다루고 싶은데 어떻게 하면 될까요? 구글링 해보면 JPA의 conver로 해결 된다고 해서 아래와 같이 시도해보고 있는데 잘 안되네요.. 혹시 좋은 방법 있을까요. @Entity class ItemEntity { @Id @GeneratedValue private Long id; @Convert(converter = BookJsonConverter.class) private BookJson bookJson; } @Data class BookJson { private Long id; private String name; } class BookJsonConverter implements JsonConverter<BookJson> { // 이렇게 하는 이유는 BookJson같은 애들이 너무 많아서.... } public interface JsonConverter<T> implements AttributeConverter<T, String> { @Override default String convertToDatebaseColumn(T dataObj) { return new ObjectMapper().writeValueAsString(dataObj); } @Override default T convertToEntityAttribute(String dbData) { return new ObjectMapper().readValue(dbData, new TypeReference<>() {}); // <---- 여기서 hashMap을 반환하면서 결국 BookJson으로 cast시 에러 발생..... } }
- 해결됨실전! 스프링 데이터 JPA
fetch join 수행시 우선순위?
항상 강의 잘 듣고 있습니다. 감사합니다! fetch join을 할 때 기본적으로 left outer join이 수행된다고 하셨는데 그 전 강의에서는 대부분 Inner join으로 수행됐던것같아서. 질문드렸습니다! 수행하는 우선순위가 따로 있는건가요?
- 미해결실전! 스프링 데이터 JPA
PDF 오류일까요?...
안녕하세요. 강의영상 소스코드와 PDF 소스가 꼭 맞아야되는지는 모르겠으나...실습하면서 잠깐 헤매서 내용 공유드립니다. 영상에서 @Query 등록시 @Query("select new study.datajpa.dto.MemberDto PDF 내용 @Query("select new study.datajpa.repository.MemberDto
- 미해결실전! 스프링 데이터 JPA
연관관계매핑에서 @ManyToOne의 Id
삭제된 글입니다
- 미해결실전! 스프링 데이터 JPA
스냅샷이란..?
선생님 강의 정말 잘 듣고있습니다!! 선생님이 QueryHint에서 readOnly를 켜주면 " 스냅샷을 안찍죠 . . . " 이러셨는데 이떄 스냅샷이 JPA 영속성컨텍스트(1차캐시) 를 의미하는 건가요?
- 미해결실전! 스프링 데이터 JPA
선생님 pdf파일 55페이지 오타있어요
Pageable, Page를 파리미터와 응답 값으로 사용히자 않고 => Pageable, Page를 파리미터와 응답 값으로 사용하지 않고
- 미해결실전! 스프링 데이터 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;}