Spring boot에서 JPA로 쿼리문을 실행하여 값을 얻는데 문제가 발생했다.
현재 필자의 상황은 User 테이블에서 PK인 userId를 이용해서 필드 now_emotion과 ad_id를 조회하고자 했다.
그리고 조회된 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() 을 오버라이딩하는 것을 항상 잊지말자!!!