Spring/spring_old

11. JPA 사용을 위한 코딩

slow333 2023. 1. 27. 13:09

우선 db 연계를 확인... 나는 pc에 mysql을 설치하고 workbench로 db 확인

intellej ultimate에서는 application.yml 설정하면 알아서 연동할 db에 대한 연동을 확인 해줌.. 편함

1. 기존의 map 저장을 DB로 변경하기 위해 기존 mapstore를 비활성화

repository에 새로운 패키지 생성(jpo)

실제 jpa에서 사용할 entity 객체로 이 것만 있어도 db 테이블이 생성됨..

@Entity
@Getter
@Setter
@NoArgsConstructor
@Table(name = "club") // db table의 이름을 지정 가능 아니면 class 이름으로 생성
public class ClubJpo {

  @Id //db에서 사용할 key 값 , 반드시 있어야 함.
  private String id;
  private String name;
  private String intro;
  private String foundationTime;

  public ClubJpo(Club club) {
//    this.id = club.getId();
//    this.name = club.getName();
//    this.intro = club.getIntro();
//    this.foundationTime = club.getFoundationTime();
    BeanUtils.copyProperties(club, this); // 위와 같은 내용.
  }

  public Club toDomain(){ // jpo 객체를 domain(java) 객체로 만들어 줌
    Club club = new Club(this.name, this.intro);
    club.setId(this.id);
    club.setFoundationTime(this.foundationTime);
    return club;
  }
}

2. spring data jpa 인터페이스 생성

jpa entity manager를 사용하지 않고 spring data jpa를 사용해서 entity manage 자체도 spring에 맏김

JpaRepository를 상속받아서 사용할 인터페이스를 구현하고

이전에 정의한 java interface(ClubStore)를 실제 구현하는 구현체인 ClubJpaStore에서는 위에서 정의한 인터페이스를 bean 객체로 주입받아서 사용하면 JpaRepository에서 구현한 기본적인 CRUD를 사용 가능함(좀 복잡하내)

(JpaRepository -> PagingAndSortingRepository -> CrudRpository 순으로 상속함 ,CrudRepository에는 기본적인 CRUD가 정의되어 있음)

결국 spring data jpa를 사용하는 것은 내가 db 제어를 위해 인터페이스 구현체를 만들 때 

내가 db 제어를 위한 방식을 정의하지 않고 이미 spring에서 구현해 놓은 방식을 상속 받아서 사용하는 것

public interface ClubRepository extends JpaRepository<ClubJpo, String> {

}

사용자 정의 method를 정의하고 싶으면... 아래 참조(메서드명 내 키워드)

예 : 이름이 포함된 모든 사용자를 찾고 싶으면

findByNameLike ==> 반대는 findByNameNotLike 

정확하게 일치하는 것만 찾고 싶으면 : findByName

public interface ClubRepository extends JpaRepository<ClubJpo, String> {
  List<ClubJpo> findAllByName(String name);
  List<ClubJpo> findByNameLike(String name);
}

3. 인터페이스 구현체 생성(ClubJpaStore)

mapstore에서와 같이 사용자 생성 interface(공용)을 implements하고

ClubRepository를 bean으로 부터 받아서 사용함

  - 이 인터페이스는 결국 JpaRepository를 상속 받았으므로 Spring data jpa에서 제공하는 공용 method를 사용할 수 있음

  - ClubJpaStore는 ClubRepository를 Spring으로 부터 DI 받음 

    ==> ClubRepository --> JpaRepository  -> PagingAndSortingRepository -> CrudRpository

 

@Repository
public class ClubJpaStore implements ClubStore {

  private ClubRepository clubRepository;

  public ClubJpaStore(ClubRepository clubRepository) {
    this.clubRepository = clubRepository;
  }

  @Override
  public String create(Club club) {
    clubRepository.save(new ClubJpo(club));
    return club.getId();
  }

  @Override
  public List<Club> findByName(String clubName) {
    List<ClubJpo> clubs = clubRepository.findAllByName(clubName);
    return clubs.stream().map(ClubJpo::toDomain).collect(Collectors.toList());
  }

  @Override
  public Optional<Club> findById(String clubId) {
    Optional<ClubJpo> clubJpo = clubRepository.findById(clubId);
    if (clubJpo.isEmpty()) {
      throw new IllegalStateException("없는 id 입니다");
    }
    return Optional.ofNullable(clubJpo.get().toDomain());
  }

  @Override
  public List<Club> findByNameContaining(String clubName) {
    List<ClubJpo> clubs = clubRepository.findByNameLike(clubName);
    return clubs
    	.stream() // stream으로 변환하고
        .map(ClubJpo::toDomain)  // jpo 객체를 club(java class) 객체로 변환, Stream<Club>
        .collect(Collectors.toList()); // List로 반환
  }

