개요
MyBatis로 개발을 하던 중 요즘 많은 곳에서 JPA를 사용한다는 이야기를 접하게 되었다.
결과적으로 MyBatis와 달리 생산성이 어마무시하게 늘어나는 걸 보고 본격적으로 공부하고 정리해보게 되었다.
목차
1. JPA란?
2. JPA 사용 목적
3. SpringData JPA를 이용한 간단한 CRUD
JPA란?
JPA는 자바 진영의 ORM 기술 표준이다. 아주 오래전 EJB를 사용하던 때 한 회사원이 EJB의 복잡성과 어려움에 견디지 못하고 퇴근하고 Hibernate를 만들었고 이걸 접한 JAVA에서 Hibernate 담당자들을 데려와 여러 개발자와 함께 JPA 표준을 만들었다는 이야기가 있다. 중요한건 JPA는 하나의 명세일뿐 JPA를 기반으로 Hibernate, OpenJPA, EclipseLink같은 구현체가 파생되었다.
JPA 사용 목적
생산성 - 반복적인 SQL 작업과 CRUD 작업을 개발자가 하지 않아도 됨.
유지보수 : 객체의 수정에 따른 SQL 수정 작업을 개발자가 하지 않아도 됨.
패러다임 불일치 해결 : 객체와 관계형 데이터베이스를 매핑하는 과정의 문제를 개발자가 하지 않아도 됨.
성능 : 캐싱을 지원하여 SQL이 여러번 수행되는것을 최적화 ( 무슨말인지 모르겠음 공부 필요 )
JPA를 사용한 객체 매핑시 사용 어노테이션
@Entity - 엔티티임을 정의
@Table - (name = "테이블이름) 매핑할 테이블정보를 알려줌
@id - 엔티티 클래스의 필드를 테이블의 기본키로 매핑, 사용된 필드를 식별자 필드라 함
@Column - 필드를 컬럼에 매핑, name 속성을 사용해 필드를 테이블의 NAME 컬럼에 매핑가능
Spring Data JPA 를 이용한 간단한 CRUD
FrameWork - Spring Boot
DB - MySQL
ORM - String Data JPA
접근구조
Controller -> ServiceImpl (Service Interface구현) -> Repository -> Entity
메이븐설정
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
Spring-boot-starter-web = Spring Boot 사용
Spring-boot-starter-data-jpa = Spring Data JPA 이용
mysql-connector-java = MySql 연동 위한 Connector
application.properties 설정
MySql Connection 설정
spring.datasource.url=jdbc:mysql://localhost:3306/java?serverTimezone=UTC&useUnicode=true&charaterEncoding=utf-8
spring.datasource.username=id
spring.datasource.password=password
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
Entity 구현
@Entity
public class Team {
@Id
@Column(name="seq")
private int seq;
@Column(name="user_name")
private String user_name;
@Column(name="password")
private String password;
//Getter,Setter 생략
}
@id - Primary Key 지정
@Column - DB 테이블 Column과 매핑
UserVO 구현
view에서 넘어온 데이터를 담아놓을 UserVO를 구현
Entity와는 별도로 VO객체를 구현해서 관리
public class UserVO {
private String user_name;
private String user_password;
public String getUser_name() {
return user_name;
}
public void setUser_name(String user_name) {
this.user_name = user_name;
}
public String getUser_password() {
return user_password;
}
public void setUser_password(String user_password) {
this.user_password = user_password;
}
//Getter,Setter 생략
}
Repository 구현
public interface TeamRepository extends JpaRepository<Team, Integer>{
@Modifying
@Query("UPDATE TB_USER SET user_name =:user_name,user_password=:user_password WEHRE seq = :seq")
public int updateMember(@Param("seq")int seq,@Param("user_name")String user_name,@Param("user_password")String user_password);
}
JpaRepository<T,ID>
- T 는 Repository에 적용시킬 Entity
- ID 는 @id의 Type
JpaRepository를 단순하게 상속하기만 해도 Save(),FindOne(),FindAll(),Count(),Delete()를 사용할 수 있음.
save() : 새로운 엔티티는 저장( persist )하고 이미 있는 엔티티는 수정합니다.
delete() : 엔티티 하나를 삭제합니다.
findOne() : 엔티티 하나를 조회합니다
getOne() : 엔티티가 아닌 프록시로 조회합니다.
findAll() : 모든 엔티티를 조회합니다.
Service 구현
public interface TeamService {
public void addMember(UserVO userVO);
public void deleteMember(int seq);
public void updateMember(UserVO userVO);
public UserVO getMember(int seq);
}
ServiceImpl 구현
@Service
public class TeamServiceImpl implements TeamService{
@Autowired
private TeamRepository teamRepository;
@Override
public void addMember(UserVO userVO) {
Team temTeam = new Team(userVO.getUser_name(),userVO.getUser_password());
teamRepository.save(temTeam);
}
@Override
public void updateMember(UserVO userVO) {
Team temTeam = new Team(userVO.getUser_name(),userVO.getUser_password());
teamRepository.updateMember(temTeam.getSeq(), temTeam.getUser_name(), temTeam.getUser_password());
}
@Override
public void deleteMember(int seq) {
teamRepository.deleteById(seq);
}
@Override
public UserVO getMember(int seq) {
UserVO memberInfo = new UserVO();
Team team = teamRepository.findById(seq).orElse(null);
if(team.equals(null)) {
return null;
}
memberInfo.setUser_name(team.getUser_name());
memberInfo.setUser_password(team.getUser_password());
return memberInfo;
}
}
Controller 구현
@RestController
public class UserController {
@Autowired
private TeamServiceImpl teamServiceImpl;
@RequestMapping("/user/signup")
public ResponseEntity<String> doSignup(UserVO userVO){
teamServiceImpl.addMember(userVO);
return ResponseEntity.ok("ok");
}
@RequestMapping(value="/user/{seq}",method = RequestMethod.DELETE)
public ResponseEntity<String> deleteMemeber(@PathVariable int seq){
teamServiceImpl.deleteMember(seq);
return ResponseEntity.ok("ok");
}
@RequestMapping(value="/user")
public ResponseEntity<String> updateMember(UserVO userVO){
teamServiceImpl.updateMember(userVO);
return ResponseEntity.ok("ok");
}
@RequestMapping(value="/user/{seq}",method=RequestMethod.GET)
public ResponseEntity<?> getMember(@PathVariable int seq){
UserVO userInfo = teamServiceImpl.getMember(seq);
if(userInfo == null) {
return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(null);
}
return ResponseEntity.status(HttpStatus.OK).body(userInfo);
}
}
'Spring' 카테고리의 다른 글
[JPA] 연관관계 조회 방식별(Fetch, Lazy) 성능 차이 테스트 (0) | 2023.07.25 |
---|---|
[Spring] MapStruct 사용 주의 사항 (0) | 2023.07.25 |
[Spring] Redis Template과 Redis Repository 특징과 장단점 (0) | 2023.07.24 |
[Spring] Http Status Code 제어 (0) | 2020.10.26 |
[Spring] Spring Security와 JWT 사용 (0) | 2020.09.11 |