Caused by: com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException

개발환경

  • hibernate : 4.2.0.Final
    • hibernate dialect : org.hibernate.dialect.MySQLDialect
  • MariaDB : 5.5.29-MariaDB

문제 로그

java.lang.reflect.InvocationTargetException

    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)

    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)

    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)

    at java.lang.reflect.Method.invoke(Method.java:601)

    at org.codehaus.mojo.exec.ExecJavaMojo$1.run(ExecJavaMojo.java:297)

    at java.lang.Thread.run(Thread.java:722)

Caused by: org.springframework.jdbc.BadSqlGrammarException: PreparedStatementCallback; bad SQL grammar [insert into department(id, name, description, parent_id, createdDate) values(?, ?, ?, ?, ?)]; nested exception is java.sql.BatchUpdateException: Table 'database.department' doesn't exist

    at org.springframework.jdbc.support.SQLErrorCodeSQLExceptionTranslator.doTranslate(SQLErrorCodeSQLExceptionTranslator.java:237)

    at org.springframework.jdbc.support.AbstractFallbackSQLExceptionTranslator.translate(AbstractFallbackSQLExceptionTranslator.java:72)

    at org.springframework.jdbc.core.JdbcTemplate.execute(JdbcTemplate.java:605)

    at org.springframework.jdbc.core.JdbcTemplate.execute(JdbcTemplate.java:617)

    at org.springframework.jdbc.core.JdbcTemplate.batchUpdate(JdbcTemplate.java:890)

    at org.springframework.jdbc.core.namedparam.NamedParameterBatchUpdateUtils.executeBatchUpdateWithNamedParameters(NamedParameterBatchUpdateUtils.java:40)

    at org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate.batchUpdate(NamedParameterJdbcTemplate.java:324)

    ... 6 more

Caused by: java.sql.BatchUpdateException: Table 'database.department' doesn't exist

    at com.mysql.jdbc.PreparedStatement.executeBatchSerially(PreparedStatement.java:2054)

    at com.mysql.jdbc.PreparedStatement.executeBatch(PreparedStatement.java:1467)

    at com.mchange.v2.c3p0.impl.NewProxyPreparedStatement.executeBatch(NewProxyPreparedStatement.java:1723)

    at org.springframework.jdbc.core.JdbcTemplate$4.doInPreparedStatement(JdbcTemplate.java:905)

    at org.springframework.jdbc.core.JdbcTemplate$4.doInPreparedStatement(JdbcTemplate.java:890)

    at org.springframework.jdbc.core.JdbcTemplate.execute(JdbcTemplate.java:589)

    ... 12 more

Caused by: com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: Table 'database.department' doesn't exist

    at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)

    at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:57)

    at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)

    at java.lang.reflect.Constructor.newInstance(Constructor.java:525)

    at com.mysql.jdbc.Util.handleNewInstance(Util.java:411)

    at com.mysql.jdbc.Util.getInstance(Util.java:386)

    at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:1054)

    at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:4120)

    at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:4052)

    at com.mysql.jdbc.MysqlIO.sendCommand(MysqlIO.java:2503)

    at com.mysql.jdbc.MysqlIO.sqlQueryDirect(MysqlIO.java:2664)

    at com.mysql.jdbc.ConnectionImpl.execSQL(ConnectionImpl.java:2815)

    at com.mysql.jdbc.PreparedStatement.executeInternal(PreparedStatement.java:2155)

    at com.mysql.jdbc.PreparedStatement.executeUpdate(PreparedStatement.java:2458)

    at com.mysql.jdbc.PreparedStatement.executeBatchSerially(PreparedStatement.java:2006)

    ... 17 more

[INFO] ------------------------------------------------------------------------

[INFO] BUILD FAILURE

[INFO] ------------------------------------------------------------------------

[INFO] Total time: 10.762s

[INFO] Finished at: Wed Apr 24 22:06:17 KST 2013

[INFO] Final Memory: 43M/365M

[INFO] ------------------------------------------------------------------------

[ERROR] Failed to execute goal org.codehaus.mojo:exec-maven-plugin:1.2.1:java (default-cli) on project docs-flow-data-manager: An exception occured while executing the Java class. null: InvocationTargetException: PreparedStatementCallback; bad SQL grammar [insert into department(id, name, description, parent_id, createdDate) values(?, ?, ?, ?, ?)]; nested exception is java.sql.BatchUpdateException: Table 'database.department' doesn't exist -> [Help 1]

