day34 πŸŒ•

μž₯λ―ΈΒ·2022λ…„ 7μ›” 17일
0

였늘의 μ„±κ³Ό

λͺ©λ‘ 보기
34/129

μŠ€ν”„λ§ MVC 1편 - λ°±μ—”λ“œ μ›Ήκ°œλ°œ ν•΅μ‹¬κΈ°μˆ  μ„Ήμ…˜ 3 μˆ˜κ°•

μ„Ήμ…˜ 3. μ„œλΈ”λ¦Ώ, JSP, MVC νŒ¨ν„΄ μˆ˜κ°• μ™„λ£Œ!!

이번 κ°•μ˜λŠ” μ‹€μŠ΅ μœ„μ£Όλ‘œ μ§„ν–‰ν•΄μ„œ λ”±νžˆ 정리할 게 λ§Žμ§€ μ•Šλ‹€... λ‹€ μ½”λ“œλΌ...

μ•„λ¬΄νŠΌ μ²˜μŒμ—” μ„œλΈ”λ¦ΏμœΌλ‘œ νšŒμ› 관리 μ›Ή μ• ν”Œλ¦¬μΌ€μ΄μ…˜μ„ λ§Œλ“€μ—ˆλ‹€.
그런데 μ„œλΈ”λ¦Ώκ³Ό μžλ°” μ½”λ“œλ§ŒμœΌλ‘œ HTML을 λ§Œλ“€μ—ˆλ”λ‹ˆ λ„ˆλ¬΄ 번거둭고 λΉ„νš¨μœ¨μ μ΄μ—ˆλ‹€. 차라리 HTML λ¬Έμ„œμ— λ™μ μœΌλ‘œ λ³€κ²½ν•΄μ•Ό ν•˜λŠ” λΆ€λΆ„λ§Œ μžλ°” μ½”λ“œλ₯Ό λ„£λŠ” 것이 더 νŽΈλ¦¬ν•  것이닀.

➑️ ν…œν”Œλ¦Ώ 엔진(JSP, Thymeleaf λ“±)을 μ‚¬μš©ν•˜λ©΄ HTML λ¬Έμ„œμ—μ„œ ν•„μš”ν•œ 곳만 μ½”λ“œλ₯Ό μ μš©ν•΄ λ™μ μœΌλ‘œ λ³€κ²½ν•  수 μžˆλ‹€.


JSPλŠ” μžλ°” μ½”λ“œλ₯Ό κ·ΈλŒ€λ‘œ λ‹€ μ‚¬μš©ν•  수 μžˆλ‹€.

<%@ page import="hello.servlet.domain.member.MemberRepository" %>
➑️ μžλ°”μ˜ importλ¬Έκ³Ό κ°™λ‹€.

<% ~~ %>
➑️ μžλ°” μ½”λ“œλ₯Ό μž…λ ₯ν•  수 μžˆλ‹€.

<%= ~~ %>
➑️ μžλ°” μ½”λ“œλ₯Ό 좜λ ₯ν•  수 μžˆλ‹€.

JSPλ₯Ό μ‚¬μš©ν•œ 덕뢄에 λ™μ μœΌλ‘œ 변경이 ν•„μš”ν•œ λΆ€λΆ„μ—λ§Œ μžλ°” μ½”λ“œλ₯Ό μ μš©ν•  수 μžˆμ—ˆλ‹€. ν•˜μ§€λ§Œ 이 경우 JSPκ°€ λ„ˆλ¬΄ λ§Žμ€ 역할을 ν•œλ‹€. κ·Έλž˜μ„œ 이λ₯Ό ν•΄κ²°ν•˜κΈ° μœ„ν•΄ MVC νŒ¨ν„΄μ΄ λ“±μž₯ν–ˆλ‹€.


ν•˜λ‚˜μ˜ μ„œλΈ”λ¦Ώμ΄λ‚˜ JSP만으둜 λΉ„μ¦ˆλ‹ˆμŠ€ 둜직과 λ·° λ Œλ”λ§κΉŒμ§€ λͺ¨λ‘ μ²˜λ¦¬ν•˜κ²Œ 되면 λ„ˆλ¬΄ λ§Žμ€ 역할을 ν•˜κ²Œ 되고 μœ μ§€λ³΄μˆ˜κ°€ μ–΄λ €μ›Œμ§„λ‹€.
JSP 같은 λ·° ν…œν”Œλ¦Ώμ€ 화면을 λ Œλ”λ§ ν•˜λŠ” 데 μ΅œμ ν™”λ˜μ–΄ 있기 λ•Œλ¬Έμ— 이 λΆ€λΆ„μ˜ μ—…λ¬΄λ§Œ λ‹΄λ‹Ήν•˜λŠ” 것이 κ°€μž₯ νš¨κ³Όμ μ΄λ‹€.


