묻고 답해요
161만명의 커뮤니티!! 함께 토론해봐요.
인프런 TOP Writers
-
해결됨즐거운 자바
메서드와 프로퍼티의 차이가 뭔가요?
setter와 getter가 나오면서 값자기 메서드를 프로퍼티로 부르는 것 같은데 이에 대한 차이가 뭔가요?
-
미해결
Spring JPA 다대다 관계 테이블 질문드립니다.
2개의 다대다 관계의 엔티티를 연결테이블을 이용해서 총 3개의 엔티티로 구성했습니다.Companion 엔티티@Entity @Getter @NoArgsConstructor(access = AccessLevel.PROTECTED) @Builder @AllArgsConstructor public class Companion { // Companion 엔티티는 동반 여행에 참여하는 개별 동반자의 정보를 나타냅니다. // 회원들과의 다대다 관계를 통해 여러 회원과 연결될 수 있으며, 동반 여행의 세부 정보를 저장합니다. @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; // 동반자 엔티티의 고유 식별자 private String name; // 동반자의 이름 private String code; // 동반자를 구분하는 코드 정보 private Boolean isStart; // 동반 여행의 시작 여부 private Boolean isEnd; // 동반 여행의 종료 여부 private String tendency; // 동반자의 특성 정보 private String mate; // 동반자에 대한 추가 정보 private LocalDateTime startTime; // 동반 여행의 시작 시간 private LocalDateTime endTime; // 동반 여행의 종료 시간 @OneToMany(mappedBy = "companion") private List<MemberCompanion> companionMembers = new ArrayList<>(); }Member 엔티티@Entity @Getter @Builder @NoArgsConstructor(access = AccessLevel.PROTECTED) @AllArgsConstructor public class Member { // Member 엔티티는 시스템 사용자를 나타내며, 동반자와의 다대다 관계를 허용합니다. // 각 회원은 여러 개의 동반자와 연결될 수 있으며, 동반자 정보를 관리합니다. @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; // 회원 엔티티의 고유 식별자 @Column(unique = true) private String email; // 회원의 고유한 이메일 주소 private String nickname; // 회원의 사용자명 private String snsType; // 소셜 로그인 종류 private String originalId; // 고유 아이디 @OneToMany(mappedBy = "member") private List<MemberCompanion> myCompanions = new ArrayList<>(); }Companion과 Member를 연결하는 Entity@Entity @Getter @Builder @NoArgsConstructor(access = AccessLevel.PROTECTED) @AllArgsConstructor public class MemberCompanion { // MemberCompanion 엔티티는 회원과 동반자 간의 관계를 정의하는 엔티티입니다. // 회원과 동반자를 관련시키며, 회원-동반자 관계의 역할 정보를 포함합니다. @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; // 회원-동반자 관계 엔티티의 고유 식별자 @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name = "member_id") private Member member; // 회원 @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name = "companion_id") private Companion companion; // 그룹 @Enumerated(value = EnumType.STRING) private Role role; // 회원-동반자 관계 역할 (예: 리더, 구성원) } 문제가 발생한 것은, Companion을 build하고 생성된 Companion과 Member를 통해서 MemberCompanion을 생성한 후, 생성된 MemberCompanion을 다시 Companion의 companionMembers에 넣으려고하면 순환 참조 오류가 터집니다. Dto를 사용해봤지만 잘 해결이 안되어서 질문 올립니다./** * 그룹 등록을 처리하는 메서드 * * @param companionAddRequestDto 그룹 등록 요청 DTO * @return ResponseEntity 객체를 반환하여 등록 성공 또는 실패 응답을 전송 */ @Transactional public ResponseEntity registCompanion(CompanionAddRequestDto companionAddRequestDto) { Member member = memberRepository.findById(companionAddRequestDto.getMemberId()) .orElseThrow(() -> new EntityNotFoundException("회원을 찾을 수 없습니다.")); Companion companion = Companion.builder() .name(companionAddRequestDto.getName()) .code(generateRandomCode()) .isStart(companionAddRequestDto.getIsStart()) .isEnd(companionAddRequestDto.getIsEnd()) .tendency(companionAddRequestDto.getTendency()) .mate(companionAddRequestDto.getMate()) .startTime(companionAddRequestDto.getStartTime()) .endTime(companionAddRequestDto.getEndTime()) .companionMembers(new ArrayList<>()) .build(); companionRepository.save(companion); // MemberCompanion 엔티티를 생성 MemberCompanion memberCompanion = MemberCompanion.builder() .member(member) .companion(companion) .role(Role.LEADER) .build(); memberCompanionRepository.save(memberCompanion); // 등록 성공 응답을 생성하고 반환 return ResponseEntity.ok() .body(new SuccessResponseDto(true, "그룹 등록이 완료되었습니다.", companion)); }해당 코드에서memberCompanionRepository.save(memberCompanion);이후 companion.getCompanionMembers.add(memberCompanion)시 getCompanionMembers값이 null이라 나오고 다른 방법을 사용하면 순환참조가 발생합니다.해결 방법이 있을까요..?
-
해결됨자바와 스프링 부트로 생애 최초 서버 만들기, 누구나 쉽게 개발부터 배포까지! [서버 개발 올인원 패키지]
초반 실행 오류
안녕하세요! 선생님 강의 초반에 문제가 발생해서 이렇게 질문을 남기게 되었습니다.처음에 library-app을 실행할 때 시간이 조금 지연됐습니다. 그리고 기다림 끝에 Started LibraryAppApplication in XX Seconds라고 뜨고 실행을 중지하고(중지버튼 눌렀더니 오류라고 나온 화면입니다.) 다음순서로 넘어가 패키지와 CalculatorController라는 클래스를 만들고 실행하려고 하는데 실행 버튼을 누를 수 없고 마우스를 실행버튼에 올렸더니 '에디터의 파일을 실행할 수 없습니다.' 라는 문구가 나오더라구요..혹시 문제가 무엇인지 알려주실 수 있을까요??
-
미해결스프링 시큐리티 OAuth2
authenticationEntryPoint 를 기본 설정된 /login이 아닌 react 웹 페이지로 설정 시 cors 문제가 지속해서 발생합니다.
authenticastion Entry Point로 지정 시 cors문제가 계속해서 진행되어 Authorization Code를 받아올 수 없습니다.코드 첨부Authorization Server Config@Bean @Order(Ordered.HIGHEST_PRECEDENCE) public SecurityFilterChain authorizationServerSecurityFilterChain(HttpSecurity http) throws Exception { OAuth2AuthorizationServerConfiguration.applyDefaultSecurity(http); http .getConfigurer(OAuth2AuthorizationServerConfigurer.class) .oidc(Customizer.withDefaults() ); http .exceptionHandling((exceptions) -> exceptions .authenticationEntryPoint( new LoginUrlAuthenticationEntryPoint("http://localhost:3000") // new LoginUrlAuthenticationEntryPoint("/login") )) http.oauth2ResourceServer((resourceServer) -> resourceServer .jwt(Customizer.withDefaults())); return http.build(); } @Bean public RegisteredClientRepository registeredClientRepository() { RegisteredClient oidcClient = RegisteredClient.withId(UUID.randomUUID().toString()) .clientId("oidc-client") .clientSecret("{noop}secret") .clientAuthenticationMethod(ClientAuthenticationMethod.CLIENT_SECRET_BASIC) .authorizationGrantType(AuthorizationGrantType.AUTHORIZATION_CODE) .authorizationGrantType(AuthorizationGrantType.REFRESH_TOKEN) .redirectUri("https://oidcdebugger.com/debug") .redirectUri("https://test-b821b.web.app") .postLogoutRedirectUri("http://127.0.0.1:8080/") .scope(OidcScopes.OPENID) .scope(OidcScopes.PROFILE) .clientSettings(ClientSettings.builder().requireAuthorizationConsent(true).build()) .build(); return new InMemoryRegisteredClientRepository(oidcClient); } @Bean public AuthorizationServerSettings authorizationServerSettings() { return AuthorizationServerSettings.builder().issuer("http://localhost:6080").build(); } } Default Web Config @Bean public WebMvcConfigurer corsConfigurer() { return new WebMvcConfigurer() { @Override public void addCorsMappings(CorsRegistry registry) { registry.addMapping("/**") .allowedOrigins("http://localhost:3000") .allowedMethods("GET", "POST", "PUT", "DELETE", "OPTIONS") .allowedHeaders("*") .allowCredentials(true) .exposedHeaders("*"); } }; } @Bean public CorsConfigurationSource corsConfigurationSource() { CorsConfiguration configuration = new CorsConfiguration(); configuration.setAllowCredentials(true); configuration.addAllowedHeader("*"); configuration.addAllowedMethod("*"); configuration.addAllowedOrigin("http://localhost:3000"); configuration.setExposedHeaders(Arrays.asList("*")); UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(); source.registerCorsConfiguration("/**", configuration); return source; } @Bean public SecurityFilterChain filterChain(HttpSecurity http) throws Exception { http .cors(customCorsConfig -> customCorsConfig.configurationSource(corsConfigurationSource())) .csrf(AbstractHttpConfigurer::disable) .authorizeHttpRequests(authorizeHttpRequestsCustomizer -> authorizeHttpRequestsCustomizer.requestMatchers(AUTH_WHITELIST).permitAll() .anyRequest().authenticated() ) .formLogin( httpSecurityFormLoginConfigurer -> httpSecurityFormLoginConfigurer.loginPage("http://localhost:3000").loginProcessingUrl("/login") // Customizer.withDefaults() ) ; return http.build(); } @Bean public UserDetailsService userDetailsService() { PasswordEncoder passwordEncoder = new BCryptPasswordEncoder(); UserDetails userDetails = User.builder() .username("user") .password(passwordEncoder.encode("password")) .roles("USER") .build(); return new InMemoryUserDetailsManager(userDetails); } @Bean public JWKSource<SecurityContext> jwkSource() { KeyPair keyPair = generateRsaKey(); RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic(); RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate(); RSAKey rsaKey = new RSAKey.Builder(publicKey) .privateKey(privateKey) .keyID(UUID.randomUUID().toString()) .build(); JWKSet jwkSet = new JWKSet(rsaKey); return new ImmutableJWKSet<>(jwkSet); } private static KeyPair generateRsaKey() { KeyPair keyPair; try { KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA"); keyPairGenerator.initialize(2048); keyPair = keyPairGenerator.generateKeyPair(); } catch (Exception ex) { throw new IllegalStateException(ex); } return keyPair; } @Bean public JwtDecoder jwtDecoder(JWKSource<SecurityContext> jwkSource) { return OAuth2AuthorizationServerConfiguration.jwtDecoder(jwkSource); } @Bean public PasswordEncoder encoder() { return new BCryptPasswordEncoder(); } 위 코드로 진행했을 시 발생하는 Cors Error입니다 Access to XMLHttpRequest at 'http://localhost:6080/oauth2/authorize?client_id=oidc-client&redirect_uri=https%3A%2F%2Foidcdebugger.com%2Fdebug&scope=openid&response_type=code&response_mode=form_post&state=3it6dl9kewr&nonce=hyq3pnronj7&continue' (redirected from 'http://localhost:6080/login') from origin 'http://localhost:3000' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.3. 이로 인해 CorsFilter를 적용하게 되면 해당 Cors는 해결되지만 authorization code 가 Redirect되는 시점에 Cors 에러가 새롭게 나옵니다.CorsFilter @Component @Slf4j @Order(Ordered.HIGHEST_PRECEDENCE) public class CorsFilter implements Filter { private static final Set<String> allowedOrigins = new HashSet<String>(); static { allowedOrigins.add( "http://localhost:3000" ); } @Override public void init(FilterConfig fc) throws ServletException { } @Override public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException { HttpServletResponse response = (HttpServletResponse) res; HttpServletRequest request = (HttpServletRequest) req; String origin = request.getHeader(HttpHeaders.ORIGIN); log.info("Origin: {}", origin); if (origin != null) { Optional<String> first = allowedOrigins.stream().filter(origin::startsWith).findFirst(); first.ifPresent(s -> response.setHeader("Access-Control-Allow-Origin", s)); } response.setHeader("Access-Control-Allow-Credentials", "true"); response.setHeader("Access-Control-Allow-Methods", "*"); response.setHeader("Access-Control-Max-Age", "3600"); response.setHeader("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept, Key, Authorization"); if ("OPTIONS".equalsIgnoreCase(request.getMethod())) { response.setStatus(HttpServletResponse.SC_OK); } else { chain.doFilter(req, res); } } @Override public void destroy() { } Cors 오류Access to XMLHttpRequest at 'https://oidcdebugger.com/debug?code=1o_jSQQVu6EB4XDq-xCWP3qrzp2VDdGbH_AN7iBJGU5gQRC7BRFkQYdn2A6P-6G5Aoi8XLJLaVR4MSVktNzDvYLMmj_UXahcWfEwQdA-tk4GCw5Bff4mXn2q6mIYfs_d&state=3it6dl9kewr' (redirected from 'http://localhost:6080/login') from origin 'http://localhost:3000' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.혹시 외부 로그인 페이지와 연동한 예시가 있거나, Cors 문제를 해결할 방안이 있는지 궁금합니다ㅠㅠ
-
해결됨실전! 스프링 부트와 JPA 활용2 - API 개발과 성능 최적화
계층형 테이블에 매핑된 엔티티 컬렉션을 fetch join으로 가져올 때 쿼리 개수 질문드립니다.
[질문 템플릿]1. 강의 내용과 관련된 질문인가요? (예)2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? (예)3. 질문 잘하기 메뉴얼을 읽어보셨나요? (예)[질문 내용]코드는 마지막에 첨부되어 있습니다.게시글 엔티티 Post가 게시글에 달린 댓글 엔티티 Comment의 컬렉션을 프로퍼티로 갖습니다. 댓글 엔티티 Comment는 COMMENT, REPLY 타입으로 구분되며, 프로퍼티로 parentComment와 replies를 갖습니다. COMMENT 타입은 parentComment == null이며, REPLY 타입은 replies == null입니다. Post.comments는 Comment의 타입을 고려하지 않고 모두 갖고 있습니다.위 상황에서 게시물 상세 정보를 가져올 때, comments를 fetch join하여 Post 엔티티를 가져와 댓글들을 타입 계층에 따라 분리하는 작업을 합니다. 이때 REPLY 타입의 replies에 접근하지 않습니다. COMMENT 타입의 replies에는 접근하며 해당 replies는 모두 같은 게시물에 속해있습니다.예상했던 쿼리의 개수는 1 혹은 (1 + COMMENT 타입 수) 였습니다. 애초에 둘 중 무엇인지 궁금해서 일을 진행했었습니다.테스트를 실행해보면, post.comments의 요소에 처음 접근할 때 REPLY 타입을 가져오는 쿼리가 발생합니다. 그런데 이후에 다른 COMMENT 타입에 접근할 때는 REPLY를 가져오는 쿼리가 발생하지 않습니다. 만약 Post의 COMMENT 타입 Comment.replies에 접근할 때 쿼리가 발생하는 거라면 COMMENT 타입의 개수만큼 발생해야 하는게 아닌가요? 제가 무엇을 놓치고 있는지 궁금합니다.논외로, Spring data JPA의 @Query를 통해 작성한 단순한 정적 쿼리가 계속 반복된다면 QeuryDSL로 옮겨 반복을 줄이는게 합리적일까요? 아니면 spring data jpa의 편리함을 유지하는게 합리적인가요? 감사합니다.public class Post extends BaseEntity { public static final int TITLE_MAX_LENGTH = 50; public static final int CONTENT_MAX_LENGTH = 10000; @Id @GeneratedValue(strategy = GenerationType.IDENTITY) @Column(name = "post_id", nullable = false, updatable = false) private Long id; @Column(name = "title", nullable = false, length = TITLE_MAX_LENGTH, updatable = false) private String title; @Column(name = "content", nullable = false, length = CONTENT_MAX_LENGTH) private String content; @Column(name = "hits", nullable = false) private Long hits; @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name = "writer_id") private Member writer; @OneToMany(fetch = FetchType.LAZY, mappedBy = "post", orphanRemoval = true) @ToString.Exclude private List<Comment> comments = new ArrayList<>(); }public class Comment extends BaseDeleteEntity { public static final int CONTENT_LENGTH = 1000; @Id @GeneratedValue(strategy = GenerationType.IDENTITY) @Column(name = "comment_id", nullable = false) private Long id; @Column(name = "content", nullable = false, length = CONTENT_LENGTH) private String content; @Column(name = "type", nullable = false, updatable = false) private CommentType type; @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name = "post_id", nullable = false, updatable = false) private Post post; @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name = "writer") private Member writer; @OneToMany(fetch = FetchType.LAZY, mappedBy = "parent", orphanRemoval = true) private List<Comment> replies = new ArrayList<>(); @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name = "parent_comment_id", updatable = false) @ToString.Exclude private Comment parent; } @Query(value = """ SELECT p FROM Post p LEFT JOIN FETCH p.writer AS w LEFT JOIN FETCH w.profile LEFT JOIN FETCH p.comments WHERE p.id = :postId """ ) Optional<Post> findPostById(@Param("postId") final Long id); @Autowired EntityManager em; @Autowired PostRepository postRepository; @Test public void 정상작동테스트_추가적인_쿼리_발생_x() throws Exception { //given Post post = PostTest.create("username", "nickname"); Member member = post.getWriter(); em.persist(member); em.persist(post); Long postId = post.getId(); int commentCount = 10; int replyCount = 2; createComment(post, member, commentCount, replyCount); em.flush(); em.clear(); //when int totalCommentCount = commentCount * (replyCount + 1); Post findPost = postRepository.findPostById(postId).get(); System.out.println(); //then for (Comment comment : findPost.getComments().stream().filter(Comment::isCommentType).toList()) { // 이때 REPLY 타입을 조회하는 쿼리가 1회 발 System.out.println("comment = " + comment); System.out.println("comment.getReplies().get(0) = " + comment.getReplies().get(0)); } Assertions.assertThat(post.getComments().size()).isEqualTo(totalCommentCount); }[테스트 실행 시 쿼리]2023-11-02T11:45:00.154+09:00 DEBUG 51844 --- [ main] org.hibernate.SQL :selectp1_0.post_id,c1_0.post_id,c1_0.comment_id,c1_0.content,c1_0.created_by,c1_0.created_date,c1_0.deleted_date,c1_0.is_deleted,c1_0.last_modified_by,c1_0.last_modified_date,c1_0.parent_comment_id,c1_0.type,c1_0.writer,p1_0.content,p1_0.created_by,p1_0.created_date,p1_0.hits,p1_0.last_modified_by,p1_0.last_modified_date,p1_0.title,w1_0.member_id,w1_0.created_by,w1_0.created_date,w1_0.last_modified_by,w1_0.last_modified_date,w1_0.login_id,w1_0.login_type,w1_0.profile_id,p2_0.profile_id,p2_0.created_by,p2_0.created_date,p2_0.last_modified_by,p2_0.last_modified_date,p2_0.nickname,w1_0.user_role,w1_0.social_login_id,w1_0.usernamefrompost p1_0left joinmember w1_0on w1_0.member_id=p1_0.writer_idleft joinprofile p2_0on p2_0.profile_id=w1_0.profile_idleft joincomment c1_0on p1_0.post_id=c1_0.post_idwherep1_0.post_id=?2023-11-02T11:45:00.162+09:00 INFO 51844 --- [ main] p6spy2023-11-02T11:45:01.221+09:00 DEBUG 51844 --- [ main] org.hibernate.SQL :selectr1_0.parent_comment_id,r1_0.comment_id,r1_0.content,r1_0.created_by,r1_0.created_date,r1_0.deleted_date,r1_0.is_deleted,r1_0.last_modified_by,r1_0.last_modified_date,r1_0.post_id,r1_0.type,r1_0.writerfromcomment r1_0wherearray_contains(?,r1_0.parent_comment_id)[반복되는 spring data jpa 쿼리]public interface PostRepository extends JpaRepository<Post, Long>, PostQueryRepository { /** * Post 반환 시 Member, Profile을 fetch join한다. ~ToOne 매핑관계에 대한 fetch join은 별명을 사용할 수 있고, 연계하여 fetch * join할 수 있다. * * @param id must not be {@literal null}. * @return */ @Query(value = """ SELECT p FROM Post p LEFT JOIN FETCH p.writer AS w LEFT JOIN FETCH w.profile LEFT JOIN FETCH p.comments WHERE p.id = :postId """ ) Optional<Post> findPostById(@Param("postId") final Long id); /** * Post를 페이징 처리하여 Page<Post>로 반환한다. 이때 Member와 Profile을 fetch join한다. * * @param pageable the pageable to request a paged result, * can be {@link Pageable#unpaged()}, * must not be {@literal null}. */ @Query(value = """ SELECT p FROM Post p LEFT JOIN FETCH p.writer AS w LEFT JOIN FETCH w.profile """, countQuery = "SELECT count(p) FROM Post p" ) @Override Page<Post> findAll(final Pageable pageable); /** * WriterId가 memberId와 같은 Post를 페이징 처리하여 Page<Post>로 반환한다. 이때 Member와 Profile을 fetch join한다. * * @param writerId writerId가 일치하는 Post들을 반환한다. * @param pageable 페이징 정보 */ @Query(value = """ SELECT p FROM Post p LEFT JOIN FETCH p.writer AS w LEFT JOIN FETCH w.profile WHERE w.id = :writerId """, countQuery = "SELECT count(p) FROM Post p WHERE p.writer.id = :writerId" ) Page<Post> findAllByWriterId(@Param("writerId") final Long writerId, final Pageable pageable); }
-
해결됨스프링 시큐리티
웹기반 인가처리 실시간 DB 반영이 thread safe 한가? 질문
안녕하세요. 선생님.선생님 강의로 많이 배우고 있네요.UrlFilterInvocationSecurityMetadataSource 를 직접 구현하여 DB와 연동하는 것을 보여주셨는데.이 클래스에 Resouce 인가 설정을 위한 클래스의 멤버 변수로 LinkedHashMap<RequestMatcher, List<ConfigAttribute>> requestMap 을 사용하네요.만약 DB에 Resource, Role 인가 설정 변경 시 reload()가 불렸을 때 DB에서 모두 가져와 requestMap 에 put 하는데 이것이 multi thread 에 safe 한지요?만약 thread에 safe 하지 않다면 좋은 방법이 있는지요? lock을 쓰기에는 read 요청이 많아 부담스러울 것 같다는 느낌이 있네요.강의에서 Role 추가 시 실시간 설정 반영은 하지 않았지만 RoleHierarchy 또한 마찬가지 인 것 같아요.운영 시 거의 변경이 안되기 때문에 그냥 놔두는게 가장 좋은 방법인지? 선생님의 의견을 알고 싶어요.감사합니다.
-
해결됨즐거운 자바
static이 클라스에 부여 되었을 때
부부개발단 단톡방 : https://open.kakao.com/o/gcbnd3Ie클라스에 Static이 부여하지 않고 메서드에 static이 부여되었을 때 생성자를 사용하지 않아도 된다고 하셨는데 클라스에 자체에 static을 부여하는 경우가 궁금합니다.
-
미해결
Querydsl SQLExpressions에 listagg 관련 질문
안녕하세요, 김영한 님.Querydsl SQLExpressions에 listagg 관련하여 질문이 있습니다. 현재 Projections.constructoer 방식으로 조회한 결과를 Dto로 받고있는데요,SQLExpressions.listagg(컬럼, ",").withinGroup().orderBy(컬럼).getValue().as("listaggs")로 select후 Dto에서 String으로 못받는데 String으로 받으려면 어떻게 해야 될까요? 방법이 없는걸까요? 이미 같은 질문을 남긴 글이 있는데 미해결 상태라 다시 한번 글 올려 봅니다. 이방법을 사용하는 이유는 A 테이블, B 테이블이 있는데 1:N의 관계 입니다)A테이블 조회시 Response에는 B테이블의 컬럼 하나도 추가로 목록에 보여줘야 하는데 그럴때 B테이블의 해당 컬럼의 값이 다른 데이터가 2개 이상일시 A정보가 2건이 나오게 되서(페이징 처리시에도 총 카운트와 페이징 처리가 제대로 되지 않습니다.)한 row로 보여지게 하기 위해 사용하려 Querydsl SQLExpressions에 listagg 사용하려는데,String으로 받을수가 없더군요... 혹 Querydsl SQLExpressions에 listagg 아니더라도 다른 방법이 있을까요?
-
해결됨스프링 입문 - 코드로 배우는 스프링 부트, 웹 MVC, DB 접근 기술
private static Map<Long, Member> store = new HashMap<>(); 코드 이해가 안가요
Member.javapackage Hello.hellospring.domain; import jakarta.persistence.Entity; import jakarta.persistence.GeneratedValue; import jakarta.persistence.GenerationType; import jakarta.persistence.Id; @Entity public class Member { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; private String name; public Long getId() { return id; } public void setId(Long id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } } MemoryMemberRepository.javapackage Hello.hellospring.repository; import Hello.hellospring.domain.Member; import java.util.*; public class MemoryMemberRepository implements MemberRepository { private static Map<Long, Member> store = new HashMap<>(); private static long sequence = 0L; @Override public Member save(Member member) { member.setId(++sequence); store.put(member.getId(), member); return member; } @Override public Optional<Member> findByid(Long id) { return Optional.ofNullable(store.get(id)); } @Override public Optional<Member> findByName(String name) { return store.values().stream() .filter(member -> member.getName().equals(name)) .findAny(); } @Override public List<Member> findAll() { return new ArrayList<>(store.values()); } public void clearStore() { store.clear(); } } MemoryMemberReposirory.java 코드에서 private static Map<Long, Member> store = new HashMap<>(); 부분이 이해가 가질 않습니다..ㅠㅠ Map으로 <키 , 값>을 받으려고 하는것까진 알겠는데 왜 키는 id의 데이터타입인 Long으로 들어가는데 값은 name의 데이터타입인 String으로 들어가는것이 아닌 Member 객체로 들어가게 되는건가요..??
-
미해결실전! Querydsl
Querydsl 버전 관련
안녕하세요! Querydsl 을 공부한 후 현재 인턴으로 있는 회사에서 프로젝트에 적용해보려고 합니다. 근데 해당 프로젝트의 스프링 버전이 2.2.0 release 버전인데 해당 버전에서 Querydsl은 어떻게 해야하는지 여쭤볼 수 있을까요 ?
-
미해결자바(Java) 알고리즘 문제풀이 입문: 코딩테스트 대비
DFS로 말단노드의 레벨값 구할때
이진트리 노드의 하위노드가 한개만 한개는 없을 경우 안된다고 말씀하셨는데 실제로 실습을 해보았을때도 안되더라구여 왜 안되는지 이유를 알고 싶습니다예를 들어If(root.lt==null && root.rt ==null) return L;else if(root.lt==null && root.rt != null) return DFS(L+1, root.lt);else if(root.lt !=null && root.rt == null) return DFS(L+1, root.rt);else return Math.min(DFS(L+1, root.lt), DFS(L+1, root.rt);이렇게 했을 경우 하위노드에 있는 하위노드 두개가 있는건 하위노드로 접근했을 때 값이 존재 했는데 하위노드가 한개 있을 경우 하위노드가 존재하는 노드를 dfs로 재귀했을경우 null값으로 되어서 이게 왜 이렇게 되는건지 알고 싶습니다.
-
미해결자바(Java) 알고리즘 문제풀이 입문: 코딩테스트 대비
코드 정리한 것들 깃허브에 올려도 되나요?
강사님 안녕하세요. 강의 정말 잘 듣고 있습니다!매일 5문제씩 꾸준히 풀고 있는데,, 깃허브에 올려도 될까요?
-
미해결자바와 스프링 부트로 생애 최초 서버 만들기, 누구나 쉽게 개발부터 배포까지! [서버 개발 올인원 패키지]
deleteUser 관련 질문
현재 코드에서는 name을 기준으로 delete를 하는데요, findByName(name)을 이용한 코드에서 DB 안에 같은 이름의 회원이 2명 이상인 경우엔 오류가 생깁니다. 그 이유가 find는 return 개수가 1건이기 때문에 rollback 된다고 생각했습니다.이 버그를 수정하기 위해서 deleteUser의 파라미터는 Long id 로 수정했는데, 또 안 되더라고요...?findAll을 쓰면 같은 이름을 가진 모든 회원이 삭제될 것 같고... 어떻게 하면 동명이인의 회원 중에서 내가 원하는 한 회원만 삭제할 수 있나요? + 추가 방금 다른 학생분의 질문과 답변을 읽었습니다. 같은 내용의 질문인 것 같네요!그러면 파라미터를 Long id 로 변경하되, 현재 실습 중인 UI에서도 코드를 수정해야하는 부분이 있기에 삭제가 안 되는 게 맞다고 이해하면 될까요?
-
미해결자바 ORM 표준 JPA 프로그래밍 - 기본편
다대다
학습하는 분들께 도움이 되고, 더 좋은 답변을 드릴 수 있도록 질문전에 다음을 꼭 확인해주세요.1. 강의 내용과 관련된 질문을 남겨주세요.2. 인프런의 질문 게시판과 자주 하는 질문(링크)을 먼저 확인해주세요.(자주 하는 질문 링크: https://bit.ly/3fX6ygx)3. 질문 잘하기 메뉴얼(링크)을 먼저 읽어주세요.(질문 잘하기 메뉴얼 링크: https://bit.ly/2UfeqCG)질문 시에는 위 내용은 삭제하고 다음 내용을 남겨주세요.=========================================[질문 템플릿]1. 강의 내용과 관련된 질문인가요? 예2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? (예/아니오)3. 질문 잘하기 메뉴얼을 읽어보셨나요? (예/아니오)[질문 내용]여기에 질문 내용을 남겨주세요. 다대다 매핑을 듣다가 의문이 생겼습니다.기존에 양방향 매핑을 최대한 지양하라고 하시걸로 이해하셨는데 다대다 매핑을 일대다, 다대일로 풀어내면 멤버에는 @OneToManyprivate List<MemberProduct> memberProducts = new ArrayList();를 가지게 되고 멤버프로덕트에는@ManytoOne@JoinColumn(name = "MEMBER_ID")private Member member;를 갖게 된느데다대다 매핑을 일대다 다대일로 풀어내면 두 객체는 항상 양방향 매핑이 되어야 하는 것인가요?
-
미해결스프링 입문 - 코드로 배우는 스프링 부트, 웹 MVC, DB 접근 기술
윈도우 gradlew build 오류
학습하는 분들께 도움이 되고, 더 좋은 답변을 드릴 수 있도록 질문전에 다음을 꼭 확인해주세요.1. 강의 내용과 관련된 질문을 남겨주세요.2. 인프런의 질문 게시판과 자주 하는 질문(링크)을 먼저 확인해주세요.(자주 하는 질문 링크: https://bit.ly/3fX6ygx)3. 질문 잘하기 메뉴얼(링크)을 먼저 읽어주세요.(질문 잘하기 메뉴얼 링크: https://bit.ly/2UfeqCG)질문 시에는 위 내용은 삭제하고 다음 내용을 남겨주세요.=========================================[질문 템플릿]1. 강의 내용과 관련된 질문인가요? (예/아니오)2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? (예/아니오)3. 질문 잘하기 메뉴얼을 읽어보셨나요? (예/아니오)[질문 내용]jdk 17 스프링부트 3.0
-
해결됨실전! 스프링 부트와 JPA 활용1 - 웹 애플리케이션 개발
빌드가 안됩니다ㅜㅜ
강의 자료 코드 다운 받아서 실행하니깐 아래와 같이 나옵니다..사실 처음에 빌드 에러 발생했었는데 그건 영한님께서 항상 settings하시는대로 따라하니깐해결된 거 같은데, 이제는 아래와 같은 문제가 발생합니다ㅠ
-
미해결자바 ORM 표준 JPA 프로그래밍 - 기본편
컬렉션의 초기화 유무의 따른 size의 값이 다르게 측정됩니다.
@Transactional public void increasePoint() { Store store1 = storeRepository.findById(1L).get(); Point point = new Point(1); // System.out.println("store1.getPoints().size() = " + store1.getPoints().size()); store1.add(point); store1.add(point); store1.add(point); store1.add(point); store1.add(point); System.out.println("store1.getPoints().size() = " + store1.getPoints().size()); }@OneToMany(mappedBy = "store",cascade = CascadeType.ALL) private List<Point> points = new ArrayList<>();Store(1):Point(N) 입니다. Store 내부에 양방향으로 List로 갖고있고 현재 디비에 Store ID 1번을 외래키로 갖고있는 Point가 이미 2개가 있습니다. 위에서 첫번째 디버그 출력문을 주석처리하고 add를 5번 진행 후 마지막에 검증하게 되면 DB에 2개 + 1개 해서 사이즈가 3으로 측정됩니다.하지만 위에서 주석처리를 제거하고 size()를 통해 초기화 이후에 add를 5번 진행하고 사이즈를 출력하면 DB2개 + 5개해서 7개가 출력됩니다. 위에 두가지 상황에서 왜 초기화를 먼저 진행하고 add하는것과 add이후에 초기화 하는것이 결과가 다른지 궁금합니다. 같은 객체를 여러번 add해도 실제 DB에 인서트 쿼리는 1번만 발생하게 됩니다(위에 두 가지 경우 모두) 짐작은 되지만 정확한 이해가 되지 않는데.. 같은 객체라 영속성컨텍스트에서 관리하게 되면 이후에것은 이미 관리하고 있으니 저장하지 않는것으로 이해하면 될까요?위에서 point객체가 영속성컨텍스트에 관리되기 시작하는 시점은 언제인가요? 최초의 add호출인가요?PersistentBag의 add를 봤을때 컬렉션이 초기화 되어있지않다면 다른 리스트에 넣어두고 초기화되면서 합쳐주는것으로 확인했는데 왜 5개를 다 넣어주지 않고 1개만 넣어주는지 궁금합니다. (디버깅과정에서 자동초기화 되서 정확하지 않습니다.)
-
미해결실전 JSP (renew ver.) - 신입 프로그래머를 위한 강좌
session 변수 선언하지 않았는데 어떻게 에러가 안생기나요
loginOk.jsp에서 session = request.getSession(); 선언하지도 않고 어떻게 세션변수를 사용하나요 ..?
-
미해결실전! 스프링 부트와 JPA 활용1 - 웹 애플리케이션 개발
java.lang.IllegalStateException: Failed to load ApplicationContext 오류가 납니다.
학습하는 분들께 도움이 되고, 더 좋은 답변을 드릴 수 있도록 질문전에 다음을 꼭 확인해주세요.1. 강의 내용과 관련된 질문을 남겨주세요.2. 인프런의 질문 게시판과 자주 하는 질문(링크)을 먼저 확인해주세요.(자주 하는 질문 링크: https://bit.ly/3fX6ygx)3. 질문 잘하기 메뉴얼(링크)을 먼저 읽어주세요.(질문 잘하기 메뉴얼 링크: https://bit.ly/2UfeqCG)질문 시에는 위 내용은 삭제하고 다음 내용을 남겨주세요.=========================================[질문 템플릿]1. 강의 내용과 관련된 질문인가요? (예)2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? (아니오)3. 질문 잘하기 메뉴얼을 읽어보셨나요? (예/)[질문 내용]여기에 질문 내용을 남겨주세요.다른 답변들을 보고 모두 따라해 봤는데 아무 소용 없었습니다. h2 콘솔로는 실행이 되고 접속도 다 됩니다 근데 test를 하면 자꾸 java.lang.IllegalStateException: Failed to load ApplicationContext 이 에러가 생깁니다. at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:98) at org.springframework.test.context.support.DefaultTestContext.getApplicationContext(DefaultTestContext.java:124) at org.springframework.test.context.web.ServletTestExecutionListener.setUpRequestContextIfNecessary(ServletTestExecutionListener.java:190) at org.springframework.test.context.web.ServletTestExecutionListener.prepareTestInstance(ServletTestExecutionListener.java:132) at org.springframework.test.context.TestContextManager.prepareTestInstance(TestContextManager.java:248) at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.createTest(SpringJUnit4ClassRunner.java:227) at org.springframework.test.context.junit4.SpringJUnit4ClassRunner$1.runReflectiveCall(SpringJUnit4ClassRunner.java:289) at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12) at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.methodBlock(SpringJUnit4ClassRunner.java:291) at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:246) at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:97) at org.junit.runners.ParentRunner$4.run(ParentRunner.java:331) at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:79) at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:329) at org.junit.runners.ParentRunner.access$100(ParentRunner.java:66) at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:293) at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61) at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:70) at org.junit.runners.ParentRunner$3.evaluate(ParentRunner.java:306) at org.junit.runners.ParentRunner.run(ParentRunner.java:413) at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:190) at org.junit.runner.JUnitCore.run(JUnitCore.java:137) at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:69) at com.intellij.rt.junit.IdeaTestRunner$Repeater$1.execute(IdeaTestRunner.java:38) at com.intellij.rt.execution.junit.TestsRepeater.repeat(TestsRepeater.java:11) at com.intellij.rt.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:35) at com.intellij.rt.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:235) at com.intellij.rt.junit.JUnitStarter.main(JUnitStarter.java:54)MVCC=TRUE 지우라고 한 답변들도 있어서 지우는데도 안되네요;;;
-
미해결스프링과 JPA 기반 웹 애플리케이션 개발
compile 시 에러
컴파일 시 아래와 같은 에러가 발생하는데 해결에 어려움이 있습니다. 도움부탁드립니다. "C:\Program Files\Java\jdk-11.0.17\bin\java.exe" -Dmaven.multiModuleProjectDirectory=D:\SpringPrj\cryptoWebService "-Dmaven.home=C:\Program Files\JetBrains\IntelliJ IDEA 2020.3.1\plugins\maven\lib\maven3" "-Dclassworlds.conf=C:\Program Files\JetBrains\IntelliJ IDEA 2020.3.1\plugins\maven\lib\maven3\bin\m2.conf" "-Dmaven.ext.class.path=C:\Program Files\JetBrains\IntelliJ IDEA 2020.3.1\plugins\maven\lib\maven-event-listener.jar" "-javaagent:C:\Program Files\JetBrains\IntelliJ IDEA 2020.3.1\lib\idea_rt.jar=49589:C:\Program Files\JetBrains\IntelliJ IDEA 2020.3.1\bin" -Dfile.encoding=UTF-8 -classpath "C:\Program Files\JetBrains\IntelliJ IDEA 2020.3.1\plugins\maven\lib\maven3\boot\plexus-classworlds-2.6.0.jar;C:\Program Files\JetBrains\IntelliJ IDEA 2020.3.1\plugins\maven\lib\maven3\boot\plexus-classworlds.license" org.codehaus.classworlds.Launcher -Didea.version=2020.3.1 compile[INFO] Scanning for projects...[INFO] [INFO] ----------------------< com.studyolle:studyolle >-----------------------[INFO] Building studyolle 0.0.1-SNAPSHOT[INFO] --------------------------------[ jar ]---------------------------------[INFO] [INFO] --- apt-maven-plugin:1.1.3:process (default) @ studyolle ---[INFO] [INFO] --- frontend-maven-plugin:1.8.0:install-node-and-npm (install node and npm) @ studyolle ---[INFO] Installing node version v4.6.0[INFO] Unpacking C:\Users\sonth\.m2\repository\com\github\eirslett\node\4.6.0\node-4.6.0-win-x64.zip into D:\SpringPrj\cryptoWebService\src\main\resources\static\node\tmp[INFO] Copying node binary from D:\SpringPrj\cryptoWebService\src\main\resources\static\node\tmp\node-v4.6.0-win-x64\node.exe to D:\SpringPrj\cryptoWebService\src\main\resources\static\node\node.exe[INFO] Installed node locally.[INFO] [INFO] --- frontend-maven-plugin:1.8.0:npm (npm install) @ studyolle ---[INFO] Running 'npm install' in D:\SpringPrj\cryptoWebService\src\main\resources\static[INFO] npm WARN package.json static@1.0.0 No description[INFO] npm WARN package.json static@1.0.0 No repository field.[INFO] npm WARN package.json static@1.0.0 No README data[INFO] [INFO] --- maven-resources-plugin:3.2.0:resources (default-resources) @ studyolle ---[INFO] Using 'UTF-8' encoding to copy filtered resources.[INFO] Using 'UTF-8' encoding to copy filtered properties files.[INFO] Copying 2 resources[INFO] ------------------------------------------------------------------------[INFO] BUILD FAILURE[INFO] ------------------------------------------------------------------------[INFO] Total time: 35.495 s[INFO] Finished at: 2023-10-31T22:25:42+09:00[INFO] ------------------------------------------------------------------------[ERROR] Failed to execute goal org.apache.maven.plugins:maven-resources-plugin:3.2.0:resources (default-resources) on project studyolle: Input length = 1 -> [Help 1][ERROR] [ERROR] To see the full stack trace of the errors, re-run Maven with the -e switch.[ERROR] Re-run Maven using the -X switch to enable full debug logging.[ERROR] [ERROR] For more information about the errors and possible solutions, please read the following articles:[ERROR] [Help 1] http://cwiki.apache.org/confluence/display/MAVEN/MojoExecutionExceptionProcess finished with exit code 1