@GeneratedValue는 @Id와 함께 쓰는 어노테이션이며 auto_increment와 같은 자동 생성 전략을 결정합니다.

 

JPA에서 복합키를 구현하기 위한 IdClass와 EmbeddedId를 복습하던 도중 @GeneratedValue도 함께 사용해보았습니다.

 

IdClass 사용

우선 Primary Key를 위한 UserId 클래스를 생성합니다.

 

그리고 User Entity를 생성합니다.

클래스선언 위에 @IdClass를 사용해줍니다.

 

이제 DB가 만들어지는지 실행을 해볼까요?

음~ 잘 만들어졌네요!

 

이제 User table에 데이터를 넣어봅시다.

데이터를 넣기 위해 Test를 작성하였습니다.

User 테이블은 auto_increment이므로 id는 1이됩니다.

 

하지만 에러가 떠버립니다.

 

 

EmbeddedId 사용

다음은 Embeddable 입니다.

우선 Primary Key를 위한 UserId 클래스를 생성합니다.

 

그리고 User Entity입니다.

PK 위에 @EmbeddedId를 사용합니다.

 

이번에는 auto_increment조차 생기지 않습니다.

다른 방법들도 시도해보았으나 모두 실패했습니다 ㅠ

 

 

결론

사실 제가 코드를 잘못 짠줄 알고 구글링을 여러번 시도했습니다.

https://infondgndg91.blogspot.com/2019/11/hibernate-composite-identifiers.html

 

Hibernate - Composite Identifiers @EmbeddedId @IdClass With @GeneratedValue is impossible

ndgndg91

infondgndg91.blogspot.com

그러던 중 이 블로그를 발견하였고, 이분도 어떤 커뮤니티에서 물어보셨던 것인지

@GeneratedValue를 @IdClass, @EmbeddedId와 함께 사용하는 것이 불가능하다는 답변을 받은것 같습니다.

 

앞으로 주의해서 사용해야 할 것 같습니다.

복합 키를 구현하기 위해서 두 가지 방법을 이용할 수 있습니다.

  1. IdClass 어노테이션 이용
  2. Embeddable 어노테이션 이용

IdClass 어노테이션은 https://emoney96.tistory.com/249 에 정리가 되어있으며,

이 글에서는 Embeddable 어노테이션 적용'만' 다룰 것입니다.

 

우선 @Embeddable을 적용할 Id전용 클래스를 생성합니다.

@IdClass와 다른 점은 @Embeddable을 붙인다는 점밖에 없습니다.

FollowId 클래스를 생성합니다.

 

Follow Entity 클래스에서 EmbeddedId 어노테이션을 적용한 FollowId 클래스 변수를 선언합니다.

 

그 다음 @MapsId 어노테이션을 이용하여 FollowId의 각 변수들과 매핑시켜주시면 됩니다.

여기서 주의할 점은

User 클래스에서 작성한 mappedBy의 이름과 Follow의 변수명이 같아야하고,

Follow 클래스에서 작성한 MapsId의 value와 FollowId의 변수명이 같아야합니다.

 

FollowId의 변수 fan을 fan1으로 변경했을 경우에도 실행은 됩니다.

하지만 table은 의도한대로 만들어지지 않는 것을 알 수 있습니다.

위의 결과는 fan1은 외래 키가 아니라 follow table의 순수 컬럼이자 기본 키가 되는 것이고,

fan은 외래 키가 맞지만 FollowId 클래스에 매핑할 "fan" 변수가 없어서 기본 키가 되지 못한 상황입니다.

 

 

복합 키를 구현하기 위해 @Id 어노테이션을 두개 사용했더니 에러가 발생했습니다 ㅠ

 

구글링 하다가 @Id를 한 클래스에 두개를 쓰면 안된다는 것을 알게되었고 복합 키 구현 방법을 찾아다녔습니다.

 

일단 복합 키 구현에는 두 가지 방법이 있습니다.

  1. IdClass 어노테이션 이용
  2. Embeddable 어노테이션 이용

저는 이 글에서 IdClass 어노테이션 적용'만' 다룰 것입니다.

(Embeddable은 몰라서 그래요.. 공부해서 포스팅 해보겠습니다...)

 

 

우선 @IdClass를 적용하기 위해 Id전용 클래스를 생성합니다.

저는 FollowId 클래스를 생성하였습니다.

 

그 다음 Entity 클래스에서 IdClass 어노테이션을 추가해서 작성해둔 Id전용 클래스를 적어두면 끝입니다!

 

여기서 주의할 점은

