[Spring Boot] JPA 즉시 로딩과 지연 로딩(FetchType.EAGER or LAZY)

[Spring Boot] JPA 즉시 로딩과 지연 로딩(FetchType.EAGER or LAZY)

블로그 프로젝트 진행 중 FetchType.LAZY와 EAGER이란 것이 나왔다.

하나의 게시물을 눌렀을 때, 화면에 필수적으로 나타나야 하는 것은

  • 작성자
  • 제목
  • 내용

위 3가지가 있었고 있었고, 댓글은 바로 보여지는 경우와 접혀있다가 눌렀을 때 보이는 경우로 나눌 수 있었다.


JPA의 기본 패치 전략

- @ManyToOne, @OneToOne: 즉시로딩(FetchType.EAGER)

- @OneToMany, @ManyToMany : 지연로딩(FetchType.LAZY)

JPA의 기본 패치 전략으로 인해 ManyToOne은 EAGER, OneToMany는 LAZY로 되어있다.

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
public class Board {

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY) // auto_increment
private int id;

@Column(nullable = false, length = 100)
private String title;

@Lob // 대용량 데이터
private String content; // 섬머노트 라이브러리 <html>태그가 섞여서 디자인이 됨.

@ColumnDefault("0")
private int count; // 조회수

@ManyToOne(fetch = FetchType.EAGER) // Many = Board, One = User ==> 한명의 유저는 여러개의 보드를 쓸 수 있다.
@JoinColumn(name = "userId")
private User user; // DB는 object를 저장할 수 없어서 Foreign key를 사용하지만, 자바는 오브젝트를 저장할 수 있다.

@OneToMany(mappedBy = "board", fetch = FetchType.LAZY) // 하나의 게시물은 여러개의 답변을 가질 수 있다.
// mappedBy 연관관계의 주인이 아니다. (FK가 아니다) DB에 컬럼 생성X
private List<Reply> reply;

@CreationTimestamp
private Timestamp createDate;
}


1. 댓글이 바로 보이는 경우

즉시로딩 fetch = FetchType.EAGER을 사용하면 된다.

2. 댓글을 접어놓았을 경우

지연로딩 fetch = FetchType.LAZY를 사용하면 된다.

나는 댓글을 바로 Load할 것이기 때문에 답변 부분의 OneToMany JPA의 기본패치 전략 LAZY즉시로딩 EAGER로 바꿔줄 것이다.

1
2
3
@OneToMany(mappedBy = "board", fetch = FetchType.EAGER) // 하나의 게시물은 여러개의 답변을 가질 수 있다.
// mappedBy 연관관계의 주인이 아니다. (FK가 아니다) DB에 컬럼 생성X
private List<Reply> reply;
[Spring Boot] IntelliJ에서 Live Reload 설정하기

[Spring Boot] IntelliJ에서 Live Reload 설정하기

Live Reload

  • Live Reload라는 기능은 Spring Boot로 개발하면서 자바 소스를 수정하고 저장하면 자동으로 재시작을 해주는 기능이다.

1. spring-boot-devtools 의존성 추가하기

1
developmentOnly 'org.springframework.boot:spring-boot-devtools'

2. application.yml에 추가하기

1
2
3
4
5
6
7
8
9
spring:
devtools:
livereload: # view단이 바뀌었을 때 자동으로 리로드 설정
enabled: true
restart: # 컨트롤러,모델단(classpath에 있는 파일)이 바뀌었을 때 프로젝트 재시작 설정
enabled: false

freemarker:
cache: false

3. Intelli J 설정 수정하기

Settings > Build, Execution, Deployment > Compiler >Build project automatically 활성화

4. registry 수정하기

Find Action (Ctrl + Shift + A) –> “registry” 검색 –> compiler.automake.allow.when.app.running Value 체크

[Spring Boot] 블로그 프로젝트 기본 세팅하기

[Spring Boot] 블로그 프로젝트 기본 세팅하기

기본 셋팅

프로그램

Windows 10
-----------------
IntelliJ : 코드작성

Docker - MySQL

MySQL Workbench

Postman

의존성 추가

springboot devtools

lombok

spring data JPA

mysql driver

spring security

spring web

​ OAuth2 client는 직접구현해보기

1
2
3
4
5
6
7
8
9
10
11
12
13
14
implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
implementation 'org.springframework.boot:spring-boot-starter-security'
implementation 'org.springframework.boot:spring-boot-starter-web'
compileOnly 'org.projectlombok:lombok'
developmentOnly 'org.springframework.boot:spring-boot-devtools'
runtimeOnly 'mysql:mysql-connector-java'
annotationProcessor 'org.projectlombok:lombok'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
testImplementation 'org.springframework.security:spring-security-test'