Model View Controller

MVC νŒ¨ν„΄μ€ ν•˜λ‚˜μ˜ μ„œλΈ”λ¦Ώμ΄λ‚˜ JSP둜 μ²˜λ¦¬ν•˜λ˜ 것을 Controller와 ViewλΌλŠ” μ˜μ—­μœΌλ‘œ μ„œλ‘œ 역할을 λ‚˜λˆˆ 것을 λ§ν•œλ‹€.

  • Controller: HTTP μš”μ²­μ„ λ°›μ•„ νŒŒλΌλ―Έν„°λ₯Ό κ²€μ¦ν•˜κ³  λΉ„μ¦ˆλ‹ˆμŠ€ λ‘œμ§μ„ μˆ˜ν–‰ν•œλ‹€. 뷰에 전달할 κ²°κ³Ό 데이터λ₯Ό μ‘°νšŒν•˜μ—¬ λͺ¨λΈμ— λ‹΄λŠ”λ‹€.

  • Model: 뷰에 좜λ ₯ν•  데이터λ₯Ό λ‹΄μ•„λ‘”λ‹€.

  • View: λͺ¨λΈμ— λ‹΄κ²¨μžˆλŠ” 데이터λ₯Ό μ‚¬μš©ν•΄μ„œ 화면을 κ·Έλ¦¬λŠ” 일에 μ§‘μ€‘ν•œλ‹€.

Model은 HttpServletRequest 객체λ₯Ό μ‚¬μš©ν•œλ‹€.
requestλŠ” 내뢀에 데이터 μ €μž₯μ†Œλ₯Ό 가지고 μžˆλŠ”λ°, request.setAttribute(), request.getAttribute()λ₯Ό μ‚¬μš©ν•˜λ©΄ 데이터λ₯Ό λ³΄κ΄€ν•˜κ³  μ‘°νšŒν•  수 μžˆλ‹€.

/WEB-INF
➑️ 이 경둜 μ•ˆμ— JSPκ°€ 있으면 μ™ΈλΆ€μ—μ„œ 직접 JSPλ₯Ό ν˜ΈμΆœν•  수 μ—†λ‹€. 컨트둀러λ₯Ό ν†΅ν•΄μ„œ JSPλ₯Ό ν˜ΈμΆœν•΄μ•Ό ν•œλ‹€.


MVC νŒ¨ν„΄μ„ μ μš©ν•œ 덕뢄에 컨트둀러의 μ—­ν• κ³Ό λ·°λ₯Ό λ Œλ”λ§ ν•˜λŠ” 역할을 λͺ…ν™•ν•˜κ²Œ ꡬ뢄할 수 μžˆμ—ˆλ‹€.
ν•˜μ§€λ§Œ μ»¨νŠΈλ‘€λŸ¬λŠ” 쀑볡이 많고 ν•„μš”ν•˜μ§€ μ•Šμ€ μ½”λ“œλ“€λ„ 많이 μžˆμ—ˆλ‹€. λ˜ν•œ, κΈ°λŠ₯이 λ³΅μž‘ν•΄μ§ˆμˆ˜λ‘ μ»¨νŠΈλ‘€λŸ¬μ—μ„œ κ³΅ν†΅μœΌλ‘œ μ²˜λ¦¬ν•΄μ•Ό ν•˜λŠ” 뢀뢄이 점점 더 λ§Žμ•„μ§ˆ 것이닀.
이 문제λ₯Ό ν•΄κ²°ν•˜λ €λ©΄ 컨트둀러 호좜 전에 λ¨Όμ € 곡톡 κΈ°λŠ₯을 μ²˜λ¦¬ν•΄μ•Ό ν•œλ‹€.

➑️ Front Controller νŒ¨ν„΄μ„ λ„μž…ν•˜λ©΄ 이런 문제λ₯Ό κΉ”λ”ν•˜κ²Œ ν•΄κ²°ν•  수 μžˆλ‹€.


