동적 쿼리 사용 시 where 절 안에서 사용할 메소드들을 계속해서 만들다 보니 BooleanExpression(Predicate)을 만드는 코드의 양이 계속 커지고 매번 null 처리를 해주는 과정이 반복되서 이것마저 귀찮다고 느껴져 유틸 클래스를 만들어 보았습니다. 유틸 클래스 샘플 코드는 아래와 같습니다. public class DynamicQueryUtils { public static <T> BooleanExpression eq(SimpleExpression<T> left, T right) { return right == null ? null : left.eq(right); } public static <T extends Number & Comparable<?>> BooleanExpression loe(NumberExpression<T> left, T right) { return right == null ? null : left.loe(right); } public static <T extends Number & Comparable<?>> BooleanExpression goe(NumberExpression<T> left, T right) { return right == null ? null : left.goe(right); } } 위와 같이 유틸 클래스에서 null을 확인해주는 메소드를 한번 만든 뒤 부터는 Repository에서 쿼리를 작성할 때 더 이상 null 처리를 신경 쓰지 않고 코드를 짤 수 있었습니다. public List<MemberTeamDto> searchMember(MemberSearchCondition condition) { return query.select(new QMemberTeamDto(member.id, member.username, member.age, team.id, team.name)) .from(member) .join(member.team, team) .where( eq(member.username, condition.getUsername( )), eq(team.name, condition.getTeamName( )), goe(member.age, condition.getAgeGoe( )), loe(member.age, condition.getAgeLoe( )) ) .fetch( ); } 실제로 member를 검색하는 메소드를 변경해보았는데 static import를 활용하면 where 절 내부도 깔끔하게 만들 수 있고 BooleanBuilder를 사용하거나 usernameEq과 같은 추가적인 메소드를 만들지 않고도 동적 쿼리를 만들 수 있었습니다. 또, 기존 메소드를 이용하면 강력하게 활용할 수 있던 메소드 체이닝 기능도 유틸 클래스에서 비슷하게 제공하여 BooleanExpression(Predicate)을 열거하면 조건들을 조합할 수 있는 메소드를 만들었습니다. public class DynamicQueryUtils { public static Predicate conditions(Predicate... predicates) { BooleanBuilder condition = new BooleanBuilder( ); Arrays.stream(predicates).filter(Objects::nonNull).forEach(condition::and); return condition.getValue( ); } } private Predicate isValid(MemberSearchCondition condition) { return conditions( eq(member.username, condition.getUsername( )), eq(team.name, condition.getTeamName( )), goe(member.age, condition.getAgeGoe( )), loe(member.age, condition.getAgeLoe( )) ); } 이런 식으로 유틸 클래스를 한 번 만들고나니 Repository 계층을 작성하는 시점부터는 null을 신경쓰지 않고 코드를 작성할 수 있게 되더라구요. Querydsl에서 혹은 서드파티 라이브러리에서 제공해 줄 것 같기도 한데 Querydsl 생태계를 잘 몰라 아직 찾지는 못하고 있는 상황입니다. 이런 방식으로 쿼리를 생성하는 건 어떨까요?
https://www.figma.com/file/ym3ERAa0aBNWdNMnERMeGf/0719-%EC%8B%A4%EC%8A%B5?node-id=0%3A1 기본 기능 사용 및 고급 기능 사용 챕터를 수강할 때 같이 따라하며 그려본 Figma 프로젝트 링크입니다. 컴포넌트 생성과 텍스트, 컬러 스타일 만들기를 통해 이전보다 더 쉽게 피그마로 서비스 기획을 할 수 있을 것 같습니다!
안녕하세요. 아직 완강은 못했지만 강의 들으면서 연습&재미삼아 만든 토이프로젝트가 있어서, 어디 올릴까 하다가 감동의 완강기념 기타 연주가 생각나서 여기 올려봅니다 ㅎㅎ 장고 베이스로 만들었고요, 실습했던 vultr에서 docker 사용해서 구동 중입니다. 가상서버 사이트 중에 vultr가 편의성이나 가성비 측면에서 꽤 훌륭하더라고요~ 좋은 강의 다시 한번 감사드립니다 :) ㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡ 코로나 때문에 해외여행 못 간지 백만년... 여행에 대한 간절한 마음을 '여최몇?'이라는 토이 프로젝트로 풀어내보았습니다. http://mytravel.letsgo247.net 지금까지 여행 했던 나라들을 선택하면 여행 경력에 대한 간략한 통계를 다른 참가자들의 것과 비교해서 보여주는 간단한 웹앱입니다. 사용자들이 각자 여행했던 나라들을 리스트업 하고 친구들과 공유하며 프리-코로나 시대의 추억을 되살렸으면 하는 소망을 가지고 만들었습니다. 재미삼아 한번씩 해보세요~ 피드백이나 코멘트도 환영입니다!
[개정판 2023-11-27] Spring Boot 3.x 를 이용한 RESTful Web Services 개발
안녕하세요 선생님 Mybatis에서는 DAO를 interface로 선언하고 mapper.xml를 mapping하여 dao의 구현부로 xml이 될수있도록 했는데 JPA에서는 어떻게 동작하는것일까요? UserRepository를 interface로 선언하고 구현부 없이 Bean를 만들려고 하면 에러가 발생하지 않나는 생각이 들면서 따로 UserRepository의 구현부가 있을거라고 생각이 드는데 이부분이 맞을까요? 추가적이 설명 부탁드리겠습니다.
1. 외주를 할 때 자주 쓰이는 기술들을 가지고 다양한 앱 개발을 진행해봤으면 좋겠습니다.(외주를 해본 경험이 없어서 어떤 기술이 자주 쓰이는 지를 몰라 조금 두루뭉술하게 글 남깁니다.) 2. 앱 개발하면서 꼭 알고 넘어가면 좋겠다 싶은 라이브러리들을 사용해서 앱 개발을 진행해봤으면 좋겠습니다.
terminal cocoapods + ffi 삭제: sudo gem uninstall cocoapods sudo gem uninstall ffi arch 명령으로 cocoapods를 다시 설치하십시오. arch -x86_64 sudo gem install cocoapods arch 명령으로 포드 업데이트/설치를 수행하십시오. arch -x86_64 pod install pod install 명령어 작동시 문제가 발생했는데 해당방법으로 문제 해결했습니다
@Test void stringToIpPort() { IpPortToStringConverter converter = new IpPortToStringConverter(); IpPort source = new IpPort("127.0.0.1", 8080); String result = converter.convert(source); assertThat(result).isEqualTo("127.0.0.1:8080"); } @Test void ipPortToString() { StringToIpPortConverter converter = new StringToIpPortConverter(); String source = "127.0.0.1:8080"; IpPort result = converter.convert(source); assertThat(result).isEqualTo(new IpPort("127.0.0.1", 8080)); } 10. 스프링 타입 컨버터.pdf 10p ConverterTest.java 에서 함수 이름이 뒤집힌것 같습니다. stringToIpPort함수에서 IpPort를 String으로 바꾸는 작업을 하고, ipPortToString함수에서 String을 ipPort로 바꾸는 작업을 하네요.
let menu = { width: 200, height: 300, title: "My menu" }; function multiplyNumeric (obj) { for (let sum in obj) { if (typeof obj[sum] == 'number') { obj[sum] * = 2 } } return menu } multiplyNumeric(menu); /* { "width": 400, "height": 600, "title": "My menu" } */ 색을 칠한 부분을 *=가 아닌 *만 하면 처음 menu값만 나오는데, *=와 *의 로직을 잘 이해하지 못하겠습니다..ㅠㅠ 고수님들 도와주실 수 있나요??
중/상급 버전을 ci/cd 파이프라인을 보려 구매 하였지만 초급버전을 보면서 개발자 입장에서 aws 아키텍쳐를 이해 할 수 있었던 너무 좋은 겸험이였습니다 조그마난 바램이라면 추후에 실무편으로 개발자 입장에서 리엑트,장고 , mysql 등 간단하게 3tier을 서버리스 ci/cd 파이프라인으로 구축하고 배포 하는 강의를 간단하게나마 해주시면 가격과 상관없이 무조건 시청하겠습니다! 역시 파이썬 공부 열심히 해야되겠다 다시한번 강하게 느끼었습니다 고생많으셧습니다.!