/** 추가 라이브러리 **/
implementation "org.springframework.security:spring-security-taglibs" // 시큐리티 태그 라이브러리
implementation "org.apache.tomcat.embed:tomcat-embed-jasper" // JSP 템플릿 엔진
implementation 'javax.servlet:jstl' // JSTL
[Spring Boot] IntelliJ 학생인증, Ultimate 무료설치하기

[Spring Boot] IntelliJ 학생인증, Ultimate 무료설치하기

인텔리제이 학생인증

IntelliJ IDEA는 두가지 버전이 있습니다.

무료버전인 Community와 유료버전인 Ultimate.

저는 학생이기 때문에 학생인증을 받아 Ultimate 버전을 사용해보도록 하겠습니다.


1. JetBrains의 학생인증 사이트 접속하기

접속링크

Apply now 버튼을 클릭합니다.


2. 정보 입력 및 회원 가입

인증을 위해 아래 사진과 같은 폼에 정보를 입력합니다.

제출 후에는 아래 사진과 같은 이메일을 받을 수 있습니다.

링크를 클릭 후 진행 및 회원 가입하면


[Spring Boot] IntelliJ로 Spring Boot 시작하기

[Spring Boot] IntelliJ로 Spring Boot 시작하기

인텔리제이 설치하기

설치페이지에서 IntelliJ 유료버전인 Ultimate와 무료버전인 Community 두 가지 버전 중 선택하여 설치한다.
유료버전은 학생 인증을 통하여 무료로 사용할 수 있다. 다음글을 참고하자


인텔리제이에서 프로젝트 생성하기

New Project 버튼을 클릭한다.

프로젝트 유형은 Gradle을 선택한다.
이름과 디렉토리 위치를 지정하고 GroupId와 ArtifactId를 설정한다. ArtifactId는 프로젝트 이름이 된다.

Spring Boot 버전을 선택한다.
초기에 프로젝트를 생성한 후 셋팅하고 싶은 의존성(Dependencies)을 선택한다.

Spring Boot DevTools, Spring Web, Mustache

Finish를 선택하면, 아래와 같이 프로젝트가 생성된다.


스프링 부트 프로젝트 설명

plugins에서 io.spring.dependency-management 플러그인은 스프링 부트의 의존성들을 관리해 주는 플러그인이다.

repositories는 각종 의존성 들을 어떤 원격저장소에서 받을지 정한다. 기본적으로 mavenCentral을 많이 사용하지만, 최근에는 라이브러리 업로드 난이도 때문에 jcenter도 많이 사용한다.

  • mavenCentral은 이전부터 많이 사용하는 저장소지만, 본인이 만든 라이브러리를 업로드하기 위해서 많은 과정과 설정이 필요하기 때문에 개발자들이 직접 만든 라이브러리의 공유가 점점 안 되는 상황이 발생했다.
  • 최근에 나온 jcenter는 이런 문제점을 개선하여 라이브러리 업로드를 간단하게 하였다. 또한, 여기서 한 걸음 더 나아가 jcenter에 라이브러리를 업로드하면 mavenCentral에도 업로드될 수 있도록 자동화를 할 수 있다. 그래서 개발자들의 라이브러리가 점점 jcenter로 이동하고 있다.

dependencies는 프로젝트 개발에 필요한 의존성들을 선언하는 곳이다.
아까 설정한 라이브러리가 선언되어있다.


스프링 부트 프로젝트 시작하기

프로젝트 폴더 내 src>main>java>com.***.*** 안에 가장 기본이 되는 .java파일이 있는데 이를 실행한다.

위와 같이 정상적으로 실행되었다면, 웹 브라우저에서 localhost:8080으로 접속한다.


참고

추후 작성 글…인텔리제이 학생인증, vscode로 실행하기, maven/gradle 차이점, live reload사용하기, mustache

[C++] String 클래스

출처

string class

Header :


.assign : 문자열을 할당

( 문자열 ) : 문자열을 할당한다.

( 개수, 문자 ) : 문자를 개수만큼 할당한다

( 문자열, 시작위치, 개수 ) : 매개변수 문자열의 시작위치부터 개수만큼을 호출한 문자열에 할당

1
2
3
4
string s1, s2, s3 ;
s1.assign( "ABCDEFG" ) ; // s1 = "ABCDEFG"
s2.assign( 3, 'a' ) ; // s2 = "aaa"
s3.assign( s, 2, 4 ) ; // s3 = "CDEF" ( 문자열 s의 2부터 4개를 복사하여 할당 )

.append : +연산자의 역할처럼 문자열을 끝에 더한다.

( 문자열 ) : 문자열을 더한다

( 개수, 문자 ) : 문자를 개수만큼 끝에 더한다

( 문자열, 시작위치, 개수 ) :

1
2
3
4
5
string s, s2 ;
s.append( "ABCDEF" ) ; // s = "ABCDEF"
s.append( 3, 'x' ) ; // s = "ABCDEFxxx"
s2.append( s, 2, 4 ) ; // s2 = "CDEF"
s2 += "x" ; // s2 = "CDEFx"

