POJO 란 Plain Old Java Object 의 줄임말로 특별한 제약이 없는 객체를 의미한다.특별한 제약이란 무엇일까? 객체 설계 관점에서 필요에 의한게 아니라 다른 외부 기술의 사용 때문에 객체에 제약이 생기는 경우이다.예를들어 서블릿을 생각해보자. 서블릿을 이용해서 http 요청에 매핑하는 것과 스프링의 컨트롤러를 이용하는 코드를 비교해자.// HttpServletRequest 를 상속받는다public class HttpRequestMapping extends HttpServletRequest { }// 애노테이션으로 요청을 받음을 표현한다@Controllerpublic class HttpRequestMapping { }서블릿 같은 경우 HttpServletRequest 를 필수로 상속 받아야..
spring boot 버전을 올리면서 3.4.x 버전을 사용하게 됐고, 동작을 확인하던 도중 기존 코드에서 에러가 발생했다.Row was updated or deleted by another transaction (or unsaved-value mapping was incorrect)해당 로우가 다른 트랜잭션에서 업데이트되거나 삭제되었다는 메시지인데, 버전을 올리지 않으면 해당 에러는 발생하지 않았다. 해당 문제가 발생할 수 있는 상황은 이렇다.// 엔티티 정의@Entity@Table(name = "person")@AllArgsConstructor@NoArgsConstructor(access = AccessLevel.PROTECTED)public class Person { @Id @Generated..
기존 spring boot 3.0.13 버전에서 3.1.12 로 버전업을 시도했다. 하위호환을 잘 보장해준 덕에 큰 이슈없이 빌드에 성공했는데 엔티티 조회시 ArrayIndexOutOfBoundsException 이 발생하는걸 확인했다. 해당 엔티티는 크게 복잡하지 않은 보통의 엔티티였는데 왜 문제가 발생한건지 정리하려한다. 문제가 발생하는 환경을 간단한 엔티티로 표현하면 이렇다.@Entity@Table(name = "car")public class Car { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) @Column(name = "car_id") private Long id; @Column(name = "car_type") ..
현재 진행중인 프로젝트에서 spring boot 2.7.18 을 사용하고 있다. 현시점(2024.04.28) 기준 2.x 버전에서 가장 최신이다. 엔티티 로딩과정에서 직관적이지 못한 이슈를 만나서 정리하고, 어떤때 발생하고 어떻게 해결할 수 있는지 정리해보려한다. spring boot2.7.18hibernate-core5.6.15.Final # 이슈상황- 엔티티 Main 과 엔티티 Sub 는 1:1 관계로 @OneToOne 관계를 맺고있다(fetchType 은 디폴트 설정인 EAGER 를 사용한다). 외래키는 Main 에서 관리한다고 가정한다.- Main 과 Sub 는 논리적 연관관계만 가질뿐 데이터베이스 설정상으로 외래키 관계를 강제하지는 않는 상태다.- Main 과 Sub 는 두 엔티티가 모두 정상적..

spring data jpa 를 이용하면 repository 의 save() 메서드를 이용해서 엔티티를 저장한다. 이때 save() 메서드는 저장된 엔티티 객체를 반환하는데, 사실 파라미터로 전달된 엔티티 객체의 상태를 변경하고 그걸 그대로 반환하는거라 파라미터로 전달된 객체와 반환되는 객체가 같다. @Test void 동일한_객체를_반환한다() { var person = new Person("lichking"); var savedPerson = personRepository.save(person); assertThat(person).isEqualTo(savedPerson); } 이런 이유로 따로 equals 를 오버라이딩하지 않은 상태에서 Person 객체를 비교하면 테스트가 통과한다. spring d..
JPA 를 이용하면 엔티티의 상태를 변경해주는 것만으로 update 쿼리를 실행시키게 된다. 이때 발생하는 쿼리는 모든 컬럼을 대상으로 update 를 실행한다. @Entity @Table(name = "person") public class Person { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) @Column(name = "person_id") private Long id; @Column(name = "person_name") private String name; @Column(name = "person_age") private int age; // 생성자 생략 public void setAge(int age) { this.age = age;..
JPA 에서 엔티티간에 연관관계를 맺을시 연관관계의 주인이 되는 엔티티에는 @JoinColumn 애노테이션을 이용해 FK 를 설정한다. @JoinColumn 에는 여러 프로퍼티들이 있는데 이중 name 에는 해당 엔티티의 컬럼명을, referencedColumnName 에는 상대방 엔티티의 컬럼명을 적는다. referencedColumnName 을 명시적으로 넣어주지 않으면 디폴트 옵션으로 상대방의 primary key 에 해당하는 컬럼을 이용하게된다. @Entity @Table(name = "person") @AllArgsConstructor @NoArgsConstructor(access = AccessLevel.PROTECTED) public class Person { @Id @GeneratedVal..

JPA 유튜브 중에 아래와같은 동영상이 있어 이 문제를 해결해보고자한다. https://www.youtube.com/watch?v=brE0tYOV9jQ&t=156s 먼저 방송에서도 언급하지만 코드베이스는 매우작다. BOOK 엔티티와 BOOK_STORE 엔티티 두개만 존재하고 이 둘은 BOOK(N) : BOOK_STORE(1) 관계이다. @Entity @Getter @Setter public class Book { @Id @GeneratedValue @Column(name = "BOOK_ID") private Long id; @Column(name = "ISBN") private String isbn; @Column(name = "TITLE") private String title; @ManyToOne p..
JPQL 작성 후 파라미터를 매핑하는 방법은 인덱스에 기반한 방법과 이름에 기반한 방법이 있다. 1. 인덱스 매핑@Query("SELECT e FROM Expense e WHERE e.id = ?1") List findById(Long id); spring-data-jpa 를 사용시 id를 이용해 조회하는 쿼리를 자동 생성해주므로 저런식으로 JPQL을 만들필요는 없지만 예제코드임을 기억하자. 이런식으로 인덱스를 사용할 수 있으며 인덱스는 1부터 시작한다. 2번째 파라미터의 경우 ?2 로 매핑해주면 된다. 2. 이름 매핑@Query("SELECT e FROM Expense e WHERE e.id = :#{#id}") List findById(@Param("id") Long id); 이름 기반 매핑의 경우 ..
- Total
- Today
- Yesterday
- OOP
- generics
- Git
- toby
- javascript
- code
- backend개발환경
- java
- MySQL
- servlet
- mariadb
- JavaScript Core
- go-core
- JPA
- EffectiveJava
- Design Pattern
- spring cloud
- Jackson
- frontend개발환경
- frontcode
- clean code
- Kotlin
- TEST
- programming
- java8
- http
- db
- DesignPattern
- Spring
- 정규표현식
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | 6 | 7 |
8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 | 16 | 17 | 18 | 19 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 27 | 28 |
29 | 30 |