User 클래스에서 작성한 mappedBy의 이름과 Follow의 변수명, FollowId의 변수명

이 세가지가 모두 같아야합니다!

'Spring' 카테고리의 다른 글

Entity @GeneratedValue with @IdClass, @EmbeddedId  (2) 2021.08.06
Entity @Embeddable을 이용한 복합 키 구현  (0) 2021.08.01
Spring @RequestParam String[] 문제  (0) 2021.07.24
Spring JPA Pagenation  (0) 2021.07.24
Spring Optional.isPresent()  (0) 2021.07.15

Controller에서 Query String을 받아오기 위해 @RequestParam을 사용하였습니다.

@RequestParam을 이용하여 Sort객체 정보를 담기 위해 type은 String[]으로 지정하였습니다.

그럼 대략 이런식으로 쓸 수 있습니다.

 

그리고 스웨거를 이용하여 테스트를 합니다.

 

위에서부터 순서대로 sort.length, sort[0], sort[1] 입니다.

 

그럼 여기서 정렬조건을 하나만 넣어볼까요?

정렬조건을 title,desc으로 보냅니다.

 

??????? 갑자기 "title,desc"로 받아온게 아니라 split(",")으로 나눈것처럼 "title", "desc"로 받아왔습니다.

스프링에서는 ","로 나열된 String을 배열로 인식하여 자동으로 나눠준다고합니다.

하지만 저는 지금 상황에서 원하지 않습니다.. "title,desc" 이렇게 그대로 들어오기를 원합니다.

 

 

https://stackoverflow.com/questions/23695817/requestparam-array-mapping-issues/55251064

 

@RequestParam array mapping issues

I'm doing a REST service with Spring MVC framework. I have a method: @RequestMapping("/rest/{tableName}", method = RequestMethod.GET) public @ResponseBody CustomObject query( @PathVariable("

stackoverflow.com

다행히도 친구가 찾아준 이 링크에서 저와 같은 상황에 놓인 사람이 있었나봅니다.

 

밑의 댓글에서 준 코드를 적용하고싶은 컨트롤러에 붙이니 해결되었습니다.

이렇게 이 initBinder 메소드를 작성하는 것만으로 해결이 되었습니다.

 

아 편안하네요

'Spring' 카테고리의 다른 글

Entity @Embeddable을 이용한 복합 키 구현  (0) 2021.08.01
Entity @IdClass를 이용한 복합 키 구현  (0) 2021.07.29
Spring JPA Pagenation  (0) 2021.07.24
Spring Optional.isPresent()  (0) 2021.07.15
Spring 기본 세팅 (STS)  (0) 2021.06.12

말 그대로 페이징, 데이터를 페이지 단위로 나눠서 보여주는 작업입니다.

이를 위해 JPA에서는 페이지 정보와 정렬 기준으로 페이징 처리를 하며 PageRequest, Pageable, Sort 객제를 사용합니다.

1
2
3
4
@Repository
public interface ConferenceRepository extends JpaRepository<Conference, Long> {
    Page<Conference> findAll(Pageable pageable);
}
cs

Repository 구성입니다.

return type을 Page 객체로 감싸줍니다.

Service에서 PageRequest 객체를 넘겨주면 Repository에서 Pageable 객체로 받습니다.

Pageable 객체에는 페이징 정보와 정렬 기준을 모두 포함하므로 전달받는 파라미터에 반드시 포함되어야합니다.

 

1
2
3
4
5
6
7
8
9
10
@Service
public class ConferenceServiceImpl implements ConferenceService {
    @Override
    public ConferenceFindAllGetRes findAllConference(int page, int size) {
        Sort sorts = Sort.by(Sort.Direction.DESC, "id");
        PageRequest pageRequest = PageRequest.of(page, size, sorts);
    
        return ConferenceFindAllGetRes.of(conferenceRepository.findAll(pageRequest), pageRequest, sorts);
    }
}
cs

Repository에서는 페이징 정보를 Pageable로 받지만 Service에서 호출 시 보낼 페이징 정보는 PageRequest 객체입니다.

딱 Request만 봐도 요청 잘하게 생겼죠?

PageRequest.of(page, size, sorts);

page: 현재 페이지 (코드에서 첫 페이지는 0입니다.)

size: 페이지에서 출력할 데이터의 갯수

sorts: 정렬기준, 방법 (ex. id 기준 asc or desc)

 

그럼 이런식으로 정렬기준에 맞게 출력이 됩니다!

