: 동시 커밋, 롤백 되는 단위.
-> 같은 세션에서만.
-> 서비스에 건다. return 되기전까진 트랜젝션으로 남아 있다가 return
하면 세션에 올라간다.
왜 JPA를 사용해야하는 가?
mybatis, JPA 면접질문으로 나온다
: @Entity가 붙은 클래스는 JPA가 관리하는 것으로, 엔티티라고 불린다.
패키지 생성
오라클 - system에서 아래 실행.
Create User scottJpa IDENTIFIED BY tiger;
GRANT DBA TO scottJpa;
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
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;
}
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:/";
}
}
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;
// }
}
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();
}
}
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;
}
}
<!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>
<!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>
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
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";
}
findAllMember
만들기 이동 public List<Member> getListAllMember() {
List<Member> listMember = memberRepository.findAllMember();
System.out.println("MemberService getListAllMember listMember.size()" + listMember.size());
return listMember;
}
JpaMemberRepository.java
에 오류뜸List<Member> findAllMember();
@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;
}
타임리프에 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>