[spring Boot]_9일차_JPA예제

youuu·2022년 10월 27일
0

SPRING

목록 보기
16/33
  • 조회할때 get mapping
  • 수정, 삭제 -> post

트랜젝션 특징


: 동시 커밋, 롤백 되는 단위.
-> 같은 세션에서만.
-> 서비스에 건다. return 되기전까진 트랜젝션으로 남아 있다가 return하면 세션에 올라간다.

  • 원자성
  • 일관성
  • 고립성
  • 지속성

왜 JPA를 사용해야하는 가?


  1. 생산성
    데이터베이스 설계 중심의 패러다임을 객체 설계 중심으로 역전시킬 수 있다.
  2. 유지보수
    객체지향 언어의 장점을 활용하여 유연하고 유지보수하기 좋은 도메인 모델을 편리하게 설계할 수 있다.
  3. 패러다임 불일치 해결
  4. 성능
  5. 데이터 접근 추상화와 벤더 독립성
  6. 표준
    자바 진영의 ORM 기술 표준

참고링크 🚩


mybatis, JPA 면접질문으로 나온다



@Entity


: @Entity가 붙은 클래스는 JPA가 관리하는 것으로, 엔티티라고 불린다.

  • @Entity는 반드시 파라미터가 없는 생성자가 있어야 하고, public 또는 protected 이어야 한다.
  • 테이블과 매핑
  • JPA에서 사용할 엔티티 이름을 지정.       
    보통 기본값인 클래스 이름을 사용
  • 🔺 주의사항
    기본 생성자는 필수 (JPA가 엔티티 객체 생성 시 기본 생성자를 사용)
  • final 클래스, enum, interface, inner class 에는 사용할 수 없다.
  • 저장할 필드에 final 사용 불가


패키지 생성



✅ 셋팅

DB 계정만들기


오라클 - system에서 아래 실행.

Create User scottJpa IDENTIFIED BY tiger;
GRANT DBA TO scottJpa;

🚩 1. 기본세팅


🌱📋 application.properties

create는 개발 단계에서만 넣어야 한다.
🔺 운영단계에서 넣으면 큰일! (-> drop후 create 하기 때문)
spring.jpa.hibernate.ddl-auto=create

server.port=8383
# Oracle Connect
spring.datasource.driver-class-name=oracle.jdbc.driver.OracleDriver
spring.datasource.url=jdbc:oracle:thin:@localhost:1521/xe
spring.datasource.username=scottJpa
spring.datasource.password=tiger

📋 JpaMemberRepository.java

package com.oracle.oBootJpa01.domain;

import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Table;

import lombok.Getter;
import lombok.Setter;

@Entity
@Getter
@Setter
@Table(name = "member1")
public class Member {
	@Id
	private Long id;
	private String name;
}

📌📋 MemberController.java

package com.oracle.oBootJpa01.controller;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;

import com.oracle.oBootJpa01.domain.Member;
import com.oracle.oBootJpa01.service.MemberService;

@Controller
public class MemberController {
	private static final Logger logger = LoggerFactory.getLogger(MemberController.class);
	private final MemberService memberService;
	
	@Autowired
	public MemberController(MemberService memberService) {
		this.memberService = memberService;
	}
	
	@GetMapping(value = "/members/new")
	public String createForm() {
		System.out.println("MemberController /members/new Start =======");
		return "members/createMemberForm";
	}
	
	@PostMapping(value = "members/save")
	public String memberSave(Member member) {
		System.out.println("MemberController memberSave Start =======");
		System.out.println("member.getId() ==>" + member.getId());
		System.out.println("member.getName() ==>" + member.getName());
		memberService.memberSave(member);
		return "redirect:/";
	}
}

📋 Member.java

toString 을 써서 Member객체를 보기 위해 처음엔 아래처럼 사용했다.
Override 사용, @Getter @Setter 사용 하였다.

package com.oracle.oBootJpa01.domain;

import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Table;

import lombok.Getter;
import lombok.Setter;

@Entity
@Getter
@Setter
@Table(name = "member1")
public class Member {
	@Id
	private Long id;
	private String name;
	
	
	@Override
	public String toString() {
		String returnStr = "";
		returnStr = "[id:" + this.id + ", name:" + this.name + "]";	
		return returnStr;
	}
}

수정 후 : @Getter @Setter 대신 @Data를 넣는다.
@Data 안에 toString 이 내장되어있다.

이부분은 주석을 풀어도 돌아간다.

	@Override
	public String toString() {
		String returnStr = "";
		returnStr = "[id:" + this.id + ", name:" + this.name + "]";
		return returnStr;
	}
