반응형

Entity Manager 란?

  • Entity를 관리하는 역할
  • CRUD 기능과 같이 Entity와 관련된 모든 일을 처리하는 역할
  • Entity Manager는 영속성 컨텍스트에 Entity를 보관하고 관리 => Entity의 상태 변화를 감지하고 필요한 쿼리를 자동으로 수행

Entity Manager을 사용한 MySQL CRUD 예제

  • User 객체를 만들고 DB에 CRUD 하는 예제를 만들어 봄

MySQL에 DB 생성 (testdb)

spring-boot-starter-data-jpa, mysql-connector-java 라이브러리 추가

  • build.gradle에 다음 코드 추가
implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
runtimeOnly 'mysql:mysql-connector-java'

application.yml

spring:
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://localhost:3306/testdb
    username: root
    password: root1234

  jpa:
    hibernate:
      ddl-auto: create

    show-sql: true

    properties:
      hibernate:
        format_sql: true
  • spring.datasource : DB 접속 정보 설정
  • spring.jpa.hibernate.ddl-auto : 옵션 설명
  • spring.jpa.show-sql : JPA가 생성한 쿼리를 log에 출력할지 여부
  • spring.properties.hibernate.format_sql
  1. true 일때

  1. false 일때

User 객체 생성

@Data
@Entity
public class User {
    @Id @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "user_id")
    private Long id;

    private String name;
    private int age;
}
  • @Entity를 통해 DB와 매핑
    • name 속성을 통해 따로 이름을 지정해줄 수 있지만 설정하지 않으면 클래스 이름 그대로 매핑
    • @Entity 객체가 DB의 Table과 매핑됨
  • @Id는 DB에서의 Primary Key를 의미
    • @Entity 객체 안에는 @Id를 가진 변수가 존재해야 함
    • JPA는 이 어노테이션을 통해 각각의 객체를 구분
  • @GneratedValue를 통해 Id 생성 전략 설정 가능
    • Id 생성 전략에는 4가지 전략이 있음
    1. AUTO(default) : JPA가 자동으로 생성 전략 설정
    2. IDENTITY : 기본키 생성을 DB에 위임 (MySQL : AUTO_INCREMENT)
    3. SEQUENCE : DB의 Object Sequence 사용
    4. TABLE : DB에 키 생성 전용 테이블을 만들고 이를 사용하여 기본키 생성
  • @Column(name = "user_id")를 통해 User 테이블의 Id가 DB에 매핑될 때 컬럼명이 "user_id"로 매핑됨

UserRepository

  • DB와 연결되는 부분
  • EntityManager을 주입받아 사용
@Repository
@RequiredArgsConstructor
public class UserRepository {

    private final EntityManager em;

    // Create, Update
    public void save(User user) {
        em.persist(user);
    }

    // Delete
    public void remove(Long id) {
        em.remove(findById(id));
    }

    // Read
    public User findById(Long id) {
        return em.find(User.class, id);
    }

    public User findByName(String findName) {
        return em.createQuery("SELECT u FROM User u WHERE u.name = :findName", User.class)
                .setParameter("findName", findName)
                .getSingleResult();
    }

    public List<User> findAll() {
        return em.createQuery("SELECT u FROM User u", User.class)
                .getResultList();
    }
}
  • 기본적인 CRUD 기능 제공
  • 하지만 findByName, findAll과 같은 기능들은 따로 제공하지 않으므로 위와 같이 직접 JPQL을 작성해 줘야 함

UserService

  • Service는 Controller, Repository와 연결된 핵심 비지니스 로직
  • @Transactional을 통해 Service 단에 transaction을 걸어줌 (DB의 일관성을 유지하기 위해)
@Service
@Transactional
@RequiredArgsConstructor
public class UserService {

    private final UserRepository userRepository;

    // 유저 등록
    public Long save(User user) {
        userRepository.save(user);
        return user.getId();
    }

    // 유저 수정
    public Long update(Long id, String newName, int newAge) {
        User updateUser = userRepository.findById(id);
        updateUser.setName(newName);
        updateUser.setAge(newAge);

        return updateUser.getId();
    }

    // 유저 삭제
    public void remove(Long id) {
        userRepository.remove(id);
    }

    // id로 유저 검색
    public User findById(Long id) {
        return userRepository.findById(id);
    }

    // name으로 유저 검색
    public User findByName(String name) {
        return userRepository.findByName(name);
    }

    // 유저 전체 검색
    public List<User> findAll() {
        return userRepository.findAll();
    }
}
  • update 메소드를 보면 id를 통해 user을 찾아오고 변경할 이름, 나이를 set 해주고 끝남
  • 따로 추가나 수정하는 기능이 없음
  • JPA의 영속성 컨텍스트에 의해 찾아온 user가 연결되어 있기 때문에 따로 update 하는 쿼리가 없어도 DB의 값이 변경됨

UserController

@RestController
@RequestMapping("/entitymanager-example/user")
@RequiredArgsConstructor
public class UserController {

    private final UserService userService;

    @PostMapping("")
    public String create(@RequestParam String name, int age) {
        User user = new User();
        user.setName(name);
        user.setAge(age);

        Long userId = userService.save(user);
        return userId + "번 유저 등록 완료";
    }

    @PutMapping("")
    public String update(@RequestParam Long id, String name, int age) {
        Long userId = userService.update(id, name, age);
        return userId + "번 유저 수정 완료";
    }

    @DeleteMapping("")
    public String delete(@RequestParam Long id) {
        userService.remove(id);
        return id + "번 유저 삭제 완료";
    }

    @GetMapping("")
    public String read(@RequestParam @Nullable Long id, String name) {
        if(id != null) {
            return userService.findById(id).toString();
        } else {
            return userService.findByName(name).toString();
        }
    }

    @GetMapping("/all")
    public String readAll() {
        return userService.findAll().toString();
    }
}
  • REST API 적용
  • 입력을 모두 URL의 Query Parameter로 받음
  • GET /user 에서 Query Parameter로 id가 입력되면 findById, id가 입력되지 않으면 findByName 진행

결과

application을 실행하면 Table이 자동으로 생성됨

User 등록 테스트

 

User 수정 테스트

 

findById 테스트

findByName 테스트

User 삭제 테스트

User 3명 추가 후 findAll 테스트

반응형

↓ 클릭시 이동

복사했습니다!