이거를 이제 findByTitle이나 findByConferenceCategoryId와 같은 메소드에도 적용할 수 있습니다

스프링에서 Optional 객체에 get() 메소드를 사용하여 안에 있는 객체를 가져올 수 있습니다.

하지만 비어있는 Optional 객체를 대상으로 get() 메소드를 사용할 경우 에러가 발생합니다.

 

따라서 isPresent()객체를 사용하여 객체 존재여부를 확인 후에 가져오도록 해야합니다.

 

 

ex)

1
User user = userRepositorySupport.findUserByUserId(userId).get();
cs

=> findUserByUserId에서 객체를 못 가져왔을 시 에러 발생

 

1
2
3
4
5
6
Optional<User> user = userRepositorySupport.findUserByUserId(userId);
        
if(user.isPresent())
    return user.get();
else
    return null;
cs

=> isPresent() 메소드로 사전에 확인함으로 문제 해결

'Spring' 카테고리의 다른 글

Entity @Embeddable을 이용한 복합 키 구현  (0) 2021.08.01
Entity @IdClass를 이용한 복합 키 구현  (0) 2021.07.29
Spring @RequestParam String[] 문제  (0) 2021.07.24
Spring JPA Pagenation  (0) 2021.07.24
Spring 기본 세팅 (STS)  (0) 2021.06.12

Spring Basic Setting

스프링을 배우고나서 복습을 반복적으로 하고있지만 까먹거나 헷갈리는 부분이 많아서 정리를 하려고 합니다..

저는 우선 개발 툴로는 STS(Spring Tool Suite)를 사용하였고, Gradle이 아닌 Maven를 사용하였습니다.

위와 같이 Spring Legacy Project를 생성하면 밑에있는 창이 뜹니다.

 

프로젝트 이름을 적어주시고, Templates는 Spring MVC Project를 선택하여 Next를 누르고,

 

패키지 이름을 작성한 후에 Finish를 누릅니다.

여기서 패키지 이름은 최소 3단계로 작성해주시는 것이 좋습니다.

 

그럼 이렇게 프로젝트가 생성되는데 초기 설정을 위해 pom.xml에 들어갑니다.

들어가면 무슨 설정이 많이 있는데 이것만 고쳐줍니다.

properties 태그에 있는 java-version과 springframework-version을 본인에 맞는 버전으로 변경합니다.

저는 1.8과 5.2.6으로 변경하였습니다.

 

그리고 plugin 태그에 있는 이 부분도 본인의 java-version으로 변경해줍니다.

 

나중에 코딩을 하는 도중에 mysql이나 mybatis처럼 pom.xml에 의존성을 추가해야할 일이 분명 있습니다.

https://mvnrepository.com/

여기에서 적용할 의존성을 검색하여 pom.xml에 추가합니다.

스프링에서 세팅은 정말 중요한것 같습니다..

 

 

이제 pom.xml 내용을 변경하였으니 maven-update를 해주어야 합니다.

해당 프로젝트에 우클릭을 하여 Maven→Update Project...를 누릅니다. (단축키로는 Alt + F5입니다.)

그러면 현재 자신이 작업중인 프로젝트가 체크되어 있을텐데 그냥 OK만 눌러주시면 됩니다.

 

이제 기본적인 설정은 끝났고 실행을 해봅시다!

처음 프로젝트를 만들게 되면 HomeController와 home.jsp가 생성되어 있습니다. (필요에 따라 지워도 상관없습니다.)

 

 

스프링 실행 방법은

MySpring 프로젝트 우클릭 → Run As → Run on Server을 누르면 톰캣이 돌아가면서 실행됩니다.

그러면 이렇게 기본 페이지가 뜹니다!

 

 

 

만약 이런 에러를 보셨다면 경로가 톰캣 정보를 들어가셔서 경로 확인을 해야합니다.

 

여기서 톰캣을 더블클릭해서 들어가면

이런 창이 뜨게 되는데 Modules 탭을 누릅니다.

그럼 이렇게 Path가 겹치는 경우가 있습니다. 이런 경우에는 Edit을 눌러서 경로를 변경해주시거나 Remove로 제거해주시면 됩니다.

 

'Spring' 카테고리의 다른 글

Entity @Embeddable을 이용한 복합 키 구현  (0) 2021.08.01
Entity @IdClass를 이용한 복합 키 구현  (0) 2021.07.29
Spring @RequestParam String[] 문제  (0) 2021.07.24
Spring JPA Pagenation  (0) 2021.07.24
Spring Optional.isPresent()  (0) 2021.07.15

+ Recent posts