.clear : 문자열의 내용을 모두 삭제

1
s.clear() ;

.compare : 문자열을 비교 ( 사전순으로 비교 )

1
s.compare( s2 ) ;  // s == s2이면 0,  s<s2이면 음수,  s>s2이면 양수를 반환

.empty : 문자열이 비었는지 확인

1
s.empty() ;

.erase : 문자열을 지운다

( 시작위치, 개수 ) : 시작위치부터 개수만큼의 문자를 지운다.

1
2
string s = "ABCDEF" ;
s.erase( 0, 3 ) ; // s = "DEF" ( 인덱스 0부터 3개의 문자를 지운다 )

.find : 특정 문자열을 찾고, 그 시작위치를 반환

( 문자 ) : 인덱스 0부터 해당 문자를 찾고, 시작위치를 반환한다.

( 문자열 ) : 인덱스 0부터 해당 문자열을 찾고, 그 시작위치를 반환한다.

( 문자열, 시작위치 ) : 시작위치부터 문자열을 찾고, 시작위치를 반환한다.

1
2
3
4
5
6
string s1 = "abcd" ;
string s2 = "b" ;
**int** location = s1.find( s2 ) ;
location = s1.find( s2, x ) ;
location = s1.find_first_of( s2, x ) ;
location = s1.find_first_not_of( s2, x ) ; location = s1.find_last_of s1.find_last_not_of

.replace : 문자열을 대체

( 시작위치, 개수, 문자열 ) : 호출한 문자열의 시작위치부터 개수만큼의 문자를 매개변수 문자열로 대체한다.

1
2
   string s = "abc_def" ;
s.replace( 4, 3, "zzz" ) ; // s = "abc_zzz" ( 인덱스 4부터 3개의 문자를 "zzz"로 대체 )

.insert : 문자열을 지정한 위치에 삽입

( 시작위치, 문자열 ) : 시작위치에 문자열을 삽입한다.

string s = “ABCDEF” ; s.insert( 2, “xx” ) ; // s = “ABxxCDEF”

.pop_back : 문자열에서 가장 뒤의 문자 하나를 빼낸다.

.push_back : 문자열의 가장 뒤에 문자 하나를 추가한다.

string s = “ABCDEF” ; s.pop_back() ; // s = “ABCDE” s.push_back( ‘x’ ) ; // s = “ABCDEx”

.resize : 문자열의 크기를 재설정

s

.size, .length : 문자열의 크기를 반환

.max_size : 문자열이 최대로 가질수 있는 길이를 반환한다.

string s = “ABCDEF” ; int size = s.size() ; // size = 6 ( 실제 사용되고 있는 크기 ) int length = s.length() ; // length = 6 ( 문자열의 길이 )

.capacity : 할당된 메모리의 크기를 반환 ( reallocation 없이 사용할 수 있는 문자수를 반환 )

string s = “ABCDEF” ; int capacity = s.capacity() ; // size = 6, capacity = 15

★ capacity가 size보다 클때, 속도는 더 빠르다 !

= capacity가 size보다 크면, 기존 공간에 문자를 추가하면 되지만

그 반대의 경우에는 문자를 추가하기 위해 새로운 메모리를 할당해야 하기 때문이다.

.reserve : reallocation을 피하기 위해, 메모리의 최소용량을 지정

( 크기 ) : 크기만큼의 여유 메모리를 할당한다.

** 이때, 매개변수의 크기는 현재 capacity보다 크지않으면 의미도 효과도 없다.

string s = “ABCDEF” ; // size = 6, capacity = 15 s.reserve( 100 ) ; // size = 6, capacity = 111 s.reserve( 1000 ) ; // size = 6, capacity = 1007

.substr : 문자열의 일부분을 문자열로 반환

( 시작위치 ) : 시작위치부터 끝까지의 문자들을 문자열로 반환

( 시작위치, 개수 ) : 시작위치부터 개수만큼의 문자를 문자열로 반환

string s = “ABCDEF” ; string s2 = s.substr( 4 ) ; // s2 = “EF” ( 인덱스 4부터 끝까지의 문자열을 반환 ) string s3 = s.substr( 1, 3 ) ; // s3 = “BCD” ( 인덱스 1부터 3까지의 문자열을 반환 )

.swap : 문자열을 서로 바꾼다

string a = “ABCD” ; string b = “WXYZ” ; a.swap( b ) ; // a = “WXYZ”, b = “ABCD” b.swap( a ) ; // a = “ABCD”, b = “WXYZ”

.at : 문자열에서 특정위치의 문자를 액세스

string s = “ABCDEF” ; char c = s.at(3) ; // c = ‘D’

.c_str : string 문자열을 char* 형으로 바꾸어 반환한다.

string s = “ABCDEF” ; int length = strlen( s.c_str() ) ;

.date

.copy

.back

.front

.begin

.end