프로젝트/텀블벅 클론 코딩

[Trouble Shooting] - 좋아요 Repository 실행 오류

zangsu_ 2023. 5. 19. 18:00

좋아요 기능을 구현하기 위한 좋아요 모델 Like를 다음과 같이 구현하였다.

@Entity
@Table(name = "LIKE")
@Data
@NoArgsConstructor
public class Like {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "ID")
    long likeId;

    @ManyToOne
    @JoinColumn(name = "USER_IDX")
    User user;

    @ManyToOne
    @JoinColumn(name = "PROJECT_ID")
    Project project;
}

User index와 Project Id값을 각각 다대일 연관관개로 매핑하여 가지고 있는 테이블이다.

 

아래는 EntityManager를 이용해 DB에 직접적으로 접근하는 Repository 코드의 일부이다.

@Repository
public class LikeRepository {

    @PersistenceContext
    EntityManager em;

    public long save(User user, Project project){
        Like like = new Like();
        like.setUser(user);
        like.setProject(project);

        em.persist(like);

        return like.getLikeId();
    }

    //...//
}

 

LikeRepository의 동작을 확인하기 위한 테스트 코드를 작성 후 실행하였다.

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = "classpath:appConfig.xml")
public class LikeRepositoryTest {

    @Autowired LikeRepository likeRepository;
    @Autowired UserRepository userRepository;
    @Autowired ProjectRepository projectRepository;

    User basicUser;
    Project basicProject;

    @Test
    @Transactional
    public void 좋아요() throws Exception{
        //given
        make_basic_data();

        //when
        long likeId = likeRepository.save(basicUser, basicProject);

        //then
        Assertions.assertThat(likeRepository.findById(likeId).getUser()).isEqualTo(basicUser);
        Assertions.assertThat(likeRepository.findById(likeId).getProject()).isEqualTo(basicProject);
    }

	//...//
    
    @Transactional
    public void make_basic_data(){

        basicUser = new User();
        //== basicUser 값 설정 ==//
        userRepository.save(basicUser);

        basicProject = new Project();
        //== basicProject 필드 값 설정 ==//
        projectRepository.save(basicProject);
    }
}

 

좋아요() 메서드의 실행 결과 다음의 오류 메시지를 확인할 수 있었다.

...
14:57:43.558 [main] DEBUG org.mariadb.jdbc.client.impl.StandardClient -- execute query: insert into LIKE (PROJECT_ID, USER_IDX) values (?, ?)
14:57:43.586 [main] WARN org.mariadb.jdbc.message.server.ErrorPacket -- Error: 1064-42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'LIKE (PROJECT_ID, USER_IDX) values (2, 2)' at line 1
14:57:43.587 [main] DEBUG org.hibernate.engine.jdbc.spi.SqlExceptionHelper -- could not execute statement [n/a]
java.sql.SQLSyntaxErrorException: (conn=2813) You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'LIKE (PROJECT_ID, USER_IDX) values (2, 2)' at line 1
	at org.mariadb.jdbc.export.ExceptionFactory.createException(ExceptionFactory.java:282)
	at org.mariadb.jdbc.export.ExceptionFactory.create(ExceptionFactory.java:370)
	...
	at com.example.tumblbugclone.repository.LikeRepository.save(LikeRepository.java:24)
    ...
	at com.example.tumblbugclone.repository.LikeRepositoryTest.좋아요(LikeRepositoryTest.java:41)
	...
14:57:43.595 [main] WARN org.hibernate.engine.jdbc.spi.SqlExceptionHelper -- SQL Error: 1064, SQLState: 42000
14:57:43.595 [main] ERROR org.hibernate.engine.jdbc.spi.SqlExceptionHelper -- (conn=2813) You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'LIKE (PROJECT_ID, USER_IDX) values (2, 2)' at line 1
14:57:43.620 [main] DEBUG org.hibernate.resource.transaction.backend.jdbc.internal.JdbcResourceLocalTransactionCoordinatorImpl -- JDBC transaction marked for rollback-only (exception provided for stack trace)
java.lang.Exception: exception just for purpose of providing stack trace
	at org.hibernate.resource.transaction.backend.jdbc.internal.JdbcResourceLocalTransactionCoordinatorImpl$TransactionDriverControlImpl.markRollbackOnly(JdbcResourceLocalTransactionCoordinatorImpl.java:324)
	...
	at com.example.tumblbugclone.repository.LikeRepository$$SpringCGLIB$$0.save(<generated>)
	at com.example.tumblbugclone.repository.LikeRepositoryTest.좋아요(LikeRepositoryTest.java:41)
    ...
