
📌 JPA
JPA(Java Persistence API)는 Java 진영의 ORM 기술 표준으로, 적합한 SQL을 생성하여 DB에 전달하고, 객체를 자동으로 매핑해준다. (SQL을 직접 작성할 필요가 없음)
장점
- 생산성이 뛰어나고 유지보수가 용이하다.
- DBMS에 대한 종속성이 줄어든다.
단점
- JPA의 장점을 살려 잘 사용하기 위해서는 학습 비용이 높고, 복잡한 쿼리를 사용할 때 불리하다.
- 잘못 사용할 경우 SQL을 직접 사용하는 것보다 성능이 떨어질 수 있다.
📌 Entity
데이터베이스에 쓰일 필드와 여러 Entity 간의 관계를 설정하는 것이다.
(myBatis에서의 sql, xml, domain 역할)
- @Entity를 이용해 해당 클래스가 Entity임을 알려준다.
- JPA에 정의된 필드를 바탕으로 테이터베이스에 테이블을 만들 수 있다.
Entity 관련 Annotation
@Entity: 데이터베이스의 table임을 의미한다.
@Table: 테이블 이름을 명시한다. (작성하지 않는 경우, Entity 클래스명이 테이블명이 됨)
Id: primary key를 의미한다.
GeneratedValue: primary key의 생성 전략을 설정한다. (ex. startegy = GenerationType.Auto)
Column: table의 컬럼을 의미한다. (length, nullable 등 속성을 변경할 수 있다.)
📌 Repository
Entity에 의해 생성된 DB에 접근하는 메소드를 사용하기 위한 인터페이스이다. (myBatis에서의 mapper 역할)
- JpaRepository를 상속받으면, 기본적인 DB 접근 메소드를 사용할 수 있다.
(ex. findAll(), findById(), findBy컬럼명(), save()) - JpaRepository에서 기본적으로 제공하는 쿼리는 repository에서 별도로 작성하지 않아도 service에서 바로 사용할 수 있다.
📌 Optional
Null의 가능성이 있는 객체를 감싸는 Wrapper 클래스이다.
Optional<T>
- Option 변수 내부에는 null이 아닌 T객체가 있을 수 있다.
- 또는 null이 있을 수 있다.
- 즉, Optional 클래스는 여러가지 API를 제공해 Null의 가능성이 있는 객체를 다룰 수 있다.
- Optional 클래스의 값을 가져오기 위해서는 .get()으로 접근 후 가져와야 한다.
Optional 클래스의 주요 메소드
Present(): 값이 있으면 true, 없으면 false를 반환한다.
orElse(): 값이 있으면 그 값을 반환하고, 없으면 ()안에 인자로 넘겨진 값을 반환한다. (ex. ~~.orElse("저장된 값이 없습니다.")
orElseThrow(): 값이 있으면 그 값을 반환하고, 없으면 ()안의 throw 함수(예외처리 함수)를 실행한다.
of(): 명시된 값을 갖는 Optional 객체를 반환한다. (주의: null이 아님을 확신하는 값이어야 함)
📌 JPA 사용하기
dependency 라이브러리 추가 & application.properties 수정
→ Entity 생성 (테이블 설정, getter, setter)
→ Repository 생성 (DB에 접근하는 메소드를 사용하기 위한 인터페이스)
→ Service 생성
→ Controller 생성
dependency 추가
// build.gradle
implementation: 'org.springframework.boot:spring-boot-starter-data-jpa'
application.properties 수정
// application.properties
spring.jpa.show-sql=true // jpa에서 사용할 수 있는 sql문을 보여준다.
spring.jpa.hibernate.ddl-auto=create // 서버 실행 시, 설정한 테이블이 생성되도록 한다.
// none: not create, create: auto create, update: only update
UserEntity
이전 mybatis에서의 sql, xml, domain 파일의 역할을 한다.
// UserEntity.java
@Entity
@Table(name="myTable")
public class MemberEntity {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private int id;
@Column(length = 31, nullable = false)
private String userId;
@Column(length = 31, nullable = false)
private String name;
@Column(nullable = false)
private String password;
// 속성을 기본값으로 유지한다면, @Column 표기하지 않아도 된다.
private String email;
public int getId() { return id; }
public void setId(int id) { this.id = id; }
public String getUserId() { return userId; }
public void setUserId(String userId) { this.userId = userId; }
// ...
// name, password, email의 getter, setter 함수
}
repository
// MemberRepository.java
@Repository
public interface MemberRepository extends JpaRepository<MemberEntity, Integer> {
MemberEntity findByUserIdAndPassword(String userId, String password);
Optional<MemberEntity> findByUserId(String userId);
}
Service
// MemberService.java
@Service
public class MemberService {
@Autowired
private MemberRepository memberRepository;
public void insertNewMember(MemberDTO memberDTO){
MemberEntity member = new MemberEntity();
member.setUserId(memberDTO.getUserId());
member.setName(memberDTO.getName());
member.setPassword(memberDTO.getPassword());
// .save()와 같은 기본 JpaRepository 쿼리는 repository에서 별도로 작성하지 않아도 바로 사용할 수 있다.
memberRepository.save(member);
}
public boolean checkMember(MemberDTO memberDTO) {
MemberEntity member = memberRepository.findByUserIdAndPassword(memberDTO.getUserID(), memberDTO.getPassword());
if (member != null) return true;
else return false;
}
public Optional<MemberDTO< getProfile(String userId) {
Optional<MemberEntity> member = memberRepository.findByUserId(userId);
if (member.isPresent()){
MemberDTO data = new MemberDTO();
data.setId(member.get().getId());
data.setUserId(member.get().getUserId());
data.setPassword(member.get().getPassword());
data.setName(member.get().getName());
return Optional.of(data);
} else {
return Optional.empty();
}
}
public boolean updateProfile(MemberDTO memberDTO) {
Optional<MemberEntity> member = memberRepository.findById(memberDTO.getId());
if (member.isPresent()){
MemberEntity data = member.get();
data.setName(memberDTO.getName());
data.setPassword(memberDTO.getPassword());
data.setUserId(memberDTO.getUserId());
memberRepository.save(data);
return true;
} else return false;
}
public void deleteProfile(MemberDTO memberDTO) {
memberRepository.deleteById(memberDTO.getId());
}
}
Controller
// MemberController.java
@Controller
public class MemberController {
@Autowired
private MemberService memberService;
@GetMapping("/profile")
public String getProfile(@RequestParam String userId, Model model) {
Optional<MemberDTO> member = memberService.getProfile(userId);
if (member.isPresent()){
model.addAttribute("member", member.get());
return "profile";
} else {
return "error";
}
}
@PostMapping("/register")
@ResponseBody
public void postRegister(@requestBody MemberDTO memberDTO) {
MemberDTO member = new MemberDTO();
member.setUserId(memberDTO.getUserId());
member.setName(memberDTO.getName());
member.setPassword(memberDTO.getPassword());
memberService.insertNewMember(member);
}
@PostMapping("/login")
@ResponseBody
public boolean postLogin(@RequestBody MemberDTO memberDTO) {
MemberDTO memberToCheck = new MemberDTO();
memberToCheck.setUserId(memberDTO.getUserId());
memberToCheck.setPassword(memberDTO.getPassword());
return memberService.checkMember(memberToCheck);
}
@PostMapping("/profile")
@ResponseBody
public boolean postEdit(@RequestBody MemberDTO memberDTO) {
MemberDTO member = new MemberDTO();
member.setId(membersDTO.getId());
member.setUserId(memberDTO.getUserId());
member.setName(memberDTO.getName());
member.setPassword(memberDTO.getPassword());
return memberService.updateProfile(member);
}
@PostMapping("/delete")
@ResponseBody
public void postDelete(@RequestBody MemberDTO memberDTO){
MemberDTO member = new MembersDTO();
member.setId(memberDTO.getId());
member.setUserId(memberDTO.getUserId());
member.setName(memberDTO.getName());
member.setPassword(memberDTO.getPassword());
memberService.deleteProfile(member);
}
}'포스코x코딩온 웹 풀스택 양성과정' 카테고리의 다른 글
| [포스코x코딩온] 웹 풀스택 과정 18주차 회고 | Spring JDBC, MyBatis (0) | 2024.04.18 |
|---|---|
| [포스코x코딩온] 웹 풀스택 과정 18주차 회고 | Spring REST API (0) | 2024.04.18 |
| [포스코x코딩온] 웹 풀스택 과정 18주차 회고 | Spring Bean (0) | 2024.04.18 |
| [포스코x코딩온] 웹 풀스택 과정 17주차 회고 | Spring (0) | 2024.04.18 |
| [포스코x코딩온] 웹 풀스택 과정 17주차 회고 | JAVA 래퍼, 제네릭, 콜렉션 (1) | 2024.04.18 |