
PersistenceException: Unable to build Hibernate SessionFactory
DataSourceBeanCreationException: Failed to create database
SQLGrammarException: Table doesn't exist
원인
MySQL 연결 설정 오류, 데이터베이스 권한 부족, Hibernate DDL 설정 오류가 겹쳐 발생함.
문제 해결 과정
createDatabaseIfNotExist=true 옵션을 추가하여 자동으로 데이터베이스가 생성되도록 수정함.해결 방법
application.yml 설정을 다음과 같이 개선하고 데이터베이스 권한을 수정함:
spring:
datasource:
url: jdbc:mysql://localhost:3306/zb-payment-study-test?createDatabaseIfNotExist=true&useSSL=false
username: root
password: root1234
driver-class-name: com.mysql.cj.jdbc.Driver
hikari:
maximum-pool-size: 10
minimum-idle: 5
idle-timeout: 300000
connection-timeout: 20000
connection-test-query: SELECT 1
jpa:
hibernate:
ddl-auto: create
properties:
hibernate:
dialect: org.hibernate.dialect.MySQL8Dialect
format_sql: true
show_sql: true
CREATE DATABASE IF NOT EXISTS zb_payment_study_test;
GRANT ALL PRIVILEGES ON zb_payment_study_test.* TO 'root'@'localhost';
FLUSH PRIVILEGES;
org.hibernate.LazyInitializationException: failed to lazily initialize a collection
DataIntegrityViolationException: Cannot delete or update a parent row
원인
문제 해결 과정
해결 방법
@Entity
public class Store {
@OneToMany(mappedBy = "store", cascade = CascadeType.ALL, fetch = FetchType.LAZY)
private List<Reservation> reservations = new ArrayList<>();
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "owner_id", nullable = false)
private Member owner;
}
@Repository
public interface StoreRepository extends JpaRepository<Store, Long> {
@EntityGraph(attributePaths = {"owner", "reservations"})
Optional<Store> findWithOwnerById(Long id);
}
@Transactional
public void deleteStore(Long storeId) {
Store store = storeRepository.findById(storeId)
.orElseThrow(() -> new BusinessException(ErrorCode.STORE_NOT_FOUND));
reservationRepository.deleteAllByStoreId(storeId);
reviewRepository.deleteAllByStoreId(storeId);
storeRepository.delete(store);
}
원인
문제 해결 과정
해결 방법
dependencies {
implementation 'com.querydsl:querydsl-jpa:5.0.0:jakarta'
annotationProcessor 'com.querydsl:querydsl-apt:5.0.0:jakarta'
}
def querydslDir = layout.buildDirectory.dir("generated/querydsl").get().asFile
sourceSets {
main.java.srcDirs += querydslDir
}
private BooleanExpression createWhereCondition(StoreSearchCriteria criteria) {
BooleanExpression condition = null;
if (StringUtils.hasText(criteria.keyword())) {
condition = store.name.containsIgnoreCase(criteria.keyword())
.or(store.location.containsIgnoreCase(criteria.keyword()));
}
if (criteria.latitude() != null && criteria.longitude() != null) {
BooleanExpression locationCondition = createLocationCondition(
criteria.latitude(), criteria.longitude()
);
condition = condition == null ? locationCondition : condition.and(locationCondition);
}
return condition;
}
StackOverflowError: Infinite recursion
원인
문제 해결 과정
해결 방법
@Aspect
@Component
@Slf4j
public class LoggingAspect {
@Pointcut("execution(* com.zerobase.zbpaymentstudy..*Service.*(..))")
private void allService() {}
@Around("allService()")
public Object logging(ProceedingJoinPoint joinPoint) throws Throwable {
String methodName = joinPoint.getSignature().getName();
try {
log.info("Start - {} args: {}", methodName,
Arrays.toString(joinPoint.getArgs()));
Object result = joinPoint.proceed();
log.info("End - {} result: {}", methodName, result);
return result;
} catch (Exception e) {
log.error("Error - {} error: {}", methodName, e.getMessage());
throw e;
}
}
}
TransactionRequiredException: No transaction aspect-managed TransactionStatus in scope
원인
문제 해결 과정
해결 방법
@Service
@Transactional
public class ReservationServiceImpl implements ReservationService {
@Transactional(readOnly = true)
public Page<ReservationDto> findReservations(...) {
// 조회 로직
}
@Transactional
public ApiResponse<ReservationDto> createReservation(...) {
// 예약 생성 로직
}
}
도메인 구조 개선
Redis 통합
일관된 예외 처리
테스트 코드 개선
이번 프로젝트에서 다양한 오류를 경험하며 문제 해결 능력을 크게 향상시킬 수 있었다. 특히 오류를 해결하면서 시스템이 점점 더 견고해지는 것을 체감할 수 있었고, 앞으로 더 나은 설계와 최적화를 적용할 수 있는 자신감을 얻었다.
"나이가 60이다 70이다 하는 것으로 그 사람이 늙었다 젊었다 할 수 없다. 늙고 젊은 것은 그 사람의 신념이 늙었느냐 젊었느냐 하는데 있다."
-맥아더-