ν† ν”½

+)22. 07. 18. μΆ”κ°€ μ™„λ£Œ!

1. JPA Entity Manager

μ—”ν‹°ν‹° λ§€λ‹ˆμ €(Entity Manager)λŠ” 컀밋 μ‹œμ μ— μ˜μ†μ„± μ»¨ν…μŠ€νŠΈ(Persistence Context)μ—μ„œ κ΄€λ¦¬ν•˜κ³  있던 μ˜μ† 객체의 λ³€κ²½ 내역을 μΆ”μ ν•˜μ—¬ λ°μ΄ν„°λ² μ΄μŠ€μ— λ°˜μ˜ν•˜λŠ” 역할을 ν•œλ‹€.


μ˜μ†μ„± μ»¨ν…μŠ€νŠΈ(Persistence Context)

그럼 μ˜μ†μ„± μ»¨ν…μŠ€νŠΈλž€ λ¬΄μ—‡μΌκΉŒ?
μ˜μ†μ„± μ»¨ν…μŠ€νŠΈλž€ μΌμ’…μ˜ λ©”λͺ¨λ¦¬ μ €μž₯μ†Œλ‘œ, μ—”ν‹°ν‹° νƒ€μž…κ³Ό μ‹λ³„μžλ₯Ό ν‚€λ‘œ μ‚¬μš©ν•˜λŠ” 객체의 집합을 μ˜λ―Έν•œλ‹€.
μ΄λ ‡κ²Œ μ„€λͺ…ν•˜λ©΄ μ’€ μ–΄λ ΅μ§€λ§Œ, β€˜μ—”ν‹°ν‹°λ₯Ό 영ꡬ μ €μž₯ν•˜λŠ” ν™˜κ²½β€˜μ΄λΌκ³  μƒκ°ν•˜λ©΄ 쉽닀.

EntityManager.persist(entity);
β¬†οΈΒ μ΄λ ‡κ²Œ μ—”ν‹°ν‹° λ§€λ‹ˆμ €λ₯Ό 톡해 μ˜μ†μ„± μ»¨ν…μŠ€νŠΈμ— μ ‘κ·Όν•œλ‹€.

그런데, μ΄λ ‡κ²Œ μ˜μ†μ„± μ»¨ν…μŠ€νŠΈλ₯Ό μ‚¬μš©ν•  ν•„μš” 없이 κ·Έλƒ₯ λ°”λ‘œ DB에 데이터λ₯Ό λ„£μœΌλ©΄ μ•ˆ 될까? μ™œ ꡳ이 μ˜μ†μ„± μ»¨ν…μŠ€νŠΈλ₯Ό μ“°λŠ” 걸까?
μ˜μ†μ„± μ»¨ν…μŠ€νŠΈλ₯Ό μ“°λŠ” μ΄μœ λŠ” λ‹€μŒκ³Ό 같은 이점이 있기 λ•Œλ¬Έμ΄λ‹€.

1μ°¨ μΊμ‹œ

Member member = new Member();
member.setId("member1");
member.setUsername("νšŒμ›1");
    
//1μ°¨ μΊμ‹œμ— μ €μž₯됨
em.persist(member);
    
//1μ°¨ μΊμ‹œμ—μ„œ 쑰회
Member findeMember = em.find(Member.class, "member1");

em.find둜 member1을 μ‘°νšŒν•˜λ©΄ DB에 κ°€μ„œ μ°ΎλŠ” 것이 μ•„λ‹ˆλΌ 1μ°¨ μΊμ‹œλΆ€ν„° κ°€μ„œ μ°ΎλŠ”λ‹€.

1μ°¨ μΊμ‹œλŠ” νŠΈλžœμž­μ…˜μ΄ μ‹œμž‘ν•˜κ³  μ’…λ£Œλ  λ•ŒκΉŒμ§€λ§Œ μœ μ§€λ˜λŠ” μΊμ‹œλ‹€.

λ§Œμ•½ member2λ₯Ό μ°ΎλŠ”λ‹€λ©΄ 1μ°¨ μΊμ‹œμ— μ—†λŠ” κ±Έ ν™•μΈν•˜κ³  DBμ—μ„œ μ‘°νšŒν•œλ‹€. 그리고 1μ°¨ μΊμ‹œμ— μ €μž₯ν•œ λ’€ λ°˜ν™˜ν•œλ‹€.


