kokoko121233
235
2017-12-15 00:22:31 작성 2017-12-15 00:37:10 수정됨
8
903

jpa findyBy.. 사용 관련


안녕하세요 spring boot + jpa 를 이용하여 rest 서버를 만들어보고 있는데 문제가 있습니다.

Member 클래스는 회원을 의미하며 Schedule 클래스는 일정을 의미합니다.

회원 1, 2 ... 같이 생성되며 회원이 여러개의 일정을 만들 수 있습니다.

그리고 구현하려다가 막힌 상황이

회원1이 생성한 일정 리스트를 출력하기위해 아래와 같은 코드를 작성했습니다.

그런데 findByMember를 사용할 때 에러가 발생합니다.

class Member { 

    .. field
    .. constructor, getter, setter

}

class Schedule {
    .. field

    @ManyToOne
    Member member

    .. constructor, getter, setter
} public interface ScheduleRepository extends CrudRepository<Schedule, Long> { List<Schedule> findByMember(Member member); } public class ScheduleServceImpl implements ScheduleService{ @Override public List<Schedule> findByMember(Member member) { return scheduleRepository.findByMember(member); } }


postman raw 값을

{

     "member":{

         "id":1

    }

}

로 post 전달하면 org.hibernate.TransientObjectException: object references an unsaved transient instance - save the transient instance before flushing 라는 에러가 출력됩니다.

검색해보니 저장되지 않은 값을 사용하여 나오는 에러로 ManyToOne(cascade=CascadeType.ALL) 을 추가해야된다고 하지만 추가하면 detected entity passed to persist 라고 에러가 출력됩니다.

@RequestMapping(value = "/rest/v1/schedules_by_member", method = RequestMethod.POST)
	public ApiResult<List<Schedule>> findByMember(@RequestBody Member member) {
		try {
			return scheduleService.findByMember(member);
		} catch ( RuntimeException e ) {
			return new ApiResult<>(e);
		}
	}

위와 같은 raw값을 던져주면 회원 pk가 매핑되어서 회원에 해당하는 일정 리스트를 가져올 줄 알았는데

raw값이 잘못되어서 새로운 객체를 추가하려는 시도로 인해 에러가 발생한게 맞는건가요 ?  


최종적으로

postman을 통해서 회원과 일정  생성, 조회, 삭제, 수정은 동작하는 것을 확인했지만 

findBy .. 를 이용한 조회가 잘 되지 않습니다.

"특정 회원이 생성한 일정 리스트"를 뽑아내려면 어떻게 해야 하나요?

0
0
  • 답변 8

  • 스타
    3k
    2017-12-15 09:25:40
    scheduleRepository.findByMember(member);

    jpa에서 써보지 못한 참신한 방법이네요.

    실제로 저게 동작하나요?

    0
  • 도각도각
    3k
    2017-12-15 09:38:34 작성 2017-12-15 09:39:17 수정됨

    ScheduleRepository에 던져줄 Member 오브젝트가 영속된 객체가 아니라서 그래요.

    postman으로 던진 id를 가지고 먼저 memberRepository에서 member를 찾고, 그리고 그걸 던져줘야죠.


    Member member = memberRepository.findOne(member.getId());
    
    scheduleRepository.findByMember(member);
    


    1
  • kokoko121233
    235
    2017-12-15 10:49:43

    스타

    답변감사합니다. 도각도각님이 알려주신 방법대로 제가 원하는 데이터는 뽑아왔는데요

    참신한 방법이라고 하셨는데 보통 어떻게 데이터를 가져오는지 알 수 있을까요?

    stackoverflow, springboot 공식 가이드에서 찾아본 바로는

    1. query를 직접 사용 2. ManyToOne과 OneToMany를 써서 OneToMany에 매핑된 List객체 가져오기

    3. 제가 본문에쓴 방식 이렇게를 봐왔는데 이 중에 쓰시는 방법이 있나요?

    0
  • kokoko121233
    235
    2017-12-15 11:12:01

    도각도각 

    답변감사합니다

    id 값을 받아서 그 회원 객체가져온 다음에 일정 리스트를 가져왔습니다.

    혹시 이렇게 많이 안쓰는 방식인가요? 주로 어떻게 사용하시나요?

    0
  • 도각도각
    3k
    2017-12-15 11:18:00

    저도.. 걍 책보고..

    플젝에 몇번 적용해본거라..


    그렇게 쓰는게 좋을거 같은데요..


    그리고..


    scheduleRepository.findByMemberId(id);


    이렇게 해도 될거예요.

    Schedule 엔티티에 Member가 ManyToOne으로 연결되 있다면..

    0
  • kokoko121233
    235
    2017-12-15 11:37:38

    도각도각

    findByMemberId 로도 잘 가져오네요 감사합니다.


    본문에서 바보같이 전체가 member인데 member안에서 member 넣어서 잘못된거였네요..

    {

         "member":{

             "id":1

        }

    }


    {

        "id":1

    }

    위와 같이 하니까 재대로 가져오네요.

    여러가지 정보 감사합니다.

    0
  • 도각도각
    3k
    2017-12-15 11:46:13

    저도 한지가 좀 되서..

    좀 오락가락하긴 했네요.


    컨트롤러에서 바로 Entity를 받으면 바로 영속 되거든요.


    그래서 안되나.. 했는데.. 그게 잘못이었네요..


    그리고 현업에서는.. 컨트롤러에서 바로 Entity로 영속 받는건 지양하는 편이라고 알고 있습니다.


    그래서 동일하게 생긴 DTO를 추가해서 사용하죠.. @Transident이던가.. 이게 무분별하게 붙는다고 해서..


    그래서 거의 내용이 동일한 오브젝트를 매핑해서 사용하다보니.. http://modelmapper.org/getting-started/ 를 많이 사용합니다.


    스프링의 BeansUtils 이던가.. 그거랑 비슷한 기능이 있어요.



    0
  • kokoko121233
    235
    2017-12-15 13:15:10

    참고하겠습니다 감사합니다

    0
  • 로그인을 하시면 답변을 등록할 수 있습니다.