-
프로젝트 환경설정
- Model : data를 실어서 view에 넘김
- 정적 컨텐츠 : index.html 처럼 static 폴더에 있는거 바로 띄움
- 템플릿 엔진, 렌더링 필요한거는 templates 폴더에
- ./h2.bat 으로 디비 실행
- 이거 공부해야될듯?!!
- @Entity : @Entity가 붙은 클래스는 JPA가 관리
- @Id @GeneratedValue
- entity manager ??
- Transaction???
- 컴포넌트 스캔 → 자동으로 스프링 빈에 등록
-
도메인 분석 설계
- 엔티티 클래스 개발
-
@Entity : 테이블과 링크될 클래스
-
@Id : 해당 테이블의 PK
-
@GeneratedValue : PK 생성규칙 표시 (값 생성 보장)
-
@Column(name = "member_id") : 테이블의 칼럼임을 표시
-
@Embeddable : 값 타입을 정의하는 곳에 표시
-
@Embedded : 값 타입을 사하는 곳에 표시
-
@JoinColumn(name = member_id") : 외래키 이름이 member_id
-
연관관계주인 : fk가 가까운 곳 (주인은 아무것도 안해도 됨)
-
@OneToMany(mappedBy = "member") : Order 테이블의 ㅣmember에서 매핑된 애(읽기전용)
-
상속관계매핑 → 상속관계 전략 지정을 부분클래스에
-
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
-
@Enumerated(EnumType.STRING)
-
@JoinTable(name = "category_item", joinColumns = @JoinColumn(name = "category_id"), inverseJoinColumns = @JoinColumn(name = "item_id"))
-
enum : 사용자가 자신이 필요한 정보를 열거(=선언, 정의)하여 사용하는 집합 자료형
-
- 엔티티 설계시 주의점
- 엔티티에 Setter 사용 가급적 자제 : 변경포인트가 많아 유지보수가 어려움
- 모든 연관관계는 자연로딩으로!!! : EAGER는 N+1문제, join으로 인한 성능문제, 어떤 SQL이 실행될지 추적어려움 → LAZY로 설정!!!
- @XToOne(OneToOne, ManyToOne) 은 기본이 EAGER → ex) @ManyToOne(fetch = FetchType.LAZY) 해야됨!!
- @OneToMany는 기본이 LAZY
- 컬렉션은 필드에서 바로 초기화하자!!
- 연관관계 편의 메서드
- 양방향의 경우 하나의 메소드에서 양측의 관계를 설정하게 해주는게 안
- 엔티티 클래스 개발
-
애플리케이션 구현 준비
- 애플리케이선 아키텍처
- controller : 웹 계층
- service : 비즈니스 로직, 트랜젝션 처리
- repository : JPA 직접 사용 / 엔티티 매니저 사용
- domain : 엔티티가 모여있는 계층 / 모든 계층에서 사
- 애플리케이선 아키텍처
-
회원 도메인 개발
-
회원 리포지토리
- @PersistenceContext : EntityManager를 빈으로 주입
- EntityManager : 영속성 관리
- 쓰레드 간 EntityManager 공유 X
- 스프링은 싱글톤 기반이라 모든 쓰레드가 빈을 공유하지만 스프링 컨테이너가 초기화되면서 @PersistenceContext로 주입받은 EntityManager를 Proxy로 감쌈 → Thread-Safe 보장!
- em.persist(member) : JPA가 member 저장(영속성)
- 영속성 : 데이터를 생성한 프로그램이 종료되어도 사라지지 않는 데이터의 특
- em.createQuery("select m from Member m", Member.class) : “select문” = JPQL(Entity 대상으로 쿼리 날림), Member m이 반환 타입
- setParameter :
- @RequiredArgsConstructor : final 이 붙은거 생성자 만들어줌!
-
Test할때 Memory DB 사용~
-
-
주문 검색기능 개발
- JPA에서 동적쿼리를 어떻게 해결?
- Querydsl로 처리
- JPA에서 동적쿼리를 어떻게 해결?
-
웹 계층 개발
- 홈 화면과 레이아웃
-
- resources:templates/ +{ViewName}+ .html
-
- 회원등록
-
model.addAttribute("memberForm", new MemberForm()); ⇒ controller에서 view 넘어갈 때 데이터를 실어서 넘김
-
Get은 form 화면을 열어보고, Post는 데이터를 실제 등록
-
오류 있으면 다시 등록하게
public String create(@Valid MemberForm form, BindingResult result) { if (result.hasErrors()) { return "members/createMemberForm"; }
-
-
API 만들때는 절대 Entity를 웹으로 반환 X !!!!
- api는 스펙, entity에 로직 추가했는데 api 스펙이 변하면 안됨
- DTO : Data Transfer Object, 계층 간 데이터 전송을 위해 도메인 모델 대신 사용되는 객체
-
상품 수정
- @GetMapping("items/{itemId}/edit")public String updateItemForm(@PathVariable("itemId") Long )
-
***** 머지가 머지?! *****
- 변경 감지와 병합
- 준영속 엔티티 : 영속성 컨텍스트가 더는 관리하지 않는 엔티티 → JPA를 한번 걸친거(식별ID가 있음)
- 영속 엔티티는 변경 감지가 일어남! But 준영속은 JPA가 관리 X (BookForm form 에서 form.get어쩌구해서 새로운 book 객체 만들고 값을 바꿔도 디비에 없데이트 X)
- 준영속 엔티티 수정방법 2가지
-
변경 감지 기능 사용 (dirty checking)
-
@Transactionalpublic void updateItem(Long itemid, Book param) {
Item findItem = itemRepository.findOne(itemid);
-
-
em.merge(item) : 값이 없으면 null로 들어가는 문
-
- 엔티티 변경할 때는 항상 변경감지 사용
- 변경 감지와 병합
-
@RequestParam("memberId") Long memberId : memberId에 있는거를 memberId 변수에 담아서 전달
-
@ModelAttribute : 사용자가 요청시 전달하는 값을 오브젝트(객체) 형태로 매핑
-
@PathVariable("orderId") Long orderId : url에서 각 구분자에 들어오는 값을 처리해야 할 때 사용
- 홈 화면과 레이아웃
-
질문 (10/31)
💡 **Q. ㅁㅁㅁㅁ을 채우세용**
@ㅁㅁㅁㅁ
public class HelloController {
@GetMapping("hello") public String hello(Model model) { model.addAttribute("data", "hello!!"); return "hello"; }
}
-
정답!
@Controller
-
그럼 Controller의 역할은 ?!!
모델과 뷰 사이 다리역할
-
그럼 스프링에서 @Controller을 쓰면 어떤 일이 ??!!
스프링 시작시 객체를 생성하여 스프링 컨테이너에서 컨트롤러 관리
-
@Controller에 어떤 어노테이션이 있어서 가능할까??!
@Component 가 있어서 가능하다~
-
return “hello” 는 어떤 의미? (기능?, 효과?) 일까?!
templates의 hello.html로 간다~
-
-
-
-
Q. 다대다 는 어떻게 바꿔서 풀어내면 좋을까??
-
정답!
엔티티를 추가해서 다대다 관계를 일대다, 다대일 관계로~
-
-
질문 (11/7)
💡 **Q1. a와 b에 어떤게 들어갈까?**@Service
@ a. 여기를 채워주세용
- 정답!
-
Transactional(readOnly = true) 붙인 이유는?! (hint: 왜 회원가입은 안붙었을까)
회원가입할 때는 readOnly가 아니거든!
-
@ b. 여기를 채워주세용
- 정답
-
RequiredArgsConstructor 은 무슨역할일까?! (hint : final)
final 붙은거 생성자 바로 만들어줘용
-
public class MemberService {
private **final** MemberRepository memberRepository;} */** *회원 가입 */* **@Transactional** public Long join(Member member) { validateDuplicateMember(member); //중복회원 검증 memberRepository.save(member); return member.getId(); } private void validateDuplicateMember(Member member) { List<Member> findMembers = memberRepository.findByName((member.getName())); if (!findMembers.isEmpty()) { throw new IllegalStateException("이미 존재하는 회원입니다."); } } //회원 전체 조회 **@ a. 여기를 채워주세용 (위에랑 같은거)** public List<Member> fineMembers(){ return memberRepository.findAll(); } **@a. 여기를 채워주세용 (위에랑 같은거)** public Member findOne(Long memberId){ return memberRepository.findOne(memberId); }
}
- Q2. 모든 연관관계는 무슨 로딩으로 해야될까?
- 정답!
- 자연로딩 / 왜?
- EAGER는 N+1문제, join으로 인한 성능문제, 어떤 SQL이 실행될지 추적어려움 → LAZY로 설정!!! 그럼 어떤 연관관계에서 따로 지정해줘야될까?
-
정답
@XToOne(OneToOne, ManyToOne) 은 기본이 EAGER → ex) @ManyToOne(fetch = FetchType.LAZY) 해야됨!!
-
- EAGER는 N+1문제, join으로 인한 성능문제, 어떤 SQL이 실행될지 추적어려움 → LAZY로 설정!!! 그럼 어떤 연관관계에서 따로 지정해줘야될까?
- 자연로딩 / 왜?
- 정답!
-
질문(11/14)
-
1. @RequestParam, @ModelAttribute, @PathVariable의 차이점이 뭘까??!
- @RequestParam : 사용자가 요청시 전달하는 값을 매개변수로 1:1 맵핑
- @ModelAttribute : 사용자가 요청시 전달하는 값을 오브젝트 형태로 매핑
- @PathVariable : url에서 각 구분자에 들어오는 값을 처리해야 할 때 사용
@PostMapping("/order") public String order(**@RequestParam("memberId") Long memberId, @RequestParam("itemId") Long itemId, @RequestParam("count")** **int count**) { orderService.order(memberId, itemId, count); return "redirect:/orders"; } @PostMapping("/orders/{orderId}/cancel") public String cancelOrder(**@PathVariable("orderId") Long orderId**){ orderService.cancelOrder(orderId); return "redirect:/orders"; } @PostMapping("items/{itemId}/edit") public String updateItem(**@PathVariable Long itemId, @ModelAttribute("form") BookForm for**m) { //Book book = new Book(); // book.setId(form.getId()); // book.setName(form.getName()); // book.setPrice(form.getPrice()); // book.setStockQuantity(form.getStockQuantity()); // book.setAuthor(form.getAuthor()); // book.setIsbn(form.getIsbn()); // itemService.saveItem(book); itemService.updateItem(itemId, form.getName(), form.getPrice(), form.getStockQuantity()); return "redirect:/items"; }
-
Q. updateItem에서 Book book = new Book(); 같은 방식으로 하지 않는 이유는??
A. saveItem으로 하면 merge 로 해서 변경하는거임! 머지가 머지?
-
그래서 변경 감지 기능 사용 (dirty checking) 해야된다
@Transactional public void updateItem(Long itemid, Book param) { Item findItem = itemRepository.findOne(itemid); . . .
-
-
-
Notifications
You must be signed in to change notification settings - Fork 0
jeongyeon0208/spring-jpashop
Folders and files
Name | Name | Last commit message | Last commit date | |
---|---|---|---|---|
Repository files navigation
About
실전! 스프링 부트와 JPA
Resources
Stars
Watchers
Forks
Releases
No releases published
Packages 0
No packages published