JPA

JinHyeong bak
12 min readDec 5, 2020

h2 설치 및 실행

패러다임 불일치?

brew install h2

start:

To have launchd start h2 now and restart at login:
brew services start h2
Or, if you don't want/need a background service you can just run:
h2

localhost:8082 접근

memory h2 접근하기

접근 url: http://localhost:8080/h2

datasource url: jdbc:h2:mem:testdb

h2 예약어(order) 충돌문제

error: expected "identifier"

Caused by: org.h2.jdbc.JdbcSQLSyntaxErrorException: Syntax error in SQL statement "CREATE TABLE DEVELOP_REVIEW_MEMBER (MEMBER_ID BIGINT NOT NULL, NAME VARCHAR(255) NOT NULL, ORDER[*] INTEGER NOT NULL, USER_ID VARCHAR(255) NOT NULL, PRIMARY KEY (MEMBER_ID)) "; expected "identifier"; SQL statement:
create table develop_review_member (member_id bigint not null, name varchar(255) not null, order integer not null, user_id varchar(255) not null, primary key (member_id)) [42001-199]

원인: ORDER is a reserved keyword for H2DB

해결:

  1. order 이름변경 e.g.) order_no
  2. globally_quoted_identifiers: true 설정
properties:
hibernate.globally_quoted_identifiers: true

(JPA — 1) JPA사용을 위한 환경 설정 | KihoonKim:Dev
하이버네이트 데이터베이스 스키마 자동 생성 시 키워드/예약어 충돌 문제 해결하기 | Popit
Spring에서 JPA / Hibernate 초기화 전략
인텔리제이 JPA Console

JdbcSQLIntegrityConstraintViolationException: NULL not allowed for column “member_id”; SQL statement:

insert into "develop_review_member" ("name", "order", "user_id") values  
('철수', 1, 'a'),
('짱구', 2, 'b'),
('민구', 3, 'c');

member_id auto_increment 인데. 왜 안됨...∑(;°Д°)

log 보면 sequence 를 생성하네. h2는 sequence 전략을 사용하나 보구나. 그런데 왜 1개만 생성하지? 따로 어노테이션으로 설정해줘야 하나?

Hibernate: create sequence "hibernate_sequence" start with 1 increment by 1insert into "develop_review_member" ("member_id","name", "order", "user_id") values  
(NEXTVAL('hibernate_sequence'), '철수', 1, 'a'),
(NEXTVAL('hibernate_sequence'), '짱구', 2, 'b'),
(NEXTVAL('hibernate_sequence'), '민구', 3, 'c');

related 스프링 부트 2.0 JPA Auto-configuration의 변화 | Popit

memory database script 초기화

단위 테스트에서 사용할 용도

data-h2.sql 는 안되넹.

Initialize a Database using basic SQL scripts

data-h2.sql 사용하려면 spring.datasource.platform=h2 설정을 해야함.

first or top

Limiting Query Results with JPA and Spring Data JPA | Baeldung

Failed to determine a suitable driver class

Description:

Failed to configure a DataSource: ‘url’ attribute is not specified and no embedded datasource could be configured.

Reason: Failed to determine a suitable driver class

Action:

Consider the following: If you want an embedded database (H2, HSQL or Derby), please put it on the classpath. If you have database settings to be loaded from a particular profile you may need to activate it (no profiles are currently active).

2020-07-20 00:31:30.811  WARN 13060 --- [  restartedMain] ConfigServletWebServerApplicationContext : Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'inMemoryDatabaseShutdownExecutor' defined in class path resource [org/springframework/boot/devtools/autoconfigure/DevToolsDataSourceAutoConfiguration.class]: Unsatisfied dependency expressed through method 'inMemoryDatabaseShutdownExecutor' parameter 0; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'dataSource' defined in class path resource [org/springframework/boot/autoconfigure/jdbc/DataSourceConfiguration$Hikari.class]: Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [com.zaxxer.hikari.HikariDataSource]: Factory method 'dataSource' threw exception; nested exception is org.springframework.boot.autoconfigure.jdbc.DataSourceProperties$DataSourceBeanCreationException: Failed to determine a suitable driver class

