μΉμ 3. μλΈλ¦Ώ, JSP, MVC ν¨ν΄ μκ° μλ£!!
μ΄λ² κ°μλ μ€μ΅ μμ£Όλ‘ μ§νν΄μ λ±ν μ 리ν κ² λ§μ§ μλ€... λ€ μ½λλΌ...
μλ¬΄νΌ μ²μμ μλΈλ¦ΏμΌλ‘ νμ κ΄λ¦¬ μΉ μ ν리μΌμ΄μ
μ λ§λ€μλ€.
κ·Έλ°λ° μλΈλ¦Ώκ³Ό μλ° μ½λλ§μΌλ‘ HTMLμ λ§λ€μλλ λ무 λ²κ±°λ‘κ³ λΉν¨μ¨μ μ΄μλ€. μ°¨λΌλ¦¬ HTML λ¬Έμμ λμ μΌλ‘ λ³κ²½ν΄μΌ νλ λΆλΆλ§ μλ° μ½λλ₯Ό λ£λ κ²μ΄ λ νΈλ¦¬ν κ²μ΄λ€.
β‘οΈ ν νλ¦Ώ μμ§(JSP, Thymeleaf λ±)μ μ¬μ©νλ©΄ HTML λ¬Έμμμ νμν κ³³λ§ μ½λλ₯Ό μ μ©ν΄ λμ μΌλ‘ λ³κ²½ν μ μλ€.
JSPλ μλ° μ½λλ₯Ό κ·Έλλ‘ λ€ μ¬μ©ν μ μλ€.
<%@ page import="hello.servlet.domain.member.MemberRepository" %>
β‘οΈ μλ°μ importλ¬Έκ³Ό κ°λ€.
<% ~~ %>
β‘οΈ μλ° μ½λλ₯Ό μ
λ ₯ν μ μλ€.
<%= ~~ %>
β‘οΈ μλ° μ½λλ₯Ό μΆλ ₯ν μ μλ€.
JSPλ₯Ό μ¬μ©ν λλΆμ λμ μΌλ‘ λ³κ²½μ΄ νμν λΆλΆμλ§ μλ° μ½λλ₯Ό μ μ©ν μ μμλ€. νμ§λ§ μ΄ κ²½μ° JSPκ° λ무 λ§μ μν μ νλ€. κ·Έλμ μ΄λ₯Ό ν΄κ²°νκΈ° μν΄ MVC ν¨ν΄μ΄ λ±μ₯νλ€.
νλμ μλΈλ¦Ώμ΄λ JSPλ§μΌλ‘ λΉμ¦λμ€ λ‘μ§κ³Ό λ·° λ λλ§κΉμ§ λͺ¨λ μ²λ¦¬νκ² λλ©΄ λ무 λ§μ μν μ νκ² λκ³ μ μ§λ³΄μκ° μ΄λ €μμ§λ€.
JSP κ°μ λ·° ν
νλ¦Ώμ νλ©΄μ λ λλ§ νλ λ° μ΅μ νλμ΄ μκΈ° λλ¬Έμ μ΄ λΆλΆμ μ
λ¬΄λ§ λ΄λΉνλ κ²μ΄ κ°μ₯ ν¨κ³Όμ μ΄λ€.
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. μΆκ° μλ£!
μν°ν° 맀λμ (Entity Manager)λ μ»€λ° μμ μ μμμ± μ»¨ν μ€νΈ(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)λΌ νλ€.
λ³κ²½ κ°μ§(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 λ¬Έμ λ₯Ό μΌμΌν¨λ€.
μν°ν° 맀λμ λ₯Ό μμ±ν λ νλμ μμμ± μ»¨ν
μ€νΈκ° μμ±λλ€.
λ§μ½ λμΌν μλ³μλ₯Ό κ°λ μν°ν°λ₯Ό 2λ² μ‘°ννλ€λ©΄ μν°ν° 맀λμ μ μν΄ μ²« λ²μ§Έλ μΏΌλ¦¬κ° μ€νλκ³ , λ λ²μ§Έλ μΏΌλ¦¬κ° μ€νλμ§ μκ³ μμμ± μ»¨ν
μ€νΈμμ κ°μ κ°μ Έμ¨λ€.
μν°ν° 맀λμ λ DBμ μ‘μΈμ€ νκΈ° μν΄ μ¬μ©λλ κ°μ²΄μ΄λ―λ‘ μ΄λ₯Ό ν΅ν΄ λ°μ΄ν°λ₯Ό μ‘°ν, λ±λ‘, μμ , μμ νλ μμ μ μννλ€.
μ ν리μΌμ΄μ μμ κ΄λ¦¬νλ μν°ν° 맀λμ
μ ν리μΌμ΄μ μ μμνλ©΄μ EntityManagerFactoryλ₯Ό μ΄κΈ°ννκ³ , νμν μν©μμ EntityManagerλ₯Ό μμ±νμ¬ μ¬μ©νλ€.
EntityManagerμ μ¬μ©μ λ§μΉλ©΄ closeνμ¬ μ’ λ£νλ€.
μ ν리μΌμ΄μ μ½λμμ μν°ν° 맀λμ λ₯Ό κ΄λ¦¬νκΈ° λλ¬Έμ μμ λμμ λν λ¬Έμ κ° λ°μν μ μλ€. (closeλ₯Ό μ ν΄ μ€ κ²½μ° λ©λͺ¨λ¦¬μ κ³μ μΆμ λ μ μμ.)
컨ν μ΄λμμ κ΄λ¦¬νλ μν°ν° 맀λμ
JEE 컨ν μ΄λμμ EntityManagerFactoryμ EntityManagerμ λΌμ΄ν μ¬μ΄ν΄μ κ΄λ¦¬νλ€.
μ ν리μΌμ΄μ μ½λμμλ 컨ν μ΄λκ° μ 곡νλ μν°ν° 맀λμ λ₯Ό μ¬μ©νλ©΄ λλ€. (λ³λμ closeλ₯Ό ν΄ μ€ νμκ° μμ.)
@PersistenceContextλ₯Ό μ¬μ©νμ¬ κ΅¬ννλ€.
β μ€νλ§μμ μ¬μ©νλ JPAκ° μ΄λ° λ°©μμ΄λ€.
μ°Έκ³ μλ£
μ΄λΌμ΄λνλΈ μ€νλμ€, βμμμ± μ»¨ν μ€νΈμ μν°ν° 맀λμ β, https://youtu.be/XlL0eq9Phws
SKplanet Tacademy, βJPA νλ‘κ·Έλλ° κΈ°λ³ΈκΈ° λ€μ§κΈ° 6κ° - JPA λ΄λΆκ΅¬μ‘°β, https://youtu.be/PMNSeD25Qko
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 λ μ΄λ° κ±Έ μ μ°κ³ λν° μ²΄νΉμ μ°λ κ±ΈκΉ?
μλ° μ»¬λ μ
μ μλ‘ λ€μ΄λ³΄μ.
리μ€νΈμμ λ°μ΄ν°λ₯Ό κ°μ Έμ€κ³ κ°μ λ³κ²½νλ©΄ κ·Έ νμ μ°λ¦¬κ° λ¬΄μ¨ νμλ₯Ό ν μ μ΄ μλ? μ°λ¦¬λ 리μ€νΈμ λ€μ κ°μ λ΄μ§ μλλ€. μ무 νμλ₯Ό νμ§ μμλ μμμ 리μ€νΈμ λ°λ κ°μ΄ μ μ₯λλ€.
λ§μΉ μλ° μ»¬λ μ
μμ κ°μ κ°μ Έμ λ³κ²½νλ κ²μ²λΌ μ¬μ©νκΈ° μν΄ λν° μ²΄νΉμ μ°λ κ²μ΄λ€. μ¦, μμ μνμ λ°μ΄ν°λ₯Ό κ°μ Έμμ λ°κΎΈκ³ 컀λ°λ§ νλ©΄ λλ€.
μ΄κ²μ΄ λ°λ‘ λν° μ²΄νΉμ μ°λ μ΄μ λ€.
μ°Έκ³ μλ£
SKplanet Tacademy, βJPA νλ‘κ·Έλλ° κΈ°λ³ΈκΈ° λ€μ§κΈ° 6κ° - JPA λ΄λΆκ΅¬μ‘°β, https://youtu.be/PMNSeD25Qko
βλν° μ²΄νΉ (Dirty Checking)μ΄λ?β, κΈ°μ΅λ³΄λ¨ κΈ°λ‘μ, https://jojoldu.tistory.com/415
+) 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 μ΄νμΈ λ¬Έμμ΄μ
λλ€.");
}
}
}
λ¬Όλ‘ κ·Έμ§ κ°μ μ½λκΈ΄ νλ°;; κ·Έλλ λ©μλλ₯Ό ν λ² λλ μ μ€νν΄ λ΄€λ€. κ°μ ν΄λμ€ λ΄μμ λ©μλ νΈμΆνλ λ² λ§¨λ ν·κ°λ Έλλ° μ΄μ μ’ μκ² μ... κ΅Ώ...
+) 22. 07. 20. μΆκ° μλ£!!
SELECT ANIMAL_ID FROM ANIMAL_INS WHERE NAME IS NULL
SELECT ANIMAL_ID FROM ANIMAL_INS WHERE NAME IS NOT NULL
SELECT ANIMAL_TYPE, IFNULL(NAME, 'No name') AS NAME, SEX_UPON_INTAKE FROM ANIMAL_INS ORDER BY ANIMAL_ID
β‘οΈ μ΄κ±° μκΎΈ μ λκΈΈλ λκ° λ¬Έμ μ§ νλλ° 'No name' λμλ¬Έμ λλ¬Έμ΄μμ... 'No Name'μΌλ‘ ν΄μ μ λλ κ±°μμ...^^