피할 수 없다면 즐기자! 스프링부트 너.. 뭐 돼?
# #=> application.properties 의 주석
#port - 포트 수정
server.port=9090
#thymeleaf cache - 타임 리프 캐시 설정
spring.thymeleaf.cache=false
#encoding - 한글 인코딩
server.servlet.encoding.charset=UTF-8
server.servlet.encoding.force=true
server.servlet.encoding.enabled=true
#dbms - jdbc db 설정
spring.datasource.url=jdbc:oracle:thin:@localhost:1521:XE
spring.datasource.driver-class-name=oracle.jdbc.OracleDriver
spring.datasource.username=myspring
spring.datasource.password=myspring
#jpa - jpa 설정
#spring.jpa.open-in-view=false
spring.jpa.show-sql=true
spring.jpa.hibernate.ddl-auto=none
package com.koreait.core2.member;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.SequenceGenerator;
// @Entity : jpa가 관리하는 class
@Entity
public class Member {
@Id @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "mySequence")
@SequenceGenerator(name = "mySequence", sequenceName = "member_seq", allocationSize = 1)
private int id;
// @Column(name="username")
private String name;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
package com.koreait.core2.controller;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import com.koreait.core2.member.Member;
import com.koreait.core2.member.MemberFormDTO;
import com.koreait.core2.service.MemberService;
@Controller
public class MemberController {
// Controller가 Service를 의존한다라고 표현
// Service는 여러 Controller에서 가져다 쓸 수 있기 때문에
// Spring Container에 등록을 해야한다.
// MemberService mService = new MemberService();
// 스프링스럽게 작업하기
// service 는 Spring Container에 하나만 생성 및 등록해서 같이 공유해서 쓸 수 있다.
private final MemberService memberService;
@Autowired
public MemberController(MemberService memberService) {
this.memberService = memberService;
}
/*
* 필드 주입(Field Injection)
* - final 키워드를 사용할 수 없어, 순환 참조가 발생할 수 있다. 권장하지 않는다.
*
* @Autowired private MemberService memberService;
*/
/*
* 수정자 주입 (setter Injection)
* - public 으로 노출이 되기 때문에 다른 곳에서 주입 가능하다.
*
* private MemberService memberService;
*
* @Autowired
* public void setMember(MemberService memerService){
* this.memberService = memberService;
* }
*/
// home.html에서 회원가입 페이지 맵핑
@GetMapping(value = "/members/new")
public String createForm() {
return "members/createMemberForm";
}
// 회원의 정보를 포스트맵핑
@PostMapping(value = "/members/new")
public String create(MemberFormDTO form) {
// Member => 멤버 dto
Member member = new Member();
member.setName(form.getName());
memberService.join(member);
// 홈 화면으로 돌린다.
return "redirect:/";
}
@GetMapping("/members")
public String list(Model model) {
List<Member> members = memberService.findMembers();
model.addAttribute("members", members);
return "members/memberList";
}
}
package com.koreait.core2.service;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import com.koreait.core2.member.Member;
import com.koreait.core2.repository.MemberRepository;
import com.koreait.core2.repository.MemoryMemberRepository;
@Service
@Transactional
public class MemberService {
// MemberRepository memberRepository = new MemoryMemberRepository();
private final MemberRepository memberRepository;
@Autowired
public MemberService(MemberRepository memberRepository) {
this.memberRepository = memberRepository;
}
// 회원가입
public int join(Member member) {
memberRepository.save(member);
return member.getId();
}
// 전체회원 조회
public List<Member> findMembers(){
return memberRepository.findAll();
}
}
package com.koreait.core2.repository;
import java.util.List;
import com.koreait.core2.member.Member;
public interface MemberRepository {
// 회원 저장
Member save(Member member);
// 전체 찾기
List<Member> findAll();
}
package com.koreait.core2.repository;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.springframework.stereotype.Repository;
import com.koreait.core2.member.Member;
//@Repository
public class MemoryMemberRepository implements MemberRepository{
// 메모리 사용
private static Map<Integer, Member> store = new HashMap<Integer, Member>();
private static int sequence = 0;
@Override
public Member save(Member member) {
member.setId(++sequence);
store.put(member.getId(), member);
return member;
}
@Override
public List<Member> findAll() {
return new ArrayList<Member>(store.values());
}
}
package com.koreait.core2.repository;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import javax.sql.DataSource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;
import com.koreait.core2.member.Member;
//@Repository
public class JdbcMemberRepository implements MemberRepository{
private final DataSource dataSource;
// @Autowired는 생성자가 하나일 때 생략 가능
@Autowired
public JdbcMemberRepository(DataSource dataSource) {
this.dataSource = dataSource;
}
@Override
public Member save(Member member) {
String sql = "INSERT INTO MEMBER VALUES(MEMBER_SEQ.NEXTVAL, ?)";
Connection conn = null;
PreparedStatement pstmt = null;
ResultSet rs = null;
try {
conn = dataSource.getConnection();
String generatedColums[] = {"ID"};
pstmt = conn.prepareStatement(sql, generatedColums);
pstmt.setString(1, member.getName());
pstmt.executeUpdate();
rs = pstmt.getGeneratedKeys();
if(rs.next()) {
member.setId(rs.getInt(1));
}
}catch(Exception e) {
e.printStackTrace();
}finally {
try {
rs.close();
pstmt.close();
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
return member;
}
@Override
public List<Member> findAll() {
String sql = "SELECT * FROM MEMBER";
Connection conn = null;
PreparedStatement pstmt = null;
ResultSet rs = null;
List<Member> members = null;
try {
conn = dataSource.getConnection();
pstmt = conn.prepareStatement(sql);
rs = pstmt.executeQuery();
members = new ArrayList<Member>();
while(rs.next()) {
Member member = new Member();
member.setId(rs.getInt("id"));
member.setName(rs.getString("name"));
members.add(member);
}
}catch(Exception e) {
e.printStackTrace();
}finally {
try {
rs.close();
pstmt.close();
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
return members;
}
}
package com.koreait.core2.repository;
import java.util.List;
import javax.persistence.EntityManager;
import org.springframework.stereotype.Repository;
import com.koreait.core2.member.Member;
@Repository
public class JpaMemberRepository implements MemberRepository{
// JPA는 EntityManager로 모든지 동작 한다.
private final EntityManager em;
public JpaMemberRepository(EntityManager em) {
this.em = em;
}
@Override
public Member save(Member member) {
em.persist(member);
return member;
}
@Override
public List<Member> findAll() {
return em.createQuery("select m from Member m", Member.class)
.getResultList();
// select m from Member m : JPQL이라는 쿼리
}
}
public class UserDTO {
private String userName;
private String userId;
private String userPassword;
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public String getUserId() {
return userId;
}
public void setUserId(String userId) {
this.userId = userId;
}
public String getUserPassword() {
return userPassword;
}
public void setUserPassword(String userPassword) {
this.userPassword = userPassword;
}
}
단일 책임 원칙(Single Responsibility Principle)
개방-폐쇄 원칙 (Open/Closed Principle)
리스코프 치환 원칙(Liskov Substitution Principle)
인터페이스 분리의 원칙(Interface Segregation Principle)
의존 관계 역전 원칙(Dependency Inversion Principle)
출처
https://media.giphy.com/media/kyUIknbbDNvID5XzU4/giphy.gif
https://media.giphy.com/media/A6aHBCFqlE0Rq/giphy.gif