diff --git a/week03/hyunji/README.md b/week03/hyunji/README.md new file mode 100644 index 0000000..5413f67 --- /dev/null +++ b/week03/hyunji/README.md @@ -0,0 +1,298 @@ +## 3주차 - 회원 관리 예제(웹 MVC 개발) + +### **[홈화면]** +
+
+
+
+
+
+
+
+
+
+### : 회원 가입과 회원 목록 중 선택해 해당하는 창으로 넘어감
+
+* * *
+
+### **[등록]**
+
+
+@Controller
+public class MemberController {
+
+ private MemberService memberService;
+
+ @Autowired
+ public MemberController(MemberService memberService) {
+ this.memberService = memberService;
+ }
+
+ @GetMapping(value = "/members/new")
+ public String createForm() {
+ return "members/createMemberForm";
+ }
+}
+
+
+### : 기존에 작성해둔 MemberController에 @GetMapping 추가해 createMemberForm 반환
+
+->
+
+
+
+
+
+
+
+
+
+
+
+
+### : input 박스에 이름을 입력해 등록 버튼을 누르면 등록
+
+
+
+@PostMapping(value = "/members/new")
+ public String create(MemberForm form) {
+ Member member = new Member();
+ member.setName(form.getName());
+ memberService.join(member);
+ return "redirect:/";
+ }
+
+
+### : 회원 컨트롤러에서 회원을 실제로 등록하는 역할
+### @PostMapping : 데이터를 폼에 넣어서 전달할 때 사용
+- 데이터를 등록할 때 -> PostMapping
+- 조회할 때 -> GetMapping
+
+* * *
+
+### **[조회]**
+
+
+@GetMapping(value = "/members")
+ public String list(Model model) {
+ List members = memberService.findMembers();
+ model.addAttribute("members", members);
+ return "members/memberList";
+ }
+
+
+### : 등록된 모든 멤버를 꺼내서 리스트에 저장하고 그 리스트를 모델에 담아서 넘김
+
+->
+
+
+
+
+
+
+
+
+
+
+ #
+ 이름
+
+
+
+
+
+
+
+
+
+
+
+
+
+### : 루프가 돌면서 객체를 하나씩 꺼내 멤버에 담고 아이디와 이름 출력
+
+## 3주차 - 스프링 DB 접근 기술
+
+
+
+import hello.hello_spring.repository.JdbcMemberRepository;
+import hello.hello_spring.repository.MemberRepository;
+import hello.hello_spring.repository.MemoryMemberRepository;
+import hello.hello_spring.service.MemberService;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+import javax.sql.DataSource;
+
+@Configuration
+public class SpringConfig {
+
+ private final DataSource dataSource;
+ public SpringConfig(DataSource dataSource) {
+ this.dataSource = dataSource;
+ }
+
+ @Bean
+ public MemberService memberService() {
+ return new MemberService(memberRepository());
+ }
+
+ @Bean
+ public MemberRepository memberRepository() {
+ // return new MemoryMemberRepository();
+ return new JdbcMemberRepository(dataSource);
+ }
+}
+
+
+### : 기존 메모리 버전의 멤버 리포지토리를 빼고 jdbc 버전의 멤버 리토지토리를 등록하면 구현체만 바꿔줌
+### 개방-폐쇄 원칙(OCP, Open-Closed Principle) : 확장에는 열려있고, 수정, 변경에는 닫혀있다
+### 스프링의 DI(Dependencies Injection)를 사용하면 기존 코드에 손대지 않고, 설정 수정만으로 구현 클래스 변경 가능
+
+
+
+@SpringBootTest
+@Transactional
+class MemberServiceIntegrationTest {
+
+ @Autowired MemberService memberService;
+ @Autowired MemberRepository memberRepository;
+
+ @Test
+ public void 회원가입() throws Exception {
+//Given
+ Member member = new Member();
+ member.setName("hello");
+//When
+ Long saveId = memberService.join(member);
+//Then
+ Member findMember = memberRepository.findById(saveId).get();
+ assertEquals(member.getName(), findMember.getName());
+ }
+
+ @Test
+ public void 중복_회원_예외() throws Exception {
+//Given
+ Member member1 = new Member();
+ member1.setName("spring");
+
+ Member member2 = new Member();
+ member2.setName("spring");
+//When
+ memberService.join(member1);
+ IllegalStateException e = assertThrows(IllegalStateException.class,
+ () -> memberService.join(member2)); //예외가 발생해야 한다.
+
+ assertThat(e.getMessage()).isEqualTo("이미 존재하는 회원입니다.");
+ }
+}
+
+
+### **@SpringBootTest** : 스프링 컨테이너와 테스트를 함께 실행
+### **@Transactional** : 테스트 시작 전에 트랜잭션을 시작하고, 테스트 완료 후에 항상 롤백. DB에 데이터가 남지 않아 다음 테스트에 영향 X
+
+### **[Jdbc]**
+
+
+import hello.hello_spring.domain.Member;
+import org.springframework.jdbc.core.JdbcTemplate;
+import org.springframework.jdbc.core.RowMapper;
+import org.springframework.jdbc.core.namedparam.MapSqlParameterSource;
+import org.springframework.jdbc.core.simple.SimpleJdbcInsert;
+import javax.sql.DataSource;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Optional;
+
+public class JdbcTemplateMemberRepository implements MemberRepository {
+
+ private final JdbcTemplate jdbcTemplate;
+
+ public JdbcTemplateMemberRepository(DataSource dataSource) {
+ jdbcTemplate = new JdbcTemplate(dataSource);
+ }
+
+ @Override
+ public Member save(Member member) {
+ SimpleJdbcInsert jdbcInsert = new SimpleJdbcInsert(jdbcTemplate);
+ jdbcInsert.withTableName("member").usingGeneratedKeyColumns("id");
+
+ Map parameters = new HashMap<>();
+ parameters.put("name", member.getName());
+
+ Number key = jdbcInsert.executeAndReturnKey(new MapSqlParameterSource(parameters));
+ member.setId(key.longValue());
+ return member;
+ }
+
+ @Override
+ public Optional findById(Long id) {
+ List result = jdbcTemplate.query("select * from member where id = ?", memberRowMapper(), id);
+ return result.stream().findAny();
+ }
+
+ @Override
+ public List findAll() {
+ return jdbcTemplate.query("select * from member", memberRowMapper());
+ }
+
+ @Override
+ public Optional findByName(String name) {
+ List result = jdbcTemplate.query("select * from member where name = ?", memberRowMapper(), name);
+ return result.stream().findAny();
+ }
+
+ private RowMapper memberRowMapper() {
+ return (rs, rowNum) -> {
+ Member member = new Member();
+ member.setId(rs.getLong("id"));
+ member.setName(rs.getString("name"));
+ return member;
+ };
+ }
+}
+
+
+
+
+
+@Bean
+ public MemberRepository memberRepository() {
+ return new JdbcTemplateMemberRepository(dataSource);
+ }
+
+
+### : Jdbc를 Jdbc 템플릿으로 변경
+- Jdbc와 동일한 환경설정
+- JDBC API에서 본 반복 코드를 대부분 제거
+- SQL 직접 작성
+
+### **[JPA]**
+- 반복 코드와 SQL 모두 JPA가 직접 만들어 실행
+- SQL과 데이터 중심의 설계에서 객체 중심의 설계로 패러다임을 전환 가능
+
+### **[스프링 데이터 JPA]**
+- 스프링 부트와 JPA만으로도 개발 생산성 증가
+- 스프링 데이터 JPA를 사용하면 리포지토리에 구현 클래스 없이 인터페이스 만으로 개발 가능
+- 반복 개발해온 기본 CRUD 기능도 스프링 데이터 JPA가 모두 제공
+- 단순하고 반복적 개발 코드들이 줄어들어 개발자가 핵심 비즈니스 로직을 개발하는데 집중할 수 있음
+- 제공 기능
+ - 인터페이스를 통한 기본적인 CRUD
+ - 메서드 이름 만으로 조회 기능 제공 (findByName(),findByEmail() 등)
+ - 페이징 기능 자동 제공