동일성(identity) 보μž₯

Member a = em.find(Member.class, "member1");
Member b = em.find(Member.class, "member1");
    
System.out.println(a == b); //동일성 비ꡐ true

νŠΈλž™μž­μ…˜μ„ μ§€μ›ν•˜λŠ” μ“°κΈ° 지연(transactional write-behind)

EntityManager em = emf.createEntityManager();
EntityTransaction transaction = em.getTransaction();
    
//μ—”ν‹°ν‹° λ§€λ‹ˆμ €λŠ” 데이터 λ³€κ²½ μ‹œ νŠΈλžœμž­μ…˜μ„ μ‹œμž‘ν•΄μ•Ό ν•œλ‹€.
transaction.begin(); //[νŠΈλžœμž­μ…˜] μ‹œμž‘
    
em.persist(memberA);
em.persist(memberB);
//μ—¬κΈ°κΉŒμ§€ INSERT SQL을 DB에 보내지 μ•ŠλŠ”λ‹€.
    
//μ»€λ°‹ν•˜λŠ” μˆœκ°„ DB에 INSERT SQL을 보낸닀.
transaction.commit(); //[νŠΈλžœμž­μ…˜] 컀밋

em.persist ν•˜λŠ” μˆœκ°„ INSERT SQL을 μƒμ„±ν•˜κ³  μ“°κΈ° 지연 SQL μ €μž₯μ†Œμ— 쿼리λ₯Ό λ„£μ–΄λ†“λŠ”λ‹€. (DB에 μ•ˆ λ„£κ³  κΈ°λ‹€λ¦°λ‹€.)
μ΄λ ‡κ²Œ μ“°κΈ° 지연 SQL μ €μž₯μ†Œμ— μžˆλŠ” 쿼리λ₯Ό DB에 λ³΄λ‚΄λŠ” 과정을 ν”ŒλŸ¬μ‹œ(flush)라 ν•œλ‹€.

  • ν”ŒλŸ¬μ‹œκ°€ λ°œμƒν•  λ•Œ μ‹€ν–‰λ˜λŠ” 것
    • λ³€κ²½ 감지
    • μˆ˜μ •λœ μ—”ν‹°ν‹° μ“°κΈ° 지연 SQL μ €μž₯μ†Œμ— 등둝
    • μ“°κΈ° 지연 SQL μ €μž₯μ†Œμ˜ 쿼리λ₯Ό DB에 전솑(등둝, μˆ˜μ •, μ‚­μ œ 쿼리)
  • μ˜μ†μ„± μ»¨ν…μŠ€νŠΈλ₯Ό ν”ŒλŸ¬μ‹œν•˜λŠ” 방법
    • em.flush() - 직접 호좜
    • νŠΈλžœμž­μ…˜ 컀밋 - ν”ŒλŸ¬μ‹œ μžλ™ 호좜
    • JPQL 쿼리 μ‹€ν–‰ - ν”ŒλŸ¬μ‹œ μžλ™ 호좜

λ³€κ²½ 감지(Dirty Checking)
데이터 λ³€κ²½ μ‹œ 엔티티와 μŠ€λƒ…μƒ·μ„ 비ꡐ해 바뀐 뢀뢄이 μžˆλ‚˜ 찾아보고 μžλ™μœΌλ‘œ UPDATE 쿼리문을 μ‹€ν–‰ν•œλ‹€.
더 μžμ„Έν•œ λ‚΄μš©μ€ μ•„λž˜μ— μ •λ¦¬ν•΄λ†“μ•˜λ‹€.

지연 λ‘œλ”©(Lazy Loading)

@Entity
public class Member {
    
	@Id
	@GeneratedValue
	private Long id;
    
	@Column(name = "USERNAME")
	private String name;
    
	@ManyToOne(fetch = FetchType.LAZY)
	@JoinColumn(name = "TEAM_ID")
	private Team team;
	...
}

λ‹¨μˆœνžˆ member μ •λ³΄λ§Œ μ‚¬μš©ν•˜λŠ” λΉ„μ¦ˆλ‹ˆμŠ€ 둜직 println(member.getName()); 을 μ‹€ν–‰ν•  땐 TeamκΉŒμ§€ μ‘°νšŒν•  ν•„μš” 없이 Member만 쑰회(em.find)ν•˜λ©΄ 될 것이닀.

