묻고 답해요
156만명의 커뮤니티!! 함께 토론해봐요.
인프런 TOP Writers
-
미해결실전! Querydsl
스프링 테스트 실행이 안됩니다... 제발 도와주세요 ㅠㅠ
java : 21spring : 3.3.3 사용뭔가 제대로 빌드가 되지 않은 것 같아서 gradle 클린하고 재빌드하고 여러번 했는데도 반복적으로 오류 메세지가 발생합니다 ㅠㅠ영한쌤의 다른 자바 강의도 수강 중인데 그건 해당 경로에 있어도 실행이 잘되는데 특이하게 spring 프로젝트는 안되네요... 경로에 한글이 있어서 그런가 싶어 UTF-8 설정도 해두었습니다.얼른 수업 듣구 싶어욧,,, 도와주세요 ㅠㅠ
-
미해결스프링 DB 2편 - 데이터 접근 활용 기술
내부 트랜잭션 롤백시 마킹의 필요성
대원칙인 모든 논리 트랜잭션이 커밋되어야 모두가 커밋되는거고 하나라도 롤백되면 모두가 롤백된다는 개념에서 내부 트랜잭션이 롤백되면 그 시점에 모두 롤백시키면 되지 않나요? 굳이 내부 트랜잭션 롤백 후 물리 트랜잭션에 rollback_only마크를 달아 결국 모두가 롤백되도록 하는 이유가 궁금합니다.또 궁금한 점은 만약 개발자가 실수로 외부 트랜잭션을 먼저 롤백해버린다면 -> 제가 실험해보니 외부 트랜잭션 롤백시 물리 트랜잭션이 즉각 롤백이 되더라구요. 아마 isNewTransaction이 트루인 경우니 최종 결정권자의 형태로 바로 롤백을 시키는 것 같은데 그러고 나서 내부 트랜잭션 롤백을 시도하니까 여전히 롤백 마크를 남기는 로그가 뜨더라구요. 이 점에 대해서 설명 부탁드립니다:)
-
미해결스프링 DB 2편 - 데이터 접근 활용 기술
Deadlock 발생 관련 질문이 있습니다!!
[질문 내용]안녕하세요. 강의와 조금 다른 주제일 수 있으나 도움을 얻을 수 있지 않을까 하여 질문 남깁니다!!토이 프로젝트 진행중 사용자의 최근 접속시간을 주기적으로 업데이트 시킬 필요가 있어 Spring Security 인가 필터에서 현재 로그인한 유저의 최근 접속시간을 업데이트하는 쿼리를 날리도록 작성했습니다. 이 때 Deadlock이 발생하였습니다. 현재까지 제가 찾아본 바로는 DispatcherServelt 전에는 톰캣 스레드가 락을 점유하고 이후에는 IO 스레드가 락을 점유하여 그렇다는 정보를 찾을 수 있었는데요. 정확히 이해가 안가 여기에 여쭤봅니다 ㅠㅠ. 데드락이 발생하는 원인에 어떤것이 있을까요? 참고로 인가 필터에서는 jpa 리포지토리를 의존성 주입받아 사용해서 쿼리를 날렸습니다. (현재는 이 방법 자체가 데르락을 떠나 비효율적이라 판단하여 AOP로 해결한 상태입니다. 사실 이것도 효율적인 방법인지는 잘 모르겠습니다...)
-
해결됨스프링 DB 2편 - 데이터 접근 활용 기술
JpaTransactionManager 사용할 경우 커넥션 로깅 질문
DataSourceTransactionManager의 로그에는 사용되고 있는 커넥션의 정보(ex. conn0)가 자세히 나오는데, JpaTransactionManager를 사용할 경우에는 위와 같이 몇번째 커넥션이 사용되고 있는지에 대한 정보가 잘 나오지 않는 것 같습니다. JPA를 사용할 경우, 위 사진과 같이 스레드가 커넥션 풀에서 어떤 커넥션을 가져오고 반환하는지를 알 수 있는 방법이 있는지 궁금합니다!
-
미해결실전! 스프링 부트와 JPA 활용2 - API 개발과 성능 최적화
build.gradle에 queryDSL 설정이 잘되지 않습니다.
plugins { id 'java' id 'org.springframework.boot' version '3.3.1' id 'io.spring.dependency-management' version '1.1.5' } group = 'jpabook' version = '0.0.1-SNAPSHOT' java { toolchain { languageVersion = JavaLanguageVersion.of(17) } } //롬복 셋팅 configurations { compileOnly { extendsFrom annotationProcessor } } repositories { mavenCentral() } dependencies { implementation 'org.springframework.boot:spring-boot-starter-data-jpa' implementation 'org.springframework.boot:spring-boot-starter-thymeleaf' implementation 'org.springframework.boot:spring-boot-starter-web' implementation 'org.springframework.boot:spring-boot-devtools' implementation 'junit:junit:4.13.1' implementation 'com.github.gavlyukovskiy:p6spy-spring-boot-starter:1.9.1' implementation 'org.springframework.boot:spring-boot-starter-validation' implementation 'com.fasterxml.jackson.datatype:jackson-datatype-hibernate5' implementation 'javax.persistence:javax.persistence-api:2.2' compileOnly 'org.projectlombok:lombok' runtimeOnly 'com.h2database:h2' annotationProcessor 'org.projectlombok:lombok' //test 롬복 testImplementation 'org.springframework.boot:spring-boot-starter-test' testRuntimeOnly 'org.junit.platform:junit-platform-launcher' //Querydsl 추가 implementation 'com.querydsl:querydsl-jpa:5.0.0:jakarta' annotationProcessor "com.querydsl:querydsl-apt:${dependencyManagement.importedProperties['querydsl.version']}:jakarta" annotationProcessor "jakarta.annotation:jakarta.annotation-api" annotationProcessor "jakarta.persistence:jakarta.persistence-api" } tasks.named('test') { useJUnitPlatform() jvmArgs '-Xshare:off' // JVM 아규먼트 설정 } clean { delete file('src/main/generated') }이렇게 설정해둔 상태인데 gradle을 다시로드했음에도 other에 compilequerydsl 설정이 생기지 않는 상황이고, 다른방식으로 설정도 했었는데, 그때는 또 우측 gradle의 other에 compileQeurydsl 설정이 보여서 설정을 진행했고 프로젝트 generated 디렉토리가 생성되긴 했지만, generated 디렉토리 하위 파일들이 보이지 않습니다. 어떻게 해결할 수 있을까요? 커뮤니티의 내용들을 다 참고했지만 되지 않네요..
-
미해결스프링 DB 2편 - 데이터 접근 활용 기술
mybatis xml파일을 만드는중 sql문법 질문
[질문 내용]안녕하세요 열심히 강의를 듣던 중 MyBatis 적용1-기본 강의 11:37초 쯤에 and item_name...라는 sql구문을 쓰셨는데 이렇게 앞에 and가 들어가면select * from item where and item_name...이런 식으로 sql문이 쓰여지는거 아닌가요??앞에 and가 꼭 필요한건지 알아서 떼지는건지 궁금합니다!
-
미해결스프링 DB 2편 - 데이터 접근 활용 기술
Q클래스 파일 생성 오류
[질문 템플릿]1. 강의 내용과 관련된 질문인가요? (예)2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? (예)3. 질문 잘하기 메뉴얼을 읽어보셨나요? (예)[질문 내용]상황: build tool는 Gradle를 사용하고 있습니다.Gradle -> Tasks -> build -> clean Gradle -> Tasks -> other -> compileJava위에 작업을 실행해도 generated폴더에 Q클래스가 생성되지 않습니다. 참고로 generated도 생성되지 않습니다.다른 분들처럼 오류가 발생하지는 않습니다!!
-
미해결스프링 DB 2편 - 데이터 접근 활용 기술
REQUIRES_NEW와 내부 호출
[질문 템플릿]1. 강의 내용과 관련된 질문인가요? 예2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? 예3. 질문 잘하기 메뉴얼을 읽어보셨나요? 예[질문 내용]내부 호출 문제점은 REQUIRES_NEW 어노테이션이 적용된 경우에도 동일하게 발생하는 것 같은데 맞을까요?? 아래 코드를 실행했을 때 커밋이 한 번도 발생하지 않는 것을 로그로 확인했습니다. 혹시나 해서 여쭤봅니다!! @Slf4j @SpringBootTest public class InternalCallV1Test { @Autowired CallService callService; @Test void externalCall() { callService.external(); } @TestConfiguration static class InternalCallV1TestConfig { @Bean CallService callService() { return new CallService(); } } @Slf4j static class CallService { @Transactional(propagation = Propagation.REQUIRES_NEW) public void internal() { log.info("call internal"); printTxInfo(); } @Transactional public void external() { log.info("call external"); printTxInfo(); this.internal(); throw new RuntimeException("종료"); } private void printTxInfo() { boolean txActive = TransactionSynchronizationManager.isActualTransactionActive(); log.info("tx active={}", txActive); } } }
-
미해결스프링 DB 2편 - 데이터 접근 활용 기술
ItemRepository 인터페이스 생성 이유??
1. 강의 내용과 관련된 질문인가요? (아니오)2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? (예)3. 질문 잘하기 메뉴얼을 읽어보셨나요? (예)[질문 내용]ItemRepository 인터페이스 생성한 이유가 궁금해서 질문드립니다.강의에서 해당 인터페이스를 생성하는 이유가 영한님이 알려주신 강의에서는 jdbctemplate, mybatis, jpa등등 데이터 접근 기술들을 알려주셔서 해당 구현체들을 추상화 목적으로 만드신건가요?? 아니면 현업에서는 일반적으로 영한님처럼 파일 구조로 만드나요??
-
미해결스프링 DB 2편 - 데이터 접근 활용 기술
내부 트랜잭션 커밋
학습하는 분들께 도움이 되고, 더 좋은 답변을 드릴 수 있도록 질문전에 다음을 꼭 확인해주세요.1. 강의 내용과 관련된 질문을 남겨주세요.2. 인프런의 질문 게시판과 자주 하는 질문(링크)을 먼저 확인해주세요.(자주 하는 질문 링크: https://bit.ly/3fX6ygx)3. 질문 잘하기 메뉴얼(링크)을 먼저 읽어주세요.(질문 잘하기 메뉴얼 링크: https://bit.ly/2UfeqCG)질문 시에는 위 내용은 삭제하고 다음 내용을 남겨주세요.=========================================[질문 템플릿]1. 강의 내용과 관련된 질문인가요? (예/아니오)2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? (예/아니오)3. 질문 잘하기 메뉴얼을 읽어보셨나요? (예/아니오)[질문 내용]내부 트랜잭션을 커밋 하지 않고 바로 외부 트랜잭션을 커밋 해도 문제는 없는건가요?
-
미해결스프링 DB 2편 - 데이터 접근 활용 기술
프록시 객체 트랜잭션 내부 호출
학습하는 분들께 도움이 되고, 더 좋은 답변을 드릴 수 있도록 질문전에 다음을 꼭 확인해주세요.1. 강의 내용과 관련된 질문을 남겨주세요.2. 인프런의 질문 게시판과 자주 하는 질문(링크)을 먼저 확인해주세요.(자주 하는 질문 링크: https://bit.ly/3fX6ygx)3. 질문 잘하기 메뉴얼(링크)을 먼저 읽어주세요.(질문 잘하기 메뉴얼 링크: https://bit.ly/2UfeqCG)질문 시에는 위 내용은 삭제하고 다음 내용을 남겨주세요.=========================================[질문 템플릿]1. 강의 내용과 관련된 질문인가요? (예/아니오)2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? (예/아니오)3. 질문 잘하기 메뉴얼을 읽어보셨나요? (예/아니오)[질문 내용]@Transactional이 작성되지 않은 메서드에서 @Transactional이 작성된 자신의 메서드를 호출하면 트랜잭션이 실행되지 않는다는 것은 이해하였습니다. 그러면 @Transactional이 작성된 메서드에서 @Transactional이 작성된 자신의 메서드를 호출하면 현재 자신이 프록시 객체이므로 트랜잭션이 실행되는걸까요? 아니면 현재 프록시 객체가 아니라 타겟 객체이므로 똑같이 트랜잭션이 실행되지않는걸까요?
-
미해결실전! Querydsl
querydsl 2개의 파일에서 같은 조건을 사용해야 할 경우
강사님 안녕하세요.좋은 강의 잘 들었습니다.querydsl의 정점 중 하나로 where 조건문을 분리하고 재사용한다고 했는데,예를 들어 UserRepository, StudyRepository라는 2개의 querydsl을 사용하는 repository가 있다 했을 때, 각각의 respository 에서 조회를 할 때 동일한 조건을 사용해야 할 경우가 있습니다. UserRepository.javapublic User getUser(Long UserId) { return selectForm(user) .where(userId); } private BooleanExpression eqUser(Long userId) { return user.userId.eq(userId); }StudyRepository.javapublic User getUser(Long UserId) { select(study) .from(study.user, user) .join(study.user) .where(user.userId.eq(UserId)); } private BooleanExpression eqUser(Long userId) { return user.userId.eq(userId); } 이렇게 .where(user.userId.eq(1L)) 가 2개의 파일에서 반복되는 경우 각각의 파일에 메소드로 사용하는게 좋을까요? 아니면 다음처럼 공통 유틸 파일을 만들어서 공통으로 사용하는게 좋을까요?QueryUtils.javapublic static BooleanExpression eqUser(Long userId) { return user.userId.eq(userId); }실무에서는 어떻게 사용 할까요? 이런 경우가 빈번해서 질문 드립니다.
-
미해결스프링 DB 2편 - 데이터 접근 활용 기술
스프링 부트가 제공하는 임베디드 DB DataSource 스프링 빈 자동 등록 관련
[질문 템플릿]1. 강의 내용과 관련된 질문인가요? 예2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? 예3. 질문 잘하기 메뉴얼을 읽어보셨나요? 예[질문 내용]안녕하세요.H2 DB는 자바로 만들어져 있고, 덕분에 JVM 내부에서 동작하는 임베디드 모드를 지원한다고 이해했습니다.스프링 부트는 데이터베이스에 대한 별다른 설정이 없으면 임베디드 데이터베이스를 사용(제공)한다고 하는데..질문: 그렇다면 스프링 부트가 DataSource를 스프링 빈으로 자동 등록 시 라이브러리(의존 관계)에서 H2가 있는지를 먼저 확인하고, 별도의 설정(application.properties 내 url, username 등)이 없으면 임베디드 모드로 DataSource를 생성하여 빈으로 등록하는 건가요? 아니면 application.properties를 먼저 확인하고 url이 없으면 -> 라이브러리에 H2가 있는지 확인 후 메모리 DB를 사용하는 DataSource를 생성하여 빈으로 등록하는 건가요? 만약 후자라면 왜 그렇게 설계했을지(이점?)도 궁금합니다.. 감사합니다.
-
미해결스프링 DB 2편 - 데이터 접근 활용 기술
인터페이스 테스트인데 왜 구현체가 나오는건가요?
코드를 보면 초기화를 MemoryItemRepository로 하지 않고 ItemRepository로 초기화를 했는데 인터페이스는 구현체가 아니라서 함수가 정의가 안 되어있는데 어디서 구현체를 들고와서 테스트가 진행되는건가요..?
-
미해결스프링 DB 2편 - 데이터 접근 활용 기술
REQUIRES_NEW인데 rollback되는 이유가 궁금합니다.
@Service @RequiredArgsConstructor @Transactional public class UserService { public void createUser(CreateUserRequest request) { Users users = firebaseUsersRepository.findUsersByFirebaseUid(request.getFirebaseUid()) .orElseThrow(() -> new BusinessException("Not Found User", HttpStatus.INTERNAL_SERVER_ERROR)); User user = User.builder() .name(users.getDisplay_name()) .firebaseUid(request.getFirebaseUid()) .build(); userRepository.save(user); } } @Component @RequiredArgsConstructor @Transactional(propagation = Propagation.REQUIRES_NEW) public class BaseEntityAuditAware implements AuditorAware<User> { private final UserRepository userRepository; @Override public Optional<User> getCurrentAuditor() { try { return userRepository.findById(ApiLogger.getRequestCallerId()); } catch (Exception e) { return Optional.empty(); } } }createUser에서 userRepository.save(user)를 호출할때,JpaAudit기능을 이용하기 위해 구현해놓은 BaseEntityAuditAware에서 유저정보를 가져온 후, 실제 쿼리를 날립니다.이때, 전파속성이 REQUIRE_NEW이며, 발생한 모든 예외를 catch했으므로이 함수를 호출한 부모 함수로 해당 예외가 전달되지 않을 것이기때문에 rollback이 되지 않으리라 기대했지만실제로는 unexpectedrollbackexception이 발생하며 롤백이 되었습니다.null을 반환하는건 문제가 아닌것이,실제로 예외를 발생시키지 않으려고 위 코드를 아래와같이 변경하였더니 null값으로 정상적으로 insert쿼리가 날라갔습니다. @Override public Optional<User> getCurrentAuditor() { Long callerId = ApiLogger.getRequestCallerId(); if (callerId == null) return Optional.empty(); return userRepository.findById(ApiLogger.getRequestCallerId()); }어느부분이 잘못된것이며 제가 오개념을 잡고있는 부분이 어디일까요?
-
미해결스프링 DB 2편 - 데이터 접근 활용 기술
test 코드 실행 시 전부 실패
[질문 템플릿]1. 강의 내용과 관련된 질문인가요? (예/아니오)2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? (예/아니오)3. 질문 잘하기 메뉴얼을 읽어보셨나요? (예/아니오)[질문 내용]https://drive.google.com/drive/folders/1omwrHagdmHylTjdmWgRgTnX7nQkNpvms?usp=sharingtest 코드 실행을 하는데 전부 다 실패합니다.datasource에 문제가 있는 것 같은데 왜 문제가 생긴건지 모르겠습니다.
-
미해결실전! Querydsl
컬렉션 조회 최적화와 동적쿼리에 대한 질문입니다
[질문 템플릿]1. 강의 내용과 관련된 질문인가요? (예/아니오)2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? (예/아니오)3. 질문 잘하기 메뉴얼을 읽어보셨나요? (예/아니오)[질문 내용]여기에 질문 내용을 남겨주세요.안녕하세요 강사님! 최근 JPA2 에서 수강한 컬렉션 최적화와 QueryDSL을 통해서 주변 병원 조회 기능을 구현하던중에 궁금한것이 생겨서 질문남깁니다.현재 @Entity @Getter @AllArgsConstructor @NoArgsConstructor(access = AccessLevel.PROTECTED) @SQLDelete(sql = "UPDATE store SET store_status = 'DEACTIVATE' WHERE store_id=?") @SQLRestriction("store_status = 'ACTIVATE'") @Inheritance(strategy = InheritanceType.JOINED) @DiscriminatorColumn // 하위 테이블의 구분 컬럼 생성 @Table(name = "store", indexes = { @Index(name = "idx_store_name", columnList = "storeName") }) public abstract class Store extends BaseEntity { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) @Column(name = "store_id") private Long storeId; @NotNull @Size(min = 2) @Column(nullable = false) private String storeName; private String storePhone; private String thumbnailUrl; private String notice; private String websiteLink; @Column(columnDefinition = "TEXT") private String storeInfo; private String storeInfoPhoto; @Enumerated(EnumType.STRING) private BaseStatus storeStatus; @Embedded private Address address; @OneToMany(mappedBy = "store", fetch = FetchType.LAZY) private List<BusinessHour> businessHours = new ArrayList<>(); @OneToMany(mappedBy = "store", fetch = FetchType.LAZY) private List<StorePhoto> storePhotos = new ArrayList<>(); // @OneToMany(mappedBy = "store", fetch = FetchType.LAZY) // private List<Reserve> reserves = new ArrayList<>(); @OneToMany(mappedBy = "store", fetch = FetchType.LAZY) private List<Review> reviews = new ArrayList<>(); @OneToOne(mappedBy = "store", fetch = FetchType.LAZY, cascade = CascadeType.ALL, optional = false) private RegistrationInfo registrationInfo; } 현재 이런식으로 Store 엔티티가 준비되어 있는 상황입니다.아래는 이를 상속한 Hospital 엔티티입니다.@Entity @Getter @Builder @NoArgsConstructor(access = AccessLevel.PROTECTED) @AllArgsConstructor @DiscriminatorValue("H") @OnDelete(action = OnDeleteAction.CASCADE) @Table(name = "hospital") public class Hospital extends Store { private String additionalServiceTag; @OneToMany(mappedBy = "hospital", fetch = FetchType.LAZY) private List<TagMapper> tags = new ArrayList<>(); }변경전 코드List<StoreQueryInfo> hospitalInfoList = jpaQueryFactory .select( Projections.constructor( StoreQueryInfo.class, hospital.storeId.as("storeId"), hospital.storeName.as("storeName"), hospital.thumbnailUrl.as("thumbnailUrl"), businessHour.startTime.as("startTime"), businessHour.endTime.as("endTime"), businessHour.breakStartTime.as("breakStartTime"), businessHour.breakEndTime.as("breakEndTime"), review.reviewId.count().as("reviewCount"), review.rating.avg().as("ratingAvg"), Expressions.stringTemplate( "ST_Distance_Sphere(ST_PointFromText({0}, 4326), {1})", point, hospital.address.point ).castToNum(Double.class).as("distance") ) ).from(hospital) .leftJoin(hospital.businessHours, businessHour) .on(businessHour.dayOfWeek.eq(dayOfWeek)) .leftJoin(hospital.reviews, review) .leftJoin(hospital.tags, tagMapper) .leftJoin(tagMapper.hospitalTag, hospitalTag) .where( inDistance(point, queryCond.radius()), businessHourEq(queryCond.businessHourCond()), specialitiesEq(queryCond.specialitiesCond()), emergencyEq(queryCond.emergencyCond()), isOpen(queryCond.openCond(), Time.valueOf(now.minusHours(4))) ) .groupBy( hospital.storeId, hospital.storeName, businessHour.startTime, businessHour.endTime, businessHour.breakStartTime, businessHour.breakEndTime ) .orderBy(Expressions.stringTemplate( "ST_Distance_Sphere(ST_PointFromText({0}, 4326), {1})", point, hospital.address.point ).asc()) .fetch();변경 후 코드 (변경전의 동적쿼리 미적용)public List<StoreQueryTotalInfo> findHospitalOptimization( Pageable pageable, int dayOfWeek, String point, LocalTime now, HospitalQueryCond queryCond) { NumberPath<Double> distanceAlias = Expressions.numberPath(Double.class, "distance"); // 일단 반경 내의 병원 정보를 모두 가져옴. List<Tuple> hospitals = jpaQueryFactory .select( hospital, Expressions.stringTemplate( "ST_Distance_Sphere(ST_PointFromText({0}, 4326), {1})", point, hospital.address.point ).castToNum(Double.class).as(distanceAlias) ).from(hospital) .leftJoin(hospital.registrationInfo, registrationInfo).fetchJoin() .where(inDistance(point, queryCond.radius())) .fetch(); // // 병원 돌면서 DTO 채우기 List<TestDTO> list = new ArrayList<>(); for (Tuple tuple : hospitals) { Hospital hospital1 = tuple.get(hospital); Double distance = tuple.get(distanceAlias); log.info("Hospital: " + hospital1 + ", Distance: " + distance); list.add(TestDTO.builder() .storeId(hospital1.getStoreId()) .storeName(hospital1.getStoreName()) .thumbnailUrl(hospital1.getThumbnailUrl()) .time(Times.of(hospital1.getBusinessHours(), dayOfWeek)) .reviewCount((long) hospital1.getReviews().size()) .ratingAvg(Review.getRatingAvg(hospital1.getReviews())) .distance(formatDistance(distance)) .tags(TagInfo.from(hospital1.getTags())) .build()); } return null; }강의를 듣기 전에는 @OneToMany 관계까지 모두 leftJoin()을 이용해서 데이터를 가져왔는데 쿼리가 무진장 많이 나가는 상황이 발생하더라고요.그래서 컬렉션 쿼리 최적화 수업을 들은 후 위의 코드로 변경하였습니다. (@ToOne 관계만 fetchJoin 하기, @OneToMany 관계는 가져와진 객체에 직접 접근해서 가져오는 방식으로 진행했습니다.) 근데 이때 동적쿼리를 어떤식으로 적용해야하는지 감이 잡히지 않더라고요..! 일단 원하는 반경 내의 병원을 모두 조회해서 가져오기 repository단에서 반복문을 돌면서 queryCond의 null값을 체크하며 수동으로 동적쿼리를 적용해야 하기 (코드단에서 동적쿼리 적용)위의 방식을 생각하고 있는데 이게 과연 동적 쿼리(?)가 맞는지 의구심이 들더라고요. 적용해야 하는 동적쿼리는 아래 코드와 같습니다.private BooleanExpression businessHourEq(String businessHourCond) { return businessHourCond != null ? hospitalTag.tagType.eq(HospitalTagType.BUSINESSHOUR).and(hospitalTag.tagContent.eq(businessHourCond)) : null; } private BooleanExpression specialitiesEq(String specialitiesCond) { return specialitiesCond != null ? hospitalTag.tagType.eq(HospitalTagType.SPECIALITIES).and(hospitalTag.tagContent.eq(specialitiesCond)) : null; } private BooleanExpression emergencyEq(String emergencyCond) { return emergencyCond.equals("EMERGENCY") ? hospitalTag.tagType.eq(HospitalTagType.EMERGENCY).and(hospitalTag.tagContent.eq(emergencyCond)) : null; } private BooleanExpression inDistance(String point, Integer radius) { return radius != null ? Expressions.booleanTemplate( "ST_Contains(ST_Buffer(ST_PointFromText({0}, 4326), {1}), {2})", point, radius, hospital.address.point ) : null; } private BooleanExpression isOpen(String isOpen, Time now) { return isOpen.equals("OPEN") ? businessHour.startTime.isNotNull().and(businessHour.endTime.isNotNull()) .and(businessHour.startTime.loe(now)).and(businessHour.endTime.goe(now)) : null; }
-
미해결스프링 DB 2편 - 데이터 접근 활용 기술
mybatis적용2테스트시 오류발생
https://drive.google.com/file/d/1rDjuTFQjZZOER9yTzPuAWsmouu9D_p26/view?usp=sharing미치겠네요. 그대로 따라했는데 왜오류일까요
-
미해결스프링 DB 2편 - 데이터 접근 활용 기술
컨트롤러 패키지명
학습하는 분들께 도움이 되고, 더 좋은 답변을 드릴 수 있도록 질문전에 다음을 꼭 확인해주세요.1. 강의 내용과 관련된 질문을 남겨주세요.2. 인프런의 질문 게시판과 자주 하는 질문(링크)을 먼저 확인해주세요.(자주 하는 질문 링크: https://bit.ly/3fX6ygx)3. 질문 잘하기 메뉴얼(링크)을 먼저 읽어주세요.(질문 잘하기 메뉴얼 링크: https://bit.ly/2UfeqCG)질문 시에는 위 내용은 삭제하고 다음 내용을 남겨주세요.=========================================[질문 템플릿]1. 강의 내용과 관련된 질문인가요? (예/아니오)2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? (예/아니오)3. 질문 잘하기 메뉴얼을 읽어보셨나요? (예/아니오)[질문 내용]컨트롤러를 두는 패키지명을 controller가 아닌 web으로 하신 이유가 궁금합니다
-
미해결스프링 DB 2편 - 데이터 접근 활용 기술
프록시 객체의 this
[질문 템플릿]1. 강의 내용과 관련된 질문인가요? (예)2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? (예)3. 질문 잘하기 메뉴얼을 읽어보셨나요? (예)[질문 내용]안녕하세요! 이번 강의 내용 중에 자바 언어에서 메서드 앞에 별도의 참조가 없으면 this라는 뜻으로 자기 자신의 인스턴스를 가리킨다는 this.internal() 이 되는데, 여기서 this 는 자기 자신을 가리키므로, 실제 대상 객체(target)의 인스턴스를 뜻한다.라고 설명이 되어 있는데 지금 까지 알던 개념은 CallService(부모), CallServiceProxy(자식)관계가 존재한다면 CallServiceProxy 입장에서는 this는 자기 자신의 주솟값을 가리킨다. super는 부모 즉 CallService의 주솟값을 가리킨다 입니다 여기서 this는 그럼 프록시 자기 자신의 객체 주솟값이 아닌(부모의 주솟값 == super == trarget )를 가리킨다고 이해하면 될까요? 그렇다고 하면 해당 프록시 객체는 자기 자신의 참조 주솟값은 스택 프레임에서 가지지 않는 걸까요?