org.springframework.dao.InvalidDataAccessResourceUsageException: could not execute statement; SQL [n/a]

	...
	at com.example.tumblbugclone.repository.LikeRepository$$SpringCGLIB$$0.save(<generated>)
	at com.example.tumblbugclone.repository.LikeRepositoryTest.좋아요(LikeRepositoryTest.java:41)
    ...
Caused by: org.hibernate.exception.SQLGrammarException: could not execute statement
	at org.hibernate.exception.internal.SQLExceptionTypeDelegate.convert(SQLExceptionTypeDelegate.java:64)
	at org.hibernate.exception.internal.StandardSQLExceptionConverter.convert(StandardSQLExceptionConverter.java:56)
    ...
	at com.example.tumblbugclone.repository.LikeRepository.save(LikeRepository.java:24)
    ... 38 more
Caused by: java.sql.SQLSyntaxErrorException: (conn=2813) You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'LIKE (PROJECT_ID, USER_IDX) values (2, 2)' at line 1
	at org.mariadb.jdbc.export.ExceptionFactory.createException(ExceptionFactory.java:282)
    ... 73 more

얼추 살펴 보니 SQL 문법이 잘못되었거나, MariaDB의 버전을 확인 해 보라는 등의 메시지를 볼 수 있었다.

그러나, SQL 문법은 하이버네이트에서 알아서 생성 해 줄테니 문제가 없을 것 같았고, MariaDB의 버전 호환 역시 이전에 확인 하고 넘어갔기 때문에 해당 부분 이전 단계의 문제일 것이라 생각이 들었다.

 

LikeRepositoryTest 클래스의 빌드 과정에서의 에러 메시지에서 다음의 에러를 발견할 수 있었다.

...
org.hibernate.tool.schema.spi.CommandAcceptanceException: Error executing DDL "
    drop table if exists LIKE" via JDBC Statement
	at org.hibernate.tool.schema.internal.exec.GenerationTargetToDatabase.accept(GenerationTargetToDatabase.java:67)
    ...
Caused by: java.sql.SQLSyntaxErrorException: (conn=2813) You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'LIKE' at line 1
	at org.mariadb.jdbc.export.ExceptionFactory.createException(ExceptionFactory.java:282)
    ... 61 common frames omitted

 

LIKE 테이블을 생성하는 과정에서 에러가 발생했기 때문에 LIKE 테이블을 사용하는 로직에서 전부 에러가 발생하는 것이었다. 

 

CommandAcceptanceException 으로 검색을 해 본 결과, Like Entity에 사용했던 테이블 명 LIKE가 MariaDB의 예약어 이기 때문에 발생한 오류였다.

Like Entity를 다음과 같이 수정하여 문제를 해결하였다.

@Entity
@Table(name = "LIKES")
@Data
@NoArgsConstructor
public class Like {...}

초기 개발 단계에서 spring.jpa.hibernate.ddl-auto=create로 설정 후 서버에서는 테이블을 별도로 생성하지 않아서 뒤늦게 비즈니스 로직 개발 단계에서 발견하게 되었다.

프로젝트 진행을 위해 SQL을 완벽히 공부하지 못한 상태에서 JPA를 사용하니 이런 문제를 겪게 되는 것 같다. 프로젝트가 종료되면 DB 공부를 진행하자는 다짐이 조금 더 강해졌다.

 

아래는 트러블 슈팅에 참고한 블로그이다.

 

https://lktgt.tistory.com/47

 

[Spring] JPA 테이블 생성 오류

JPA를 이용하여 Entity로 Table을 만들 때 오류가 생겼다. org.hibernate.tool.schema.spi.CommandAcceptanceException: Error executing DDL "create table like (article_id bigint not null, member_name varchar(255) not null, liked bit, primary key (

lktgt.tistory.com