INDEX
H2
- org.h2.jdbc.JdbcSQLInvalidAuthorizationSpecException: Wrong user name or password [28000-200] [ 참고 링크 ] → H2 설정 오류
# DB 연결 주소 형식 jdbc:h2:tcp://localhost:9092/~/test # YAML 설정 spring: datasource: driver-class-name: org.h2.Driver url: jdbc:h2:tcp://localhost:9092/~/test username: sa password:
JPA
- 'Basic' attribute type should not be a container
→
@Embedded
,@Embeddable
활용을 다시 숙지
@Entity public class Place { @Embedded private Location location; } @Embeddable public class Location { private Double latitude; private Double longitude; }
- nested exception is java.lang.IllegalArgumentException: No enum constant ...(package.class)
→ Enum 대소문자 구분 문제
→ 해결방안 :
1. 다 대문자로 설정
2.
@Converter
적용
@Getter public enum ProductType { ACCOMMODATION("accommodation"), // DB에 넣고 빼오는 데이터의 대소문자 차이가 있다면 에러 LEISURE("leisure"); private final String typeName; ProductType(final String typeName) { this.typeName = typeName; } }
- Failed to initialize JPA EntityManagerFactory: Unable to find column with logical name: id
→ 이 에러는 나와 같은 상황의 에러를 정리해놓은 글이 없어서 해결하는데 오래걸렸다 😢
→
@OneToMany
옵션에 mappedBy를 변수명으로 적어야한다. 착각한 부분) - mappedBy로 명시해줘야하는 부분이 클래스명(Order)을 적는건지, 테이블명(orders)을 적는건지 모르겠어서 찾아보았다. 둘다 아니었다..! → mappedBy에는 변수명(order)을 적어야함 → OrderProduct 클래스의 order와 매핑해주는 것이기 때문에 이 변수명을 적어준다.
@Entity @Table(name = "orders") ... public class Order extends BaseTimeAndDeletedEntity { ...생략 @OneToMany(mappedBy = "order", fetch = FetchType.LAZY, cascade = CascadeType.ALL, orphanRemoval = true) private List<OrderProduct> orderProducts = new ArrayList<>(); ... }
@Entity @Table(name = "order_product") ... public class OrderProduct extends BaseTimeAndDeletedEntity { ...생략 @ManyToOne(fetch = FetchType.LAZY, optional = false) @JoinColumn(name = "order_id", referencedColumnName = "order_id", nullable = false) private Order order; ... }
Controller
- SnippetException: Cannot document response fields as the response body is empty [ 참고 링크 ] → response body에 필드가 하나면 발생하는 예외 → ApiResponse 를 만들어서 statusCode와 serverDatetime을 같이 response로 보내고 해결
@Getter @Setter @NoArgsConstructor public class ApiResponse<T> { private int statusCode; private T data; @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss", timezone = "Asia/Seoul") private LocalDateTime serverDatetime; public ApiResponse(final int statusCode, final T data) { this.statusCode = statusCode; this.data = data; this.serverDatetime = LocalDateTime.now(); } public static <T> ApiResponse<T> ok(final T data) { return new ApiResponse<>(200, data); } public static <T> ApiResponse<T> fail(final int statusCode, final T errData) { return new ApiResponse<>(statusCode, errData); } }
Transaction
- org.springframework.transaction.UnexpectedRollbackException: Transaction silently rolled back because it has been marked as rollback-only [ 참고 링크 ]
트랜잭션 롤백이 되는 에러
→ Unchecked 예외가 발생해서 롤백이 되었다.
내 경우에는 다른 트랜잭션에서 nested exception is java.lang.IllegalArgumentException: No enum constant ...(package.class) 가 발생하는 상황
다른 트랜잭션 테스트를 돌리니 롤백되는 경우였다.
테스트 코드를 여러개 실행해보다가 하나는 Transacion silently rolled back ... 이고,
다른 테스트 코드는 No enum constant ... 가 떠서 바로 알았다! (운이 좋았다)
RestDocs
- ClassCastException: class java.lang.Integer cannot be cast to class java.util.List
RestDocs 코드에서 requestFields를 하나만 지정해서 발생.
Integer가 List로 캐스팅 되지 않는 예외이지만 내 경우엔 다른 원인이었다.
→ ApiResponse 클래스를 만들어 적용
→ requestFields 에 하나의 필드만 들어오는 경우를 아예 없앤다.
(statusCode와 serverDatetime이 필수로 들어간다.)