[ERROR]

[ERROR] To see the full stack trace of the errors, re-run Maven with the -e switch.

[ERROR] Re-run Maven using the -X switch to enable full debug logging.

[ERROR]

[ERROR] For more information about the errors and possible solutions, please read the following articles:

[ERROR] [Help 1] http://cwiki.apache.org/confluence/display/MAVEN/MojoExecutionException

해결책

  • 하이버네이트가 자동으로 @Entity를 이용하여 테이블을 생성할 때 기본은 클래스명을 따른다.
    • 대소문자를 구분하는 Database 에서는 이 부분이 문제를 일으키는 요인으로 추측된다.
  • @Entity 아래에 @Table(name=“TABLE_NAME”) 으로 테이블명을 대문자로 하여 강제적으로 선언했다.
  • 참조관계가 생성되는 부분들에 대해서도 @JoinTable(name=“JOIN_TABLE”)으로 지정해주는 것이 적절해보인다.

### 개발환경

* Spring MVC 3.2.0

* Hibernate 4.2.0.Final


### 문제발생

MVC 패턴에서 Controller 단에서 @PathVariable로 객체를 받아서 처리하려는 시도를 하면서 문제가 발생했다.


### 로그


HTTP Status 500 - No serializer found for class org.hibernate.proxy.pojo.javassist.JavassistLazyInitializer and no properties discovered to create BeanSerializer (to avoid exception, disable SerializationConfig.Feature.FAIL_ON_EMPTY_BEANS) ) (through reference chain: java.util.HashMap["result"]->com.sil.docsflow.web.common.Result["data"]->com.sil.docsflow.domain.company.User_$$_javassist_15["handler"])


type Exception report


message No serializer found for class org.hibernate.proxy.pojo.javassist.JavassistLazyInitializer and no properties discovered to create BeanSerializer (to avoid exception, disable SerializationConfig.Feature.FAIL_ON_EMPTY_BEANS) ) (through reference chain: java.util.HashMap["result"]->com.sil.docsflow.web.common.Result["data"]->com.sil.docsflow.domain.company.User_$$_javassist_15["handler"])


description The server encountered an internal error that prevented it from fulfilling this request.


exception


org.codehaus.jackson.map.JsonMappingException: No serializer found for class org.hibernate.proxy.pojo.javassist.JavassistLazyInitializer and no properties discovered to create BeanSerializer (to avoid exception, disable SerializationConfig.Feature.FAIL_ON_EMPTY_BEANS) ) (through reference chain: java.util.HashMap["result"]->com.sil.docsflow.web.common.Result["data"]->com.sil.docsflow.domain.company.User_$$_javassist_15["handler"])

org.codehaus.jackson.map.ser.StdSerializerProvider$1.failForEmpty(StdSerializerProvider.java:89)

org.codehaus.jackson.map.ser.StdSerializerProvider$1.serialize(StdSerializerProvider.java:62)

org.codehaus.jackson.map.ser.BeanPropertyWriter.serializeAsField(BeanPropertyWriter.java:430)

org.codehaus.jackson.map.ser.BeanSerializer.serializeFields(BeanSerializer.java:175)

org.codehaus.jackson.map.ser.BeanSerializer.serialize(BeanSerializer.java:142)

org.codehaus.jackson.map.ser.BeanPropertyWriter.serializeAsField(BeanPropertyWriter.java:430)

org.codehaus.jackson.map.ser.BeanSerializer.serializeFields(BeanSerializer.java:175)

org.codehaus.jackson.map.ser.BeanSerializer.serialize(BeanSerializer.java:142)

org.codehaus.jackson.map.ser.MapSerializer.serializeFields(MapSerializer.java:287)

org.codehaus.jackson.map.ser.MapSerializer.serialize(MapSerializer.java:212)

org.codehaus.jackson.map.ser.MapSerializer.serialize(MapSerializer.java:23)

org.codehaus.jackson.map.ser.StdSerializerProvider._serializeValue(StdSerializerProvider.java:600)

org.codehaus.jackson.map.ser.StdSerializerProvider.serializeValue(StdSerializerProvider.java:280)

