안녕하세요 Section2-5 강의 " Querydsl설정하기" 강의에서는 분명 repository 폴더 안에 search 폴더가 있었는데 강의를 듣다보니 강사님 화면에서는 search 폴더가 어느새 사라져있습니다.. 강의화면만 보고 어디있는지 알수가 없어서요ㅠ 어느 폴더로 이동해갔는지 알려주시면 감사하겠습니다. 그리고 강사님 화면을 보다가 발견했는데 config 폴더 아래에 RootConfig 파일이 새로 생겨있고, 깃 파일을 확인해보니 modelMapper를 사용하여 DTO 와 entity를 변환해주고 있는데, 앞에 강의에서 제가 듣기론 funciton을 이용해서 변환해주고 RootConfig 파일을 따로 만든 기억이 없습니다ㅠ 교육 뒷 부분에 새로 생기는 건가요?
[질문 내용] 여기에 질문 내용을 남겨주세요. 안녕하세요. 스프링 3.0 이상으로 프로젝트를 만들어서 h2 데이터베이스도 그에 맞는 최신 버전으로 다운 받아 설치하였는데요. jdbc:h2:~/jpashop로 최초 한번 연결 후 (여기까진 성공) 끊고, jdbc:h2:tcp:// localhost/~/jpashop 으로 연결하면 이 오류가 뜹니다. h2 데이터베이스는 켜둔 상태입니다. spring: datasource: url: jdbc:h2:tcp://localhost/~/jpashop username: sa password: driver-class-name: org.h2.Driver
자바와 스프링 부트로 생애 최초 서버 만들기, 누구나 쉽게 개발부터 배포까지! [서버 개발 올인원 패키지]
저희 학습내용으로 보면 private Integer age; 는 테이블의 age int, 와 같아서 어노테이션 안써도 된다고 하셨는데 그럼 name 같은경우도 테이블의 그냥 컬럼명과 타입 똑같은 조건인데 왜 어노테이션쓰고 nullable = false, length = 25라고 해야하나요?? 그리고 한가지만 더 질문 드릴게요! 저는 서버 실행하면 콘솔쪽에 따로 쿼리가 안찍히던데 왜그럴까요?? 이상은 없는데 hibernate가 인식이 안되서 그런건지 콘솔에 쿼리가 안찍히네요ㅠㅠ
학습하는 분들께 도움이 되고, 더 좋은 답변을 드릴 수 있도록 질문전에 다음을 꼭 확인해주세요. 1. 강의 내용과 관련된 질문을 남겨주세요. 2. 인프런의 질문 게시판과 자주 하는 질문(링크)을 먼저 확인해주세요. (자주 하는 질문 링크: https://bit.ly/3fX6ygx) 3. 질문 잘하기 메뉴얼(링크)을 먼저 읽어주세요. (질문 잘하기 메뉴얼 링크: https://bit.ly/2UfeqCG) 질문 시에는 위 내용은 삭제하고 다음 내용을 남겨주세요. ========================================= [질문 템플릿] 1. 강의 내용과 관련된 질문인가요? (예/아니오) 2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? (예/아니오) 3. 질문 잘하기 메뉴얼을 읽어보셨나요? (예/아니오) [질문 내용] 안녕하세요? 몇가지 이것저것 테스트하다 발견한 부분에 대해 의문이 들어서 질문드립니다., insert, update, delete 등 Write와 관련된 작업은 쓰기지연 저장소에 저장되고, commit될 때 flush가 된다고 이해했는데요 때때로 select가 수행되었을 때 Write관련 쿼리가 수행되는 것 같더라구요 Delete A엔티티 -> Delete B엔티티 -> select C -> select D 엔티티 -> commit 순으로 진행된다고 할 때, delete A, delete B 는 commit되면서 쿼리가 실행되어야 할 것 같은데, select C 시점에 쿼리가 실행되는 것 같은데(즉 select C 시점에 flush가 되는 것 같은데), 제가 추론한 게 맞는지, 왜 그런건지 이유가 궁금합니다 감사합니다!
게시글이 여러 댓글과 이미지를 가지고 있는 경우 게시글을 조회할 때 댓글과 이미지를 한번에 조회하는 것을 구현하고 있었습니다. @SpringBootTest @Transactional @Rollback(value = false) class PostRepositoryTest { @Autowired PostRepository postRepository; @Autowired UserRepository userRepository; @Autowired CommentRepository commentRepository; @Autowired ImageRepository imageRepository; @Autowired EntityManager em; @Test void 게시글조회시_댓글_이미지_함께_조회() { User user = User.builder() .username("tester") .password("password") .build(); userRepository.save(user); Post post = Post.builder() .title("테스트제목") .content("테스트내용") .build(); postRepository.save(post); Comment comment = Comment.builder() .post(post) .user(user) .content("댓글입니다.") .build(); commentRepository.save(comment); Image image = Image.builder() .image("/file/test") .post(post) .build(); imageRepository.save(image); em.flush(); em.clear(); Post findPost = postRepository.findByIdWithCommentsAndImages(post.getId()).get(); assertThat(findPost.getId()).isEqualTo(post.getId()); assertThat(findPost.getTitle()).isEqualTo("테스트제목"); System.out.println(findPost.getComments().get(0).getContent()); assertThat(findPost.getComments()).contains(comment); } } @Query("select p from Post p " + "left join fetch p.comments " + // "left join fetch p.images " + "where p.id = :id") Optional<Post> findByIdWithCommentsAndImages(@Param("id") Long id); 우선 OneToMany에서 fetch join을 2번하면 에러가 나더라구요 이 경우에 그럼 Comments와 Images를 따로 fetch join해서 가져와야하나요? 테스트에서 em.flush(); em.clear(); 하면 assertThat(findPost.getComments()).contains(comment);여기서 테스트 fail을 합니다. 영속성에서 제거가 돼서 그런 것 같은데 em.flush를 안하고 테스트를 해도 의미가 있는 건지 궁금합니다. 만약 em.flush를 해야지 의미 있다면 equals와 hashcode를 id값으로 오버라이딩을 해야하나요? 강의를 다 듣고 프로젝트에 적용해보려니까 여러군데에서 막히네요.. 개념이 부족한 거겠죠?
신규 강의 업데이트 기다리다 너무 화가 나서 글을 올립니다. 강사님께 질문드리고 싶습니다 확실히 답변 주세요 도대체 강의 업데이트는 언제 됩니까? 올해 초부터 강의가 업데이트 된다고 답변하신지 벌써 반년이 다 지나갑니다 강사님은 강의를 업데이트 하실 생각이 진정으로 있으십니까? 저야 할인받고 구매하긴 했지만 강의가 한두푼 하는것도 아니고 8만8천원짜리 강의면 취준생들은 정말 고민의 고민 끝에 구매한 금액인데 이렇게 하시면 안되죠 물론 강의를 구입하기 전에 이전버전인걸 알고 구매했으니 제 잘못도 있는게 맞습니다. 하지만 강의 이미 녹화 다 끝났다고, 6월 되기 전에 올려주신다고 하셨잖아요 저는 강사님의 답변을 믿고 일단 기존 강의 다 들은 뒤에 업데이트 된 강의 들어야지 하는 생각으로 취준생의 입장에서 정말 거금을 들여 구매한건데 정말 화가 나네요. 이렇게 약속을 지키지 않으실걸 알았으면 굳이 이 강의 구매 안하고 타 사이트에 올라온 훨씬 더 저렴한 강의 구매했겠죠 저야 한달정도밖에 기다리지 않았지만 1월부터 기다린 수강생들은 뭐가 됩니까? 강의를 계속할 여력이 되지 않으시면 공지나 질문에 답변하실때 당분간은 좀 어려울 것 같다고 말씀하시거나 현재 진행사항을 솔직히 말씀하셔야하는것 아닌가요?
스프링 데이터 JPA 실습하다가 궁금한점이 있어 질문드립니다. 아래와 같은 코드를 실행하면 member 값이 null 나오고, Board와 Member 순서를 바꾸면 제대로된 값이 나오는데 왜 그런건가요? 강의를 듣다가 제가 놓친 부분이 있는거 같은데 어디를 놓친걸까요? 영속성 컨텍스트와 관련있는 걸까요? Board { ... // 단방향 관계 @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name = "member_id") private Member member; ... } 이 상황에서 public String ....() { ... Board board = boardService.findBoard(boardId); Member member = memberService.getMemberByLoginId(memberName); ... } (참고로 둘다 service단에서는 @Transactional이 되어 있습니다. getMemberByLoginId의 경우 memberName과 LoginId를 비교해서 일치하는 member를 주는 메소드입니다.)
package hellojpa; import jakarta.persistence.*; import java.util.Date; @Entity public class Member { @Id private Long id; @Column(name = "name") private String username; private Integer age; @Enumerated(EnumType.STRING) private RoleType roleType; @Temporal(TemporalType.TIMESTAMP) private Date createdDate; @Temporal(TemporalType.TIMESTAMP) private Date lastModifiedDate; @Lob private String description; public Member(){ } } 강사님과 똑같이 작성을 하고 실행하면 아무 쿼리도 나가지 않습니다. "C:\Program Files\Java\jdk-17\bin\java.exe" "-javaagent:C:\Program Files\JetBrains\IntelliJ IDEA Community Edition 2024.1.2\lib\idea_rt.jar=49205:C:\Program Files\JetBrains\IntelliJ IDEA Community Edition 2024.1.2\bin" -Dfile.encoding=UTF-8 -classpath "E:\Spring\자바 ORM 표준 JPA 프로그래밍 - 기본편\ex1-hello-jpa-start\ex1-hello-jpa\target\classes;C:\Users\LGE\.m2\repository\org\hibernate\orm\hibernate-core\6.4.2.Final\hibernate-core-6.4.2.Final.jar;C:\Users\LGE\.m2\repository\jakarta\persistence\jakarta.persistence-api\3.1.0\jakarta.persistence-api-3.1.0.jar;C:\Users\LGE\.m2\repository\jakarta\transaction\jakarta.transaction-api\2.0.1\jakarta.transaction-api-2.0.1.jar;C:\Users\LGE\.m2\repository\org\jboss\logging\jboss-logging\3.5.0.Final\jboss-logging-3.5.0.Final.jar;C:\Users\LGE\.m2\repository\org\hibernate\common\hibernate-commons-annotations\6.0.6.Final\hibernate-commons-annotations-6.0.6.Final.jar;C:\Users\LGE\.m2\repository\io\smallrye\jandex\3.1.2\jandex-3.1.2.jar;C:\Users\LGE\.m2\repository\com\fasterxml\classmate\1.5.1\classmate-1.5.1.jar;C:\Users\LGE\.m2\repository\net\bytebuddy\byte-buddy\1.14.7\byte-buddy-1.14.7.jar;C:\Users\LGE\.m2\repository\jakarta\xml\bind\jakarta.xml.bind-api\4.0.0\jakarta.xml.bind-api-4.0.0.jar;C:\Users\LGE\.m2\repository\jakarta\activation\jakarta.activation-api\2.1.0\jakarta.activation-api-2.1.0.jar;C:\Users\LGE\.m2\repository\org\glassfish\jaxb\jaxb-runtime\4.0.2\jaxb-runtime-4.0.2.jar;C:\Users\LGE\.m2\repository\org\glassfish\jaxb\jaxb-core\4.0.2\jaxb-core-4.0.2.jar;C:\Users\LGE\.m2\repository\org\eclipse\angus\angus-activation\2.0.0\angus-activation-2.0.0.jar;C:\Users\LGE\.m2\repository\org\glassfish\jaxb\txw2\4.0.2\txw2-4.0.2.jar;C:\Users\LGE\.m2\repository\com\sun\istack\istack-commons-runtime\4.1.1\istack-commons-runtime-4.1.1.jar;C:\Users\LGE\.m2\repository\jakarta\inject\jakarta.inject-api\2.0.1\jakarta.inject-api-2.0.1.jar;C:\Users\LGE\.m2\repository\org\antlr\antlr4-runtime\4.13.0\antlr4-runtime-4.13.0.jar;C:\Users\LGE\.m2\repository\javax\xml\bind\jaxb-api\2.3.1\jaxb-api-2.3.1.jar;C:\Users\LGE\.m2\repository\javax\activation\javax.activation-api\1.2.0\javax.activation-api-1.2.0.jar;C:\Users\LGE\.m2\repository\com\h2database\h2\2.2.224\h2-2.2.224.jar" hellojpa.JpaMain 6월 13, 2024 7:44:16 오전 org.hibernate.jpa.internal.util.LogHelper logPersistenceUnitInformation INFO: HHH000204: Processing PersistenceUnitInfo [name: hello] 6월 13, 2024 7:44:16 오전 org.hibernate.Version logVersion INFO: HHH000412: Hibernate ORM core version 6.4.2.Final 6월 13, 2024 7:44:16 오전 org.hibernate.cache.internal.RegionFactoryInitiator initiateService INFO: HHH000026: Second-level cache disabled 6월 13, 2024 7:44:16 오전 org.hibernate.engine.jdbc.connections.internal.DriverManagerConnectionProviderImpl configure WARN: HHH10001002: Using built-in connection pool (not intended for production use) 6월 13, 2024 7:44:16 오전 org.hibernate.engine.jdbc.connections.internal.DriverManagerConnectionProviderImpl buildCreator INFO: HHH10001005: Loaded JDBC driver class: org.h2.Driver 6월 13, 2024 7:44:16 오전 org.hibernate.engine.jdbc.connections.internal.DriverManagerConnectionProviderImpl buildCreator INFO: HHH10001012: Connecting with JDBC URL [jdbc:h2:tcp://localhost/~/test] 6월 13, 2024 7:44:16 오전 org.hibernate.engine.jdbc.connections.internal.DriverManagerConnectionProviderImpl buildCreator INFO: HHH10001001: Connection properties: {password=****, user=sa} 6월 13, 2024 7:44:16 오전 org.hibernate.engine.jdbc.connections.internal.DriverManagerConnectionProviderImpl buildCreator INFO: HHH10001003: Autocommit mode: false 6월 13, 2024 7:44:16 오전 org.hibernate.engine.jdbc.connections.internal.DriverManagerConnectionProviderImpl$PooledConnections <init> INFO: HHH10001115: Connection pool size: 20 (min=1) 6월 13, 2024 7:44:16 오전 org.hibernate.engine.jdbc.dialect.internal.DialectFactoryImpl constructDialect WARN: HHH90000025: H2Dialect does not need to be specified explicitly using 'hibernate.dialect' (remove the property setting and it will be selected by default) 6월 13, 2024 7:44:17 오전 org.hibernate.engine.transaction.jta.platform.internal.JtaPlatformInitiator initiateService INFO: HHH000489: No JTA platform available (set 'hibernate.transaction.jta.platform' to enable JTA platform integration) 6월 13, 2024 7:44:17 오전 org.hibernate.engine.jdbc.connections.internal.DriverManagerConnectionProviderImpl$PoolState stop INFO: HHH10001008: Cleaning up connection pool [jdbc:h2:tcp://localhost/~/test] Process finished with exit code 0 <?xml version="1.0" encoding="UTF-8"?> <persistence version="2.2" xmlns="http://xmlns.jcp.org/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistence http://xmlns.jcp.org/xml/ns/persistence/persistence_2_2.xsd"> <persistence-unit name="hello"> <properties> <!-- 필수 속성 --> <property name="jakarta.persistence.jdbc.driver" value="org.h2.Driver"/> <property name="jakarta.persistence.jdbc.user" value="sa"/> <property name="jakarta.persistence.jdbc.password" value=""/> <property name="jakarta.persistence.jdbc.url" value="jdbc:h2:tcp://localhost/~/test"/> <property name="hibernate.dialect" value="org.hibernate.dialect.H2Dialect"/> <!-- 옵션 --> <property name="hibernate.show_sql" value="true"/> <property name="hibernate.format_sql" value="true"/> <property name="hibernate.use_sql_comments" value="true"/> <property name="hibernate.jdbc.batch_size" value="10"/> <property name="hibernate.hdm2ddl.auto" value="create"/> </properties> </persistence-unit> </persistence> <property name="hibernate.hdm2ddl.auto" value="create"/> 위 코드로 인해 테이블이 계속 드랍이 되어 그전까지는 주석처리하여 쿼리가 나가고 테이블이 생성되었지만 현재 위 코드를 다시 주석처리 하든 하지 않든 쿼리가 나가지 않고 테이블 생성이 되지 않습니다
테스트 케이스 세분화하기에서부터 화면이 안나와요 검정 화면으로 자막만 나옵니다. 다른 질문을 확인했을 때 크롬 하드웨어 가속을 끄면 나온다고 하여 해당 부분을 수정해서 확인하니 강의는 나오지만, 이부분에 대해 저 또한 문제가 발생하고 있음을 말씀 드립니다! 참고로, 맥북 m1 pro 입니다!
HTML 인증 메일 전송하기 쪽 개발중에 궁금한게 생겼는데요 회원 가입후 링크로 인증쪽 url의 토큰 뒤에 & 가 붙더라구요 검색해서 확인해보니 & 의 경우 서버 스크립트에서 처리할 때 & 로 변환한다고 하더라구요 그래서 왜 자꾸 & 로 변환 될까 찾던 찰나에 HtmlEmailService의 sendEmail 메서드에서 mimeMessageHelper.setText( String text, boolean html) 의 두번째 인자값이 false로 설정되어 있어 & 값이 생겼었던 것입니다. 메일의 context 도 html 소스가 문자열 그대로 나오고 html 형태로 나왔었구요. true 로 설정하니 원만히 해결 되었는데 이유가 궁금합니다... setText 메서드를 타고 들어가면 htmlText 를 MimePart로 변환해주는 메서드가 있는데 정확히 알고 싶습니다.. 혹은 해당 메서드를 보고 이와 같은 문제를 맞딱드렸을때 알아내는 방법이나 노하우 같은게 있을까요 ?
학습하는 분들께 도움이 되고, 더 좋은 답변을 드릴 수 있도록 질문전에 다음을 꼭 확인해주세요. 1. 강의 내용과 관련된 질문을 남겨주세요. 2. 인프런의 질문 게시판과 자주 하는 질문(링크)을 먼저 확인해주세요. (자주 하는 질문 링크: https://bit.ly/3fX6ygx) 3. 질문 잘하기 메뉴얼(링크)을 먼저 읽어주세요. (질문 잘하기 메뉴얼 링크: https://bit.ly/2UfeqCG) 질문 시에는 위 내용은 삭제하고 다음 내용을 남겨주세요. ========================================= [질문 템플릿] 1. 강의 내용과 관련된 질문인가요? 예 2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? 예 3. 질문 잘하기 메뉴얼을 읽어보셨나요? 예 [질문 내용] 오라클의 경우는 시퀀스로 증가하는 방법을 사용하는데, useGeneratedkey를 사용할 방법이 있을까요
[질문 템플릿] 1. 강의 내용과 관련된 질문인가요? (예) 2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? (예) 3. 질문 잘하기 메뉴얼을 읽어보셨나요? (예) [질문 내용] java.lang.NullPointerException: Cannot invoke "org.hibernate.engine.jdbc.spi.SqlExceptionHelper.convert(java.sql.SQLException, String)" because the return value of "org.hibernate.resource.transaction.backend.jdbc.internal.JdbcIsolationDelegate.sqlExceptionHelper()" is null at org.hibernate.resource.transaction.backend.jdbc.internal.JdbcIsolationDelegate.delegateWork(JdbcIsolationDelegate.java:116) ~[hibernate-core-6.5.2.Final.jar:6.5.2.Final] at org.hibernate.engine.jdbc.env.internal.JdbcEnvironmentInitiator.getJdbcEnvironmentUsingJdbcMetadata(JdbcEnvironmentInitiator.java:290) ~[hibernate-core-6.5.2.Final.jar:6.5.2.Final] at org.hibernate.engine.jdbc.env.internal.JdbcEnvironmentInitiator.initiateService(JdbcEnvironmentInitiator.java:123) ~[hibernate-core-6.5.2.Final.jar:6.5.2.Final] at org.hibernate.engine.jdbc.env.internal.JdbcEnvironmentInitiator.initiateService(JdbcEnvironmentInitiator.java:77) ~[hibernate-core-6.5.2.Final.jar:6.5.2.Final] at org.hibernate.boot.registry.internal.StandardServiceRegistryImpl.initiateService(StandardServiceRegistryImpl.java:130) ~[hibernate-core-6.5.2.Final.jar:6.5.2.Final] at org.hibernate.service.internal.AbstractServiceRegistryImpl.createService(AbstractServiceRegistryImpl.java:263) ~[hibernate-core-6.5.2.Final.jar:6.5.2.Final] at org.hibernate.service.internal.AbstractServiceRegistryImpl.initializeService(AbstractServiceRegistryImpl.java:238) ~[hibernate-core-6.5.2.Final.jar:6.5.2.Final] at org.hibernate.service.internal.AbstractServiceRegistryImpl.getService(AbstractServiceRegistryImpl.java:215) ~[hibernate-core-6.5.2.Final.jar:6.5.2.Final] at org.hibernate.boot.model.relational.Database.<init>(Database.java:45) ~[hibernate-core-6.5.2.Final.jar:6.5.2.Final] at org.hibernate.boot.internal.InFlightMetadataCollectorImpl.getDatabase(InFlightMetadataCollectorImpl.java:221) ~[hibernate-core-6.5.2.Final.jar:6.5.2.Final] at org.hibernate.boot.internal.InFlightMetadataCollectorImpl.<init>(InFlightMetadataCollectorImpl.java:189) ~[hibernate-core-6.5.2.Final.jar:6.5.2.Final] at org.hibernate.boot.model.process.spi.MetadataBuildingProcess.complete(MetadataBuildingProcess.java:171) ~[hibernate-core-6.5.2.Final.jar:6.5.2.Final] at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.metadata(EntityManagerFactoryBuilderImpl.java:1431) ~[hibernate-core-6.5.2.Final.jar:6.5.2.Final] at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.build(EntityManagerFactoryBuilderImpl.java:1502) ~[hibernate-core-6.5.2.Final.jar:6.5.2.Final] at org.springframework.orm.jpa.vendor.SpringHibernateJpaPersistenceProvider.createContainerEntityManagerFactory(SpringHibernateJpaPersistenceProvider.java:75) ~[spring-orm-6.1.8.jar:6.1.8] at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.createNativeEntityManagerFactory(LocalContainerEntityManagerFactoryBean.java:390) ~[spring-orm-6.1.8.jar:6.1.8] at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.buildNativeEntityManagerFactory(AbstractEntityManagerFactoryBean.java:409) ~[spring-orm-6.1.8.jar:6.1.8] at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.afterPropertiesSet(AbstractEntityManagerFactoryBean.java:396) ~[spring-orm-6.1.8.jar:6.1.8] at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.afterPropertiesSet(LocalContainerEntityManagerFactoryBean.java:366) ~[spring-orm-6.1.8.jar:6.1.8] at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1835) ~[spring-beans-6.1.8.jar:6.1.8] at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1784) ~[spring-beans-6.1.8.jar:6.1.8] at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:600) ~[spring-beans-6.1.8.jar:6.1.8] at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:522) ~[spring-beans-6.1.8.jar:6.1.8] at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:337) ~[spring-beans-6.1.8.jar:6.1.8] at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234) ~[spring-beans-6.1.8.jar:6.1.8] at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:335) ~[spring-beans-6.1.8.jar:6.1.8] at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:205) ~[spring-beans-6.1.8.jar:6.1.8] at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:952) ~[spring-context-6.1.8.jar:6.1.8] at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:624) ~[spring-context-6.1.8.jar:6.1.8] at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:146) ~[spring-boot-3.3.0.jar:3.3.0] at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:754) ~[spring-boot-3.3.0.jar:3.3.0] at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:456) ~[spring-boot-3.3.0.jar:3.3.0] at org.springframework.boot.SpringApplication.run(SpringApplication.java:335) ~[spring-boot-3.3.0.jar:3.3.0] at org.springframework.boot.SpringApplication.run(SpringApplication.java:1363) ~[spring-boot-3.3.0.jar:3.3.0] at org.springframework.boot.SpringApplication.run(SpringApplication.java:1352) ~[spring-boot-3.3.0.jar:3.3.0] at jpabook.jpashop.JpashopApplication.main(JpashopApplication.java:16) ~[classes/:na] at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:na] at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77) ~[na:na] at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:na] at java.base/java.lang.reflect.Method.invoke(Method.java:568) ~[na:na] at org.springframework.boot.devtools.restart.RestartLauncher.run(RestartLauncher.java:50) ~[spring-boot-devtools-3.3.0.jar:3.3.0] 2024-06-12T10:54:03.045+09:00 ERROR 26788 --- [ restartedMain] j.LocalContainerEntityManagerFactoryBean : Failed to initialize JPA EntityManagerFactory: Unable to create requested service [org.hibernate.engine.jdbc.env.spi.JdbcEnvironment] due to: Unable to determine Dialect without JDBC metadata (please set 'jakarta.persistence.jdbc.url' for common cases or 'hibernate.dialect' when a custom Dialect implementation must be provided) 2024-06-12T10:54:03.047+09:00 WARN 26788 --- [ restartedMain] ConfigServletWebServerApplicationContext : Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'entityManagerFactory' defined in class path resource [org/springframework/boot/autoconfigure/orm/jpa/HibernateJpaConfiguration.class]: Unable to create requested service [org.hibernate.engine.jdbc.env.spi.JdbcEnvironment] due to: Unable to determine Dialect without JDBC metadata (please set 'jakarta.persistence.jdbc.url' for common cases or 'hibernate.dialect' when a custom Dialect implementation must be provided) 2024-06-12T10:54:03.061+09:00 INFO 26788 --- [ restartedMain] o.apache.catalina.core.StandardService : Stopping service [Tomcat] 2024-06-12T10:54:03.086+09:00 INFO 26788 --- [ restartedMain] .s.b.a.l.ConditionEvaluationReportLogger : Error starting ApplicationContext. To display the condition evaluation report re-run your application with 'debug' enabled. 2024-06-12T10:54:03.135+09:00 ERROR 26788 --- [ restartedMain] o.s.boot.SpringApplication : Application run failed 제가 컴퓨터 재부팅하고 JpashopApplicaton을 실행했을 때 다음과 같이 에러가 떠서 h2 데이터베이스 설정이 안됐나 싶어서 설정하려 했는데 h2에서 다음과 같은 에러가 발생했다고 하네요... 이거 Chat GPT한테 물어보면 application.yml을 다시 설정하라 하는데 뭔가 건드리면 안될 것 같아서 그런데 어떻게 해결하면 좋을지 질문 드리고자 합니다.
Persist를 실행할 때는 영속성 컨텍스트 1차 캐시에 데이터를 넣지 않는 건가요? 아니면 persist도 1차 캐시에 데이터와 스냅샷 모두 저장하나요?Find를 실행해서 db에서 가져올 때만 가져올 때의 엔티키 상태를 스냅샷을 찍고 엔티티와 함께 1차 캐시에 저장하나요?jpql 실행시에는 1차 캐시를 조회하지 않는 건가요?이 질문의 이유:Find는 1차 캐시에 있는 엔티티를 먼저 조회하는 것으로 알고 있습니다.jpql을 실행할 때 Member 데이터가 없으면 안된다고 설명하고 있습니다그래서 jpql 실행은 1차 캐시를 먼저 찾지 않고 바로 쿼리를 전송하는 것인가? 라는 생각이 들었습니다.jpql이 1차 캐시를 조회하지 않으면 persist 호출 시 1차 캐시에 엔티티를 저장해도 db에서 찾으니까 결국 flush가 발생한다는 생각이 맞아 떨어지는 것 같습니다.
[질문 내용] 우선 단방향 연관관계를 적용하고 꼭 필요한 경우에 양방향 연관관계를 사용하라는 내용을 적용해보다가 이해가 안되는 부분이 생겨서 질문남깁니다. Team과 Member로 양방향 연관관계를 적용한다고 생각해보면 다른 질문의 답변을 봤을 때 Team을 조회할 때 Member가 거의 같이 조회가 되는 경우와 fetch join으로 조회 시 양방향 연관관계를 사용하여 더 편리하게 조회할 때 사용한다는 답변을 봤습니다. (제대로 이해한 것인지는 모르겠습니다.) 그래서 테스트를 해봤습니다. @Test void 멤버목록과_함께_팀조회() { Team team = new Team("teamA"); entityManager.persist(team); Member member = new Member("m1", 0, team); Member member2 = new Member("m2", 0, team); entityManager.persist(member); entityManager.persist(member2); entityManager.flush(); entityManager.clear(); System.out.println("====테스트 1 양방향 연관관계==="); Team findTeam = teamJpaRepository.findById(team.getId()).get(); List<Member> members = findTeam.getMembers(); for (Member member1 : members) { System.out.println("member1 = " + member1.getUsername()); } entityManager.flush(); entityManager.clear(); System.out.println("===테스트 2 fetch join 양방향 연관관계 사용=="); Team findTeam2 = teamRepository.findTeamWithMembersById(team.getId()).get(); List<Member> members2 = findTeam2.getMembers(); for (Member member1 : members2) { System.out.println("member1 = " + member1.getUsername()); } entityManager.flush(); entityManager.clear(); System.out.println("===테스트 3 fetch join 그냥 엔티티 사용=="); Team findTeam3 = teamRepository.findTeamWithMemberById(team.getId()).get(); List<Member> members3 = findTeam3.getMembers(); for (Member member1 : members3) { System.out.println("member1 = " + member1.getUsername()); } } public interface TeamRepository extends JpaRepository<Team, Long> { @Query("select t from Team t join fetch t.members") Optional<Team> findTeamWithMembersById(Long id); @Query("select t from Team t join fetch Member m") Optional<Team> findTeamWithMemberById(Long id); } 테스트 1의 경우 두개의 쿼리가 나가는 것을 확인했습니다. select t1_ 0.team _id, t1_0.create_by, t1_0.created_date, t1_0.last_modified_by, t1_0.last_modified_date, t1_ 0.name from team t1_0 where t1_ 0.team _id=? select m1_ 0.team _id, m1_0.member_id, m1_0.age, m1_0.create_by, m1_0.created_date, m1_0.last_modified_by, m1_0.last_modified_date, m1_0.username from member m1_0 where m1_ 0.team _id=? 테스트 2의 경우 한개의 쿼리만 나가는 것을 확인했습니다. select t1_ 0.team _id, t1_0.create_by, t1_0.created_date, t1_0.last_modified_by, t1_0.last_modified_date, m1_ 0.team _id, m1_0.member_id, m1_0.age, m1_0.create_by, m1_0.created_date, m1_0.last_modified_by, m1_0.last_modified_date, m1_0.username, t1_ 0.name from team t1_0 join member m1_0 on t1_ 0.team _id=m1_ 0.team _id 테스트 3의 경우 오류가 났습니다. 위의 테스트 1(getMembers로 접근), 테스트2(fetch join)의 경우 쿼리의 개수로 봤을 때 테스트 2를 사용하는 게 더 좋은 것 같은데 맞을까요? 테스트 3은 단방향인 경우 팀과 멤버를 같이 조회를 어떻게 해야되나요? 양방향 연관관계가 필요한 경우가 뭔가요? 원래 api 설계할 때 team, member를 각각 조회하는 경우만 만들었었는데, team과 member가 같이 조회되는 api를 만드는 경우도 있나요? (team/{id}, member/{id} 와 같은 경우만 만들어봤습니다.)
[질문 템플릿] 1. 강의 내용과 관련된 질문인가요? (예) 2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? (예) 3. 질문 잘하기 메뉴얼을 읽어보셨나요? (예) [질문 내용] jpa 활용 1편에서 라이브 코딩했던 것들을 이어서 하는거 맞죠? 따로 jpa 활용 1편까지 구현한 코드만 올려놓은 소스 파일이 없어서 jpa 활용 1편에서 듣고 코딩했던 것들 이어서 해도되는거 맞는 거죠?
테스트 코드를 작성할 때 DIP를 이용해서 결합도를 낮추고, 빠르게 테스트를 하는 것을 확인하였습니다. 궁금한 점은 interface로 서비스 레파지토리를 선언해서 사용하면, 인터페이스 자체가 어떻게보면 다형성을 위해 도면을 구성한다고 생각되는데, FakeImpl을 만들기위해서 너무 많이 다형성을 사용하는게 아닌가 싶은 생각도 들어서요. 초기 프로젝트에는 오버엔지니어링이 되지는 않을까 고민이 됩니다. 소스코드 관리하는 점에서 따라가기 쉽지 않은 것을 느꼈습니다. 물론 패키지 구조를 잘 알고 있는 사람이라면 쉽게 접근하겠지만, 그렇지 않은 사람이 코드를 분석했을 때 함수를 클릭해서 접근은 하는 경우가 많더라고요. 이럴 경우에는 패키지 구조를 도식화해서 공유해서 해결하는지, 궁금합니다.
application.yml이나 properties에 적는 설정 정보? 들을 어디서 찾아볼 수 있을까요... 공식 문서를 찾아보는데 확인이 잘 안 됩니다. logging.level.org.hibernate.SQL = debug 특히 이 부분같은 경우 어디있는지 모르겠어요