  @Override
  public List<Club> findAll() {

    return clubRepository
            .findAll() // Jpo객체를 찾아서, List<ClubJpo>
            .stream() // stream으로 변환하고, Stream<ClubJpo>
            .map(ClubJpo::toDomain) //Stream<Club>
            .collect(Collectors.toList()); 
  }

  @Override
  public void update(Club club) { // 같은 값이면 업데이트
    clubRepository.save(new ClubJpo(club));
  }

  @Override
  public void delete(String clubId) {
    clubRepository.deleteById(clubId);
  }

  @Override
  public boolean exists(String clubId) {
    return clubRepository.existsById(clubId);
  }
}

전체적으로 JPA를 통해 DB에 저장, 수정, 삭제, 조회 등을 구현하였으나

세부적인 기술 사항은 아주 많이 공부해야 하는 사항으로... 

시간이 있으면 아래 링크로 가서 좀더....

https://docs.spring.io/spring-data/jpa/docs/current/reference/html/#repositories.query-methods.details

 

Spring Data JPA - Reference Documentation

Example 119. Using @Transactional at query methods @Transactional(readOnly = true) interface UserRepository extends JpaRepository { List findByLastname(String lastname); @Modifying @Transactional @Query("delete from User u where u.active = false") void del

docs.spring.io

메서드명 내 키워드

https://kim-oriental.tistory.com/34

 

[JPA] Spring Data JPA - Query Methods (쿼리 메서드)

안녕하세요, Spring Data JPA의 쿼리를 생성하는 기능 중 한 개인 메서드명을 규칙에 맞게 작성을 하면, 자동으로 쿼리가 생성되는 Query Methods (쿼리 메서드) 기능에 대해서 알아보겠습니다. 아주 복

kim-oriental.tistory.com

메서드명 By 뒤에 작성되는 키워드로 SQL의 Where절 내 명령어와 같은 역할입니다. 아래 키워드 표는 스프링 공식 도큐먼트에 있는 내용입니다. 더 상세한 내용은 아래 공식문서를 참조하시면 됩니다.

참조 : https://docs.spring.io/spring-data/jpa/docs/current/reference/html/#repositories.query-methods

 

Spring Data JPA - Reference Documentation

Example 119. Using @Transactional at query methods @Transactional(readOnly = true) interface UserRepository extends JpaRepository { List findByLastname(String lastname); @Modifying @Transactional @Query("delete from User u where u.active = false") void del

docs.spring.io

키워드 샘플 JPQL
Distinct findDistinctByLastnameAndFirstname select distinct …​ where x.lastname = ?1 and x.firstname = ?2
And findByLastnameAndFirstname … where x.lastname = ?1 and x.firstname = ?2
Or findByLastnameOrFirstname … where x.lastname = ?1 or x.firstname = ?2
Is, Equals findByFirstname,findByFirstnameIs,findByFirstnameEquals … where x.firstname = ?1
Between findByStartDateBetween … where x.startDate between ?1 and ?2
LessThan findByAgeLessThan … where x.age < ?1
LessThanEqual findByAgeLessThanEqual … where x.age <= ?1
GreaterThan findByAgeGreaterThan … where x.age > ?1
GreaterThanEqual findByAgeGreaterThanEqual … where x.age >= ?1
After findByStartDateAfter … where x.startDate > ?1
Before findByStartDateBefore … where x.startDate < ?1
IsNull, Null findByAge(Is)Null … where x.age is null
IsNotNull, NotNull findByAge(Is)NotNull … where x.age not null
Like findByFirstnameLike … where x.firstname like ?1
NotLike findByFirstnameNotLike … where x.firstname not like ?1
StartingWith findByFirstnameStartingWith … where x.firstname like ?1 (parameter bound with appended %)
EndingWith findByFirstnameEndingWith … where x.firstname like ?1 (parameter bound with prepended %)
Containing findByFirstnameContaining … where x.firstname like ?1 (parameter bound wrapped in %)
OrderBy findByAgeOrderByLastnameDesc … where x.age = ?1 order by x.lastname desc
Not findByLastnameNot … where x.lastname <> ?1
In findByAgeIn(Collection<Age> ages) … where x.age in ?1
NotIn findByAgeNotIn(Collection<Age> ages) … where x.age not in ?1
TRUE findByActiveTrue() … where x.active = true
FALSE findByActiveFalse() … where x.active = false
IgnoreCase findByFirstnameIgnoreCase … where UPPER(x.firstname) = UPPER(?1)

 

 

'Spring > spring_old' 카테고리의 다른 글

spring boot basic  (0) 2023.05.12
10. JPA 구현을 위한 환경 구성  (0) 2023.01.26
09. DB 연계-JPA  (0) 2023.01.26
08. MVC Controller 생성  (4) 2023.01.26
05. Spring Cloud Config  (0) 2023.01.25