org.codehaus.jackson.map.ObjectMapper.writeValue(ObjectMapper.java:1345)

org.springframework.web.servlet.view.json.MappingJacksonJsonView.writeContent(MappingJacksonJsonView.java:292)

org.springframework.web.servlet.view.json.MappingJacksonJsonView.renderMergedOutputModel(MappingJacksonJsonView.java:247)

org.springframework.web.servlet.view.AbstractView.render(AbstractView.java:264)

org.springframework.web.servlet.DispatcherServlet.render(DispatcherServlet.java:1208)

org.springframework.web.servlet.DispatcherServlet.processDispatchResult(DispatcherServlet.java:992)

org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:939)

org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:856)

org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:936)

org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:827)

javax.servlet.http.HttpServlet.service(HttpServlet.java:621)

org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:812)

javax.servlet.http.HttpServlet.service(HttpServlet.java:728)

org.springframework.web.filter.HiddenHttpMethodFilter.doFilterInternal(HiddenHttpMethodFilter.java:77)

org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)

org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:88)

org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)

note The full stack trace of the root cause is available in the Apache Tomcat/7.0.34 logs.


Apache Tomcat/7.0.34


### 해결방법

* 참조페이지 : [Strange Jackson exception being thrown when serializing Hibernate object](http://stackoverflow.com/questions/4362104/strange-jackson-exception-being-thrown-when-serializing-hibernate-object)


### 나름 분석

하이버네이트에 의해 영속화된 객체에 hadler 와 hibernateLazyInitializer 의 필드가 생성되는 것으로 보인다. 이렇게 영속화된 객체를 JSON으로 직렬화 하는 과정에서 hadler 가 lazy로 처리되어 있어서 발생하는 문제가 아닌가 추측해본다.


### 문제 발생

org.hibernate.MappingException: org.hibernate.dialect.MySQLDialect does not support sequences


### 문제원인 

도메인의 @ID @GeneratedValue(strategy = GenerationType.SEQUENCE) 으로 선언해둔 부분에서 GenerationType.SEQUENCE 생성방식을 MySQL에서 지원하지 않는 것으로 보인다.


### 해결방법

GenerationType.AUTO 으로 변경


Hibernate 3.6.0.Final 을 사용하다가 4.2.Final 으로 변경하면서

MultipleBagFetchException: cannot simultaneously fetch multiple bags

이 발생하면서 entityManager가 정상적으로 밀드되지 않는 문제가 생겨남


* 관련 문제 해결 확인 :  MultipleBagFetchException: cannot simultaneously fetch multiple bags is there a workaround


@OneToMany(fetch=FetchType.EAGER)

private List<Department> departments;


형태로 선언된 부분들과 관련된 문제였다.

List 클래스와 관련된 문제가 아닐까 추측이 된다.


* 해결방법

    * 첫번째 방법

    @OneToMany(fetch=FetchType.EAGER)

    @LazyCollection(LazyCollectionOption.FALSE)  



    * 두번째 방법 

    @OneToMany(fetch=FetchType.LAZY)



* 개인적 의견 

    * 두번째 방법이 문제가 없다면, 걍 두번째 방법을 사용

    * @OneToOne의 경우에는 FetchType.EAGER 선언해도 오류없이 동작한다.



회사에서 프론트엔드(앞단)과 백엔드(딋단)을 분리하겠다는 정책에 따라서, 프론트에서 사용할 API들을 구현해야하는데 참고서로서 좋은 녀석을 찾다가 발견한 녀석이다.

  Outsider(http://blog.outsider.ne.kr) 님이 추천한 책이었는데, 때마침 나도 회사에서 프론트엔드에서 사용할 REST API를 만들어야 하는 상황이어서 '옳다구나!' 하고 바로 질렀다. 오며가며 출근길에 읽고 있는데 꽤 괜찮다 싶다. ^^

좋은 API 디자인하기, 왜 그것이 중요한가?

  : http://dev.kthcorp.com/2012/01/04/how-to-design-a-good-api-and-why-it-matters/

도 함께 읽으면서 API 설계를 위한 학습에 들어갔다.

하지만... 처음부터 잘할 수는 없는 법!

시행착오가 예상된다. 두둥!

이 책은 ebook으로 제공된다.

한빛 사이트 : https://www.hanb.co.kr/ebook/look.html?isbn=9788979149456


+ Recent posts