Member member = em.find(Member.class, 1L);

이 λ•Œ LAZYλ₯Ό μ‚¬μš©ν•  경우 Team에 ν”„λ‘μ‹œ κ°μ²΄λΌλŠ” κ°€μ§œ 객체가 λ“€μ–΄κ°€κ²Œ λœλ‹€.

Team team = member.getTeam();
team.getName(); //μ‹€μ œ team을 μ‚¬μš©ν•˜λŠ” μ‹œμ μ— μ΄ˆκΈ°ν™”ν•œλ‹€. (DB 쑰회)

λ§Œμ•½ 지연 λ‘œλ”©μ΄ μ•„λ‹Œ μ¦‰μ‹œ λ‘œλ”©μ„ μ‚¬μš©ν•  경우 μ˜ˆμƒμΉ˜ λͺ»ν•œ SQL이 λ°œμƒν•  수 있으며, JPQLμ—μ„œ N+1 문제λ₯Ό μΌμœΌν‚¨λ‹€.


μ—”ν‹°ν‹° λ§€λ‹ˆμ €(Entity Manager)

μ—”ν‹°ν‹° λ§€λ‹ˆμ €λ₯Ό 생성할 λ•Œ ν•˜λ‚˜μ˜ μ˜μ†μ„± μ»¨ν…μŠ€νŠΈκ°€ μƒμ„±λœλ‹€.
λ§Œμ•½ λ™μΌν•œ μ‹λ³„μžλ₯Ό κ°–λŠ” μ—”ν‹°ν‹°λ₯Ό 2번 μ‘°νšŒν•œλ‹€λ©΄ μ—”ν‹°ν‹° λ§€λ‹ˆμ €μ— μ˜ν•΄ 첫 λ²ˆμ§ΈλŠ” 쿼리가 μ‹€ν–‰λ˜κ³ , 두 λ²ˆμ§ΈλŠ” 쿼리가 μ‹€ν–‰λ˜μ§€ μ•Šκ³  μ˜μ†μ„± μ»¨ν…μŠ€νŠΈμ—μ„œ 값을 κ°€μ Έμ˜¨λ‹€.

μ—”ν‹°ν‹° λ§€λ‹ˆμ €λŠ” DB에 μ•‘μ„ΈμŠ€ ν•˜κΈ° μœ„ν•΄ μ‚¬μš©λ˜λŠ” κ°μ²΄μ΄λ―€λ‘œ 이λ₯Ό 톡해 데이터λ₯Ό 쑰회, 등둝, μˆ˜μ •, μ‚­μ œν•˜λŠ” μž‘μ—…μ„ μˆ˜ν–‰ν•œλ‹€.


μ—”ν‹°ν‹° λ§€λ‹ˆμ € μ’…λ₯˜

  1. μ• ν”Œλ¦¬μΌ€μ΄μ…˜μ—μ„œ κ΄€λ¦¬ν•˜λŠ” μ—”ν‹°ν‹° λ§€λ‹ˆμ €

    • μ• ν”Œλ¦¬μΌ€μ΄μ…˜μ„ μ‹œμž‘ν•˜λ©΄μ„œ EntityManagerFactoryλ₯Ό μ΄ˆκΈ°ν™”ν•˜κ³ , ν•„μš”ν•œ μƒν™©μ—μ„œ EntityManagerλ₯Ό μƒμ„±ν•˜μ—¬ μ‚¬μš©ν•œλ‹€.

    • EntityManager의 μ‚¬μš©μ„ 마치면 closeν•˜μ—¬ μ’…λ£Œν•œλ‹€.

    • μ• ν”Œλ¦¬μΌ€μ΄μ…˜ μ½”λ“œμ—μ„œ μ—”ν‹°ν‹° λ§€λ‹ˆμ €λ₯Ό κ΄€λ¦¬ν•˜κΈ° λ•Œλ¬Έμ— μžμ› λˆ„μˆ˜μ— λŒ€ν•œ λ¬Έμ œκ°€ λ°œμƒν•  수 μžˆλ‹€. (closeλ₯Ό μ•ˆ ν•΄ 쀄 경우 λ©”λͺ¨λ¦¬μ— 계속 좕적될 수 있음.)

  2. μ»¨ν…Œμ΄λ„ˆμ—μ„œ κ΄€λ¦¬ν•˜λŠ” μ—”ν‹°ν‹° λ§€λ‹ˆμ €

    • JEE μ»¨ν…Œμ΄λ„ˆμ—μ„œ EntityManagerFactory와 EntityManager의 라이프 사이클을 κ΄€λ¦¬ν•œλ‹€.

    • μ• ν”Œλ¦¬μΌ€μ΄μ…˜ μ½”λ“œμ—μ„œλŠ” μ»¨ν…Œμ΄λ„ˆκ°€ μ œκ³΅ν•˜λŠ” μ—”ν‹°ν‹° λ§€λ‹ˆμ €λ₯Ό μ‚¬μš©ν•˜λ©΄ λœλ‹€. (λ³„λ„μ˜ closeλ₯Ό ν•΄ 쀄 ν•„μš”κ°€ μ—†μŒ.)

    • @PersistenceContextλ₯Ό μ‚¬μš©ν•˜μ—¬ κ΅¬ν˜„ν•œλ‹€.

    β†’ μŠ€ν”„λ§μ—μ„œ μ‚¬μš©ν•˜λŠ” JPAκ°€ 이런 방식이닀.