package com.oracle.oBootJpa01.domain;

import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Table;

import lombok.Data;
import lombok.Getter;
import lombok.Setter;

@Entity
@Data
//@Getter
//@Setter
@Table(name = "member1")
public class Member {
	@Id
	private Long id;
	private String name;
	
//	@Override
//	public String toString() {
//		String returnStr = "";
//		returnStr = "[id:" + this.id + ", name:" + this.name + "]";
//		
//		return returnStr;
//	}
}

📋 MemberService.java

package com.oracle.oBootJpa01.service;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.oracle.oBootJpa01.domain.Member;
import com.oracle.oBootJpa01.repository.MemberRepository;

@Service
@Transactional
public class MemberService {
	private final MemberRepository memberRepository;
	
	@Autowired
	public MemberService(MemberRepository memberRepository) {
		this.memberRepository = memberRepository;
	}
	
	// 회원가입
	public Long memberSave (Member member) {
		memberRepository.memberSave(member);
		System.out.println("MemberService memberSave member ===> " + member);

		return member.getId();
	}
}

📋 JpaMemberRepository.java

package com.oracle.oBootJpa01.repository;

import javax.persistence.EntityManager;

import org.springframework.stereotype.Repository;
import com.oracle.oBootJpa01.domain.Member;

@Repository
public class JpaMemberRepository implements MemberRepository {

	// JPA DML --> EntityManager 필수 
	private final EntityManager em;
	public JpaMemberRepository(EntityManager em) {
		this.em = em;
	}
	
	@Override
	public Member memberSave(Member member) {
		// 저장 method
		em.persist(member);
		System.out.println("JpaMemberRepository memberSave member After ===========");
		return member;
	}

}

📋 index.html

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
	<a href="/members/new">Member 신규 생성</a><p>
	<a href="/members">Member List 조회</a><p>
	
</body>
</html>

📋 createMemberForm.html

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
	<h1>JPA 회원등록</h1>
	<div class="container">
		<form action="/members/save" method="post">
				ID : <input type="text" id="id" name="id" required="required">
				이름 : <input type="text" id="name" name="name" placeholder="이름을 입력하세요">
			<button type="submit">등록</button>
		</form>
	</div>
</body>

📋 MemberRepository.java

package com.oracle.oBootJpa01.repository;

import com.oracle.oBootJpa01.domain.Member;

public interface MemberRepository {
	Member	memberSave(Member member);
		
}

👀

member.java에서 @Id를 주석처리 하면 아래처럼 오류가 뜬다.
✔ PK 누락?

org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'entityManagerFactory' defined in class path resource [org/springframework/boot/autoconfigure/orm/jpa/HibernateJpaConfiguration.class]: Invocation of init method failed; nested exception is org.hibernate.AnnotationException: No identifier specified for entity: com.oracle.oBootJpa01.domain.Member



📌📋 MemberController.java

  • 아래 입력 -> getListAllMember 만들기 이동
	@GetMapping(value = "/members")
	public String listMember(Model model) {
		List<Member> memberList = memberService.getListAllMember();
		logger.info("memberList.size() -->" + memberList.size());
		model.addAttribute("members", memberList);
		return "members/membersList";
		
	}

📋 MemberService.java

  • 아래 입력 -> findAllMember 만들기 이동
	public List<Member> getListAllMember() {
		List<Member> listMember = memberRepository.findAllMember();
		System.out.println("MemberService getListAllMember listMember.size()" + listMember.size());
		return listMember;
	}

📋 MemberRepository.java

  • 아래가 자동으로 생성됨. ->JpaMemberRepository.java에 오류뜸
List<Member> findAllMember();

📋 MemberRepository.java

	@Override
	public List<Member> findAllMember() {
		List<Member> memberList = em.createQuery("select m from Member m", Member.class)
									.getResultList();
		System.out.println("JpaMemberRepository findAllMember memberList.size()" + memberList.size());
		return memberList;
	}

📋 memberList.html

타임리프에 xmlns: <html xmlns:th="http://www.thymeleaf.org">

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
	<div class="container">
		<table border="1">
			<thead>
			<tr>
				<th>No</th>
				<th>이름</th>
			</tr>
			</thead>
			<tbody>
				<tr th:each="member : ${members}">
					<td th:text="${member.id}"></td>
					<td th:text="${member.name}"></td>
				</tr>
			</tbody>
		</table>
	</div>
</body>
</html>
profile
공부중인 주니어 개발자

0개의 댓글