문제: hikari 로 하면 안되나?? 나중에 확인해보자.

datasource:
hikari:
jdbc-url: jdbc:mysql://xxxx:3306/xxx
username: test
password: "test"
driver-class-name: com.mysql.jdbc.Driver

해결:

datasource:
url: jdbc:mysql://xxxx:3306/xxx
username: test
password: "test"
driver-class-name: com.mysql.jdbc.Driver

Spring Boot & HikariCP Datasource 연동하기

MySQL 인데 hibernate_sequence 왜 생성되는거여? auto_increment 기대했는데

@GeneratedValue(strategy = GenerationType.IDENTITY) 로 변경함. h2 도 auto_increment 를 지원하는구나. ヽ( ・∀・)ノ

Spring Boot Data JPA 2.0 에서 id Auto_increment 문제 해결

could not initialize proxy — no Session

해결:

@ToString <--- 제거하면 해결된다. 왜?
@Getter
@Setter
@Entity
@Table(name = "develop_review_member")
public class Member {

무한 루프 문제 같지는 않고…영속석 콘텍스트 문제인거 같은뎅. [JPA Lazy Evaluation] LazyInitializationException: could not initialize proxy — no Session

양방향 매핑 시에는 무한 루프에 빠지지 않게 조심해야 한다. (Lombok 라이브러리를 사용할 때도 자주 발생한다) 예) Member.toString() -> getTeam() -> Team.toString() -> getMember() … 이런 문제는 엔티티를 JSON으로 변환할 때 자주 발생하는데 JSON 라이브러리들은 보통 무한루프에 빠지지 않도록 하는 어노테이션이나 기능을 제공한다.

JPA 프로그래밍 195 페이지

error log:

org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: com.review.Member.reviewHistories, could not initialize proxy - no Session	at org.hibernate.collection.internal.AbstractPersistentCollection.throwLazyInitializationException(AbstractPersistentCollection.java:597)
at org.hibernate.collection.internal.AbstractPersistentCollection.withTemporarySessionIfNeeded(AbstractPersistentCollection.java:216)
at org.hibernate.collection.internal.AbstractPersistentCollection.initialize(AbstractPersistentCollection.java:576)
at org.hibernate.collection.internal.AbstractPersistentCollection.read(AbstractPersistentCollection.java:147)
at org.hibernate.collection.internal.PersistentBag.toString(PersistentBag.java:537)
at java.lang.String.valueOf(String.java:2994)
at java.lang.StringBuilder.append(StringBuilder.java:131)
at com.review.Member.toString(Member.java:11)

engine=MyISAM 생성됨?!

해결: database-platform: org.hibernate.dialect.MySQL55Dialect

Specified key was too long max key length is 1000 bytesHibernate: create table `develop_review_member` (`member_id` bigint not null auto_increment, `name` varchar(255) not null, `order` integer not null, `user_id` varchar(255) not null, primary key (`member_id`)) engine=MyISAM

UK, FK 이름 정하기

UK

@Table(name = "develop_review_member",
uniqueConstraints = {
@UniqueConstraint(columnNames = {"user_id"}, name = "uk_user_id"),
@UniqueConstraint(columnNames = {"order"}, name = "uk_order")
})

FK

@JoinColumn(name = "member_id", foreignKey = @ForeignKey(name = "fk_member_id"))

QueryByExampleExecutor??

[스프링 데이터 JPA] 4–10. 스프링 데이터 JPA: Query by Example

JPA related

GitHub — spring-guides/gs-accessing-data-jpa: Accessing Data with JPA :: Learn how to work with JPA data persistence using Spring Data JPA.
Java 8 Date(Time) 와 JPA 그리고 스프링 부트 | Popit
[ERD] 데이터 베이스의 관계 유형을 알아보고 구현하기 (일대일, 일대다, 다대다) :: 심플한 코딩 백과사전

@DataJpaTest

--

--