참고 자료

  1. μ–΄λΌμš΄λ“œν—ˆλΈŒ μŠ€νŠœλ””μ˜€, β€œμ˜μ†μ„± μ»¨ν…μŠ€νŠΈμ™€ μ—”ν‹°ν‹° λ§€λ‹ˆμ €β€, https://youtu.be/XlL0eq9Phws

  2. SKplanet Tacademy, β€œJPA ν”„λ‘œκ·Έλž˜λ° κΈ°λ³ΈκΈ° 닀지기 6κ°• - JPA 내뢀ꡬ쑰”, https://youtu.be/PMNSeD25Qko


2. JPA Dirty Checking

Dirty Checkingμ΄λž€ λ³€κ²½ 감지λ₯Ό λ§ν•œλ‹€.
길게 말할 것 없이 μ•„λž˜ μ½”λ“œλ₯Ό μ˜ˆμ‹œλ‘œ μ•Œμ•„λ³΄μž.

EntityManager em = emf.createEntityManager();
EntityTransaction transaction = em.getTransaction();
transaction.begin(); //[νŠΈλžœμž­μ…˜] μ‹œμž‘

//μ˜μ† μ—”ν‹°ν‹° 쑰회
Member memberA = em.find(Member.class, "memberA");

//μ˜μ† μ—”ν‹°ν‹° 데이터 μˆ˜μ •
memberA.setUsername("rose");
memberA.setAge(100);

//em.update(member) <- 이런 μ½”λ“œκ°€ μžˆμ–΄μ•Ό ν•˜μ§€ μ•Šμ„κΉŒ?

transaction.commit(); //[νŠΈλžœμž­μ…˜] 컀밋

λ§Œμ•½ λ‚΄κ°€ μœ μ € λ„€μž„μ„ rose둜, λ‚˜μ΄λ₯Ό 100μ‚΄λ‘œ λ°”κΏ¨λ‹€κ³  ν•΄λ³΄μž.
그럼 이 λ•Œ λ‚΄κ°€ updateλ₯Ό ν•˜κ±°λ‚˜ persistλ₯Ό λ‹€μ‹œ ν•΄ μ€˜μ•Ό ν•˜μ§€ μ•Šμ„κΉŒ? JPAμ—κ²Œ 데이터가 λ°”λ€Œμ—ˆλ‹€λŠ” κ±Έ μ•Œλ €μ€˜μ•Ό ν•˜μ§€ μ•Šμ„κΉŒ? 싢을 것이닀.
ν•˜μ§€λ§Œ λ”°λ‘œ 그럴 ν•„μš” 없이 commit만 ν•˜λ©΄ μžλ™μœΌλ‘œ μ—…λ°μ΄νŠΈ 쿼리가 μ‹€ν–‰λœλ‹€.

