TroubleShooting

toString() 을 재정의하는 것을 잊지말자

뭉지(moonz) 2021. 11. 23. 07:47
반응형

Spring boot에서 JPA로 쿼리문을 실행하여 값을 얻는데 문제가 발생했다.

 

현재 필자의 상황은 User 테이블에서 PK인 userId를 이용해서 필드  now_emotion과 ad_id를 조회하고자 했다.

User 테이블

 

그리고 조회된 ad_id를 출력하니 19가 아닌 

클래스명과 주소값인 com.healing4u.healing4umobileWeb.model.Advertisement@116da866 이 출력되는 것이다.

(클래스명을 출력하는 메서드는 user.getAdId().getClass() )

 

이때의 코드는 아래와 같다.

@Service
public class UserService {
    @Autowired
    private UserRepository userRepository;

    @Autowired
    private AdvertisementRepository advertisementRepository;

    // 기분과 사용자 광고 조회
    public Map<String, Integer> findEmotionAndAdId (Long userId) {
        Map<String, Integer> data = new HashMap<String, Integer>();
        User user = userRepository.findById(userId)
                .orElseThrow(() -> new IllegalArgumentException("해당하는 아이디가 없습니다."));
        Integer adId = Integer.valueOf(String.valueOf(user.getAdId()));   // com.healing4u.healing4umobileWeb.model.Advertisement@116da866

        data.put("emotion", user.getNowEmotion());
        data.put("adId", adId);
        // for loop (keySet())
        System.out.println("======해당 사용자의 emotion과 adId 조회======");
        Set<String> keySet = data.keySet();
        for (String key : keySet) {
            System.out.println(key + " : " + data.get(key));
        }
        return data;
    }
}

 

그리고 이 주소 값을 Long타입으로 변환하려하면 java.lang.NumberFormatException: For input string: 에러가 뜬다. 

 

NumberFormatException 에러는 올바르지 않은 포맷을 정수로 바꾸려할 때 발생하는 에러이다. 당연히 위의 주소값(com.healing4u.healing4umobileWeb.model.Advertisement@116da866)을 바꾸려하니 이 에러가 뜨는 수 밖에..

 

다시 본론으로 돌아와서, 왜 데이터값이 아닌 클래스타입과 주소값이 나올까?

이유는 user.getAdId()를 호출할 때 자동으로 Object 클래스의 toString()메서드가 호출되기 때문이다.

Object 클래스의 toString() 메서드에는 주소값을 출력하도록 정의되어있다.

 

그렇기 때문에 Effectice Java 3/E의 아이템 12(정리글 참고)에서 나온 것처럼,

toString()을 오버라이딩해야 하는 것이다.

해당 Advertisement 클래스에서도 toString()을 오버라이딩하여야 하는데, 

현재 서비스에서는 AdId의 값만 조회하기 때문에 나머지 멤버변수 return에 대해선 주석처리 해놓았다.

@AllArgsConstructor
@NoArgsConstructor
@Builder
@Getter
@Table(name="advertisement")
@Entity
public class Advertisement {

    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Id
    @Column(name="ad_id", nullable = false)
    private long adId;

	// .. 생략
	
    @Column(length = 200, nullable = false)
    private String src;

    @Override
    public String toString() {
/*        return "AdId : " + this.getAdId() + ", emotion : " + this.getEmotion() + 
			", season : " + this.getSeason() + ", serviceName : " + this.serviceName() + 
            ", address : " + this.getAddress() + ", detailLong : " + this.getDetailLong() + 
            ", tel : " + this.getTel() + ", kakaoMapUrl : " + this.getKakaoMapUrl() +
            ", src : " + this.getSrc();
            */
        return ""+this.getAdId();
    }
}

이렇게 했을 때 adId 칼럼의 데이터가 잘 출력되는 것을 확인할 수 있다.

 

toString() 을 오버라이딩하는 것을 항상 잊지말자!!!

 

 

관련 PR comment

반응형