[Spring-Boot] JPA에서 update 쿼리 사용시, xxx is not mapped 에러 발생시 대처방법

이것 또한 이상한 에러다.

분명 아래처럼 User.java 를 잘 설정했다.

package com.izect.fiamm.data.domain;

import javax.persistence.*;
import javax.persistence.Entity;
import java.io.Serializable;

@Entity
@Table(name="user")
public class User implements Serializable{

	@Id
	@GeneratedValue(strategy = GenerationType.AUTO)
	private Long seq;

	@Column(nullable = false)
	private String userId;
	@Column(nullable = false)
	private String passwd;
	@Column
	private int grade;
	@Column(nullable = false)
	private String userName;
	@Column
	private int errCnt;

	// Getter and Setter
	public String getUserId() {
		return userId;
	}
	public void setUserId(String userId) {
		this.userId = userId;
	}
	public String getPasswd() {
		return passwd;
	}
	public void setPasswd(String passwd) {
		this.passwd = passwd;
	}
	public int getErrCnt() {
		return errCnt;
	}
	public void setErrCnt(int errCnt) {
		this.errCnt = errCnt;
	}

}

그리고 UserRepository.java 에서

public interface UserRepository extends JpaRepository<User, Long> {
    User findByUserId(String userId);

    int countByUserIdAndPasswd(String userId, String passwd);

    @Modifying
    @Query("UPDATE user u SET u.errCnt = u.errCnt + 1 WHERE u.userId = :userId")
    void passwdFail(@Param("userId") String userId);

    @Modifying
    @Query("UPDATE user u SET u.errCnt = 0, u.lastConnDate = CURRENT_DATE WHERE u.userId = :userId")
    void initFail(@Param("userId") String userId);

}

위처럼 하는데 업데이트 쿼리에서 막힌다.

work.data.jpa.repository.query.SimpleJpaQuery.validateQuery(SimpleJpaQuery.java:86)
	... 60 more
Caused by: org.hibernate.hql.internal.ast.QuerySyntaxException: user is not mapped [UPDATE user u SET u.errCnt = 0, u.lastConnDate = CURRENT_DATE WHERE u.userId = :userId]
	at org.hibernate.hql.internal.ast.QuerySyntaxException.generateQueryException(QuerySyntaxException.java:96)
	at org.hibernate.QueryException.wrapWithQueryString(QueryException.java:120)
	at org.hibernate.hql.internal.ast.QueryTranslatorImpl.doCompile(QueryTranslatorImpl.java:234)
	at org.hibernate.hql.internal.ast.QueryTranslatorImpl.compile(QueryTranslatorImpl.java:158)
	at org.hibernate.engine.query.spi.HQLQueryPlan.<init>(HQLQueryPlan.java:131)
	at org.hibernate.engine.query.spi.HQLQueryPlan.<init>(HQLQueryPlan.java:93)
	at org.hibernate.engine.query.spi.QueryPlanCache.getHQLQueryPlan(QueryPlanCache.java:167)
	at org.hibernate.internal.AbstractSessionImpl.getHQLQueryPlan(AbstractSessionImpl.java:301)
	at org.hibernate.internal.AbstractSessionImpl.createQuery(AbstractSessionImpl.java:236)
	at org.hibernate.internal.SessionImpl.createQuery(SessionImpl.java:1836)
	at org.hibernate.jpa.spi.AbstractEntityManagerImpl.createQuery(AbstractEntityManagerImpl.java:328)
	... 67 more
Caused by: org.hibernate.hql.internal.ast.QuerySyntaxException: user is not mapped
	at org.hibernate.hql.internal.ast.util.SessionFactoryHelper.requireClassPersister(SessionFactoryHelper.java:189)
	at org.hibernate.hql.internal.ast.tree.FromElementFactory.addFromElement(FromElementFactory.java:109)
	at org.hibernate.hql.internal.ast.tree.FromClause.addFromElement(FromClause.java:95)
	at org.hibernate.hql.internal.ast.HqlSqlWalker.createFromElement(HqlSqlWalker.java:338)
	at org.hibernate.hql.internal.antlr.HqlSqlBaseWalker.fromElement(HqlSqlBaseWalker.java:3678)
	at org.hibernate.hql.internal.antlr.HqlSqlBaseWalker.fromElementList(HqlSqlBaseWalker.java:3567)
	at org.hibernate.hql.internal.antlr.HqlSqlBaseWalker.fromClause(HqlSqlBaseWalker.java:708)
	at org.hibernate.hql.internal.antlr.HqlSqlBaseWalker.updateStatement(HqlSqlBaseWalker.java:365)
	at org.hibernate.hql.internal.antlr.HqlSqlBaseWalker.statement(HqlSqlBaseWalker.java:257)
	at org.hibernate.hql.internal.ast.QueryTranslatorImpl.analyze(QueryTranslatorImpl.java:278)
	at org.hibernate.hql.internal.ast.QueryTranslatorImpl.doCompile(QueryTranslatorImpl.java:206)
	... 75 more

이게 뭔 에러랴.. 분명 테이블은 user가 맞는데..

그러다 인터넷을 뒤져보니 대소문자에 주의하란다. 스텍오버플로 글(http://stackoverflow.com/questions/8230309/jpa-mapping-querysyntaxexception-foobar-is-not-mapped) 을 보니 명쾌한 답변이 있다.

쿼리에서 테이블 명을 쓸 때에는 해당 테이블과 맵핑된 도메인의 클래스 명을 사용하라고.

무슨말인고 하니, 내 user테이블과 맵핑된 클래스(@Table(name="user") 와 맵핑된) 는 User.java 이고, 클래스 명은 User이다.

즉, 나는 update문을 쓸 때에 update user 가 아닌 update User 를 써야한다는 것이다. 

내참.. 별것도 아닌 것 같은데 한참을 헤맸다 정말.. 그래도 간만에 삽질하고 시원한 느낌을 받음 🙂

 

(참고로 JpaRepository를 상속 받으면 findByXX같은 것을 쓸 수 있더라.. 좋다.. 자세한건 Y2K 님 블로그 참조)