그럼 μ–˜λŠ” λ‚΄κ°€ 데이터λ₯Ό μˆ˜μ •ν–ˆλ‹€λŠ” κ±Έ μ–΄λ–»κ²Œ μ•ŒκΉŒ?
그건 λ°”λ‘œ μŠ€λƒ…μƒ· 덕뢄이닀.
JPAμ—μ„œλŠ” μ—”ν‹°ν‹°λ₯Ό μ‘°νšŒν•˜λ©΄ ν•΄λ‹Ή μ—”ν‹°ν‹°μ˜ 쑰회 μƒνƒœ κ·ΈλŒ€λ‘œ μŠ€λƒ…μƒ·μ„ λ§Œλ“€μ–΄λ†“λŠ”λ‹€.

ν”ŒλŸ¬μ‹œ(μ˜μ†μ„± μ»¨ν…μŠ€νŠΈμ˜ λ³€κ²½ λ‚΄μš©μ„ DB에 반영) λ˜λŠ” μˆœκ°„ 엔티티와 μŠ€λƒ…μƒ·μ„ 비ꡐ해 바뀐 게 μžˆλ‹€λ©΄ UPDATE 쿼리λ₯Ό μƒμ„±ν•˜μ—¬ DB에 보낸닀.

μ˜μ†μ„± μ»¨ν…μŠ€νŠΈμ—μ„œ κ΄€λ¦¬ν•˜λŠ” 데이터듀은 μ–΄λ–€ 것이 λ³€κ²½λλŠ”μ§€ 걔넀듀이 λ‹€ μ•ˆλ‹€. κ·Έλž˜μ„œ μš°λ¦¬κ°€ λ”°λ‘œ μ•Œλ €μ€„ ν•„μš”κ°€ μ—†λŠ” 것이닀. (β†’ μ€€μ˜μ†, λΉ„μ˜μ† μƒνƒœμ˜ μ—”ν‹°ν‹°λŠ” 더티 체킹 λŒ€μƒμ— ν¬ν•¨λ˜μ§€ μ•ŠλŠ”λ‹€.)

μ°Έκ³ 
더티 μ²΄ν‚ΉμœΌλ‘œ μƒμ„±λ˜λŠ” UPDATE μΏΌλ¦¬λŠ” 기본적으둜 전체 ν•„λ“œλ₯Ό μ—…λ°μ΄νŠΈ ν•œλ‹€.
λ§Œμ•½ λ³€κ²½λœ ν•„λ“œλ§Œ μ—…λ°μ΄νŠΈ ν•˜κ³  싢을 경우, μ—”ν‹°ν‹° μ΅œμƒλ‹¨μ— @DynamicUpdate λ₯Ό μ„ μ–Έν•˜λ©΄ λœλ‹€.

그럼 μ™œ em.update 뭐 이런 κ±Έ μ•ˆ μ“°κ³  더티 체킹을 μ“°λŠ” 걸까?
μžλ°” μ»¬λ ‰μ…˜μ„ 예둜 λ“€μ–΄λ³΄μž.
λ¦¬μŠ€νŠΈμ—μ„œ 데이터λ₯Ό κ°€μ Έμ˜€κ³  값을 λ³€κ²½ν•˜λ©΄ κ·Έ 후에 μš°λ¦¬κ°€ 무슨 ν–‰μœ„λ₯Ό ν•œ 적이 μžˆλ‚˜? μš°λ¦¬λŠ” λ¦¬μŠ€νŠΈμ— λ‹€μ‹œ 값을 담지 μ•ŠλŠ”λ‹€. 아무 ν–‰μœ„λ₯Ό ν•˜μ§€ μ•Šμ•„λ„ μ•Œμ•„μ„œ λ¦¬μŠ€νŠΈμ— 바뀐 값이 μ €μž₯λœλ‹€.
마치 μžλ°” μ»¬λ ‰μ…˜μ—μ„œ 값을 가져와 λ³€κ²½ν•˜λŠ” κ²ƒμ²˜λŸΌ μ‚¬μš©ν•˜κΈ° μœ„ν•΄ 더티 체킹을 μ“°λŠ” 것이닀. 즉, μ˜μ† μƒνƒœμ˜ 데이터λ₯Ό κ°€μ Έμ™€μ„œ λ°”κΎΈκ³  μ»€λ°‹λ§Œ ν•˜λ©΄ λœλ‹€.
이것이 λ°”λ‘œ 더티 체킹을 μ“°λŠ” μ΄μœ λ‹€.


참고 자료

  1. SKplanet Tacademy, β€œJPA ν”„λ‘œκ·Έλž˜λ° κΈ°λ³ΈκΈ° 닀지기 6κ°• - JPA 내뢀ꡬ쑰”, https://youtu.be/PMNSeD25Qko

  2. β€œλ”ν‹° 체킹 (Dirty Checking)μ΄λž€?”, 기얡보단 기둝을, https://jojoldu.tistory.com/415


ν”„λ‘œκ·Έλž˜λ¨ΈμŠ€ μ½”ν…Œ 1문제

+) 22. 07. 21. μΆ”κ°€ μ™„λ£Œ!!

λ¬Έμžμ—΄ 닀루기 κΈ°λ³Έ

⬆️ 문제 μ„€λͺ…

⬇️ λ‚΄κ°€ μ§  μ½”λ“œ
class Solution {
    public boolean solution(String s) {
        boolean answer = true;
        
        if(s.length() >= 1 && s.length() <= 8) {
            if(!((s.length() == 4 || s.length() == 6) && s.matches("^[0-9]*$"))) {
                answer = false;
            }
        }  
        
        return answer;
    }
}

μ μˆ˜λŠ” 12점 λ°›μŒ!! κ΅Ώ!!

근데 λ­”κ°€ 객체지ν–₯적으둜(γ…Žγ…Ž;;) 짜 보고 μ‹Άμ–΄μ„œ μΈν…”λ¦¬μ œμ΄ μΌœμ„œ ν•΄ λ΄„.

public class Main {
    public static void main(String[] args) {
        Main m = new Main();
        m.validateNumberLength("a234");
        m.validateNumber("a234");
        System.out.println(m.solution("a234"));
    }

    public boolean solution(String s) {
        boolean answer = true;
        if(!((s.length() == 4 || s.length() == 6) && s.matches("^[0-9]*$"))) {
            return answer = false;
        }

        return answer;
    }

    public void validateNumber(String s) {
        if(!(s.matches("^[0-9]*$"))) {
            throw new RuntimeException("μˆ«μžκ°€ μ•„λ‹™λ‹ˆλ‹€.");
        }
    }

    public void validateNumberLength(String s) {
        if(!(s.length() >= 1 && s.length() <= 8)) {
            throw new IllegalArgumentException("sλŠ” 길이 1 이상 8 μ΄ν•˜μΈ λ¬Έμžμ—΄μž…λ‹ˆλ‹€.");
        }
    }
}

λ¬Όλ‘  그지 같은 μ½”λ“œκΈ΄ ν•œλ°;; κ·Έλž˜λ„ λ©”μ„œλ“œλ₯Ό ν•œ 번 λ‚˜λˆ μ„œ μ‹€ν–‰ν•΄ λ΄€λ‹€. 같은 클래슀 λ‚΄μ—μ„œ λ©”μ„œλ“œ ν˜ΈμΆœν•˜λŠ” 법 맨날 ν—·κ°ˆλ ΈλŠ”λ° 이제 μ’€ μ•Œκ² μŒ... κ΅Ώ...


ν”„λ‘œκ·Έλž˜λ¨ΈμŠ€ sqlλ¬Έ

+) 22. 07. 20. μΆ”κ°€ μ™„λ£Œ!!

IS NULL

  1. 이름이 μ—†λŠ” λ™λ¬Όμ˜ 아이디
SELECT ANIMAL_ID FROM ANIMAL_INS WHERE NAME IS NULL
  1. 이름이 μžˆλŠ” λ™λ¬Όμ˜ 아이디
SELECT ANIMAL_ID FROM ANIMAL_INS WHERE NAME IS NOT NULL
  1. NULL μ²˜λ¦¬ν•˜κΈ°
SELECT ANIMAL_TYPE, IFNULL(NAME, 'No name') AS NAME, SEX_UPON_INTAKE FROM ANIMAL_INS ORDER BY ANIMAL_ID

➑️ 이거 자꾸 μ•ˆ 되길래 뭐가 λ¬Έμ œμ§€ ν–ˆλŠ”λ° 'No name' λŒ€μ†Œλ¬Έμž λ•Œλ¬Έμ΄μ—ˆμŒ... 'No Name'으둜 ν•΄μ„œ μ•ˆ λ˜λŠ” κ±°μ˜€μŒ...^^

profile
김뉴비

0개의 λŒ“κΈ€

κ΄€λ ¨ μ±„μš© 정보