Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

@Converter annotated class not getting auto detected by jpa

@Converter(introduced since JPA2.1) seems to be a very handy way to switch database values to the value we want to see in our java code. However, I am unable to get this thing working. JPA seems to be unaware to the converter I have written and is trying to convert the values to the appropriate class by itself.

This is the code I have written:

@Converter(autoApply = true)
public class DateConverter implements AttributeConverter<Date, String> {
    @Override
    public String convertToDatabaseColumn(Date b) {
        System.out.println("Converting to Database Columns");
        return "";
    }

    @Override
    public Date convertToEntityAttribute(String string) {
        System.out.println("Converting to Entity Attribute");
        return new Date();
    }
}

Corresponding part written in model is:

@Entity
@Table(name = "test_table")
public class TestClass extends BaseModel {
    private static final long serialVersionUID = 1L;

    @Id
    private Integer           id;

    @Convert(converter = DateConverter.class)
    @Column(name = "is_dominant_project_unit_type")
    private Date              isDominantProjectUnitType;

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public Date getIsDominantProjectUnitType() {
        return isDominantProjectUnitType;
    }

    public void setIsDominantProjectUnitType(Date isDominantProjectUnitType) {
        this.isDominantProjectUnitType = isDominantProjectUnitType;
    }
}

I get the following error when I run the query:

com.abcd.exception.ProAPIException: java.util.concurrent.ExecutionException: javax.persistence.PersistenceException: org.hibernate.exception.GenericJDBCException: could not execute query
    at com.abcd.data.service.trend.TrendService.getPaginatedTrend(TrendService.java:111) ~[classes/:na]
    at com.abcd.data.service.trend.TrendService.getHithertoPaginatedTrend(TrendService.java:167) ~[classes/:na]
    at com.abcd.data.mvc.trend.TrendController.getHithertoTrend(TrendController.java:183) ~[classes/:na]
    at com.abcd.data.mvc.trend.TrendController$$FastClassByCGLIB$$44adcd0f.invoke(<generated>) ~[spring-core-3.2.2.RELEASE.jar:na]
    at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:204) ~[spring-core-3.2.2.RELEASE.jar:3.2.2.RELEASE]
    at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:698) ~[spring-aop-3.2.2.RELEASE.jar:3.2.2.RELEASE]
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:150) ~[spring-aop-3.2.2.RELEASE.jar:3.2.2.RELEASE]
    at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:91) ~[spring-aop-3.2.2.RELEASE.jar:3.2.2.RELEASE]
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172) ~[spring-aop-3.2.2.RELEASE.jar:3.2.2.RELEASE]
    at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:631) ~[spring-aop-3.2.2.RELEASE.jar:3.2.2.RELEASE]
    at com.abcd.data.mvc.trend.TrendController$$EnhancerByCGLIB$$faeff680.getHithertoTrend(<generated>) ~[spring-core-3.2.2.RELEASE.jar:na]
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.7.0_55]
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57) ~[na:1.7.0_55]
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.7.0_55]
    at java.lang.reflect.Method.invoke(Method.java:606) ~[na:1.7.0_55]
    at org.springframework.web.method.support.InvocableHandlerMethod.invoke(InvocableHandlerMethod.java:219) ~[spring-web-3.2.2.RELEASE.jar:3.2.2.RELEASE]
    at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:132) ~[spring-web-3.2.2.RELEASE.jar:3.2.2.RELEASE]
    at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:104) ~[spring-webmvc-3.2.2.RELEASE.jar:3.2.2.RELEASE]
    at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandleMethod(RequestMappingHandlerAdapter.java:745) ~[spring-webmvc-3.2.2.RELEASE.jar:3.2.2.RELEASE]
    at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:686) ~[spring-webmvc-3.2.2.RELEASE.jar:3.2.2.RELEASE]
    at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:80) ~[spring-webmvc-3.2.2.RELEASE.jar:3.2.2.RELEASE]
    at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:925) ~[spring-webmvc-3.2.2.RELEASE.jar:3.2.2.RELEASE]
    at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:856) ~[spring-webmvc-3.2.2.RELEASE.jar:3.2.2.RELEASE]
    at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:936) [spring-webmvc-3.2.2.RELEASE.jar:3.2.2.RELEASE]
    at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:827) [spring-webmvc-3.2.2.RELEASE.jar:3.2.2.RELEASE]
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:621) [tomcat-embed-core-7.0.37.jar:7.0.37]
    at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:812) [spring-webmvc-3.2.2.RELEASE.jar:3.2.2.RELEASE]
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:728) [tomcat-embed-core-7.0.37.jar:7.0.37]
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:305) [tomcat-embed-core-7.0.37.jar:7.0.37]
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210) [tomcat-embed-core-7.0.37.jar:7.0.37]
    at org.apache.shiro.web.servlet.AbstractShiroFilter.executeChain(AbstractShiroFilter.java:449) [shiro-web-1.2.1.jar:1.2.1]
    at org.apache.shiro.web.servlet.AbstractShiroFilter$1.call(AbstractShiroFilter.java:365) [shiro-web-1.2.1.jar:1.2.1]
    at org.apache.shiro.subject.support.SubjectCallable.doCall(SubjectCallable.java:90) [shiro-core-1.2.1.jar:1.2.1]
    at org.apache.shiro.subject.support.SubjectCallable.call(SubjectCallable.java:83) [shiro-core-1.2.1.jar:1.2.1]
    at org.apache.shiro.subject.support.DelegatingSubject.execute(DelegatingSubject.java:383) [shiro-core-1.2.1.jar:1.2.1]
    at org.apache.shiro.web.servlet.AbstractShiroFilter.doFilterInternal(AbstractShiroFilter.java:362) [shiro-web-1.2.1.jar:1.2.1]
    at org.apache.shiro.web.servlet.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:125) [shiro-web-1.2.1.jar:1.2.1]
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:243) [tomcat-embed-core-7.0.37.jar:7.0.37]
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210) [tomcat-embed-core-7.0.37.jar:7.0.37]
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:222) [tomcat-embed-core-7.0.37.jar:7.0.37]
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:123) [tomcat-embed-core-7.0.37.jar:7.0.37]
    at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:472) [tomcat-embed-core-7.0.37.jar:7.0.37]
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:171) [tomcat-embed-core-7.0.37.jar:7.0.37]
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:99) [tomcat-embed-core-7.0.37.jar:7.0.37]
    at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:936) [tomcat-embed-core-7.0.37.jar:7.0.37]
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:118) [tomcat-embed-core-7.0.37.jar:7.0.37]
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:407) [tomcat-embed-core-7.0.37.jar:7.0.37]
    at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1004) [tomcat-embed-core-7.0.37.jar:7.0.37]
    at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:589) [tomcat-embed-core-7.0.37.jar:7.0.37]
    at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:310) [tomcat-embed-core-7.0.37.jar:7.0.37]
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145) [na:1.7.0_55]
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615) [na:1.7.0_55]
    at java.lang.Thread.run(Thread.java:745) [na:1.7.0_55]
Caused by: java.util.concurrent.ExecutionException: javax.persistence.PersistenceException: org.hibernate.exception.GenericJDBCException: could not execute query
    at java.util.concurrent.FutureTask.report(FutureTask.java:122) ~[na:1.7.0_55]
    at java.util.concurrent.FutureTask.get(FutureTask.java:188) ~[na:1.7.0_55]
    at com.abcd.data.service.trend.TrendService.getPaginatedTrend(TrendService.java:100) ~[classes/:na]
    ... 52 common frames omitted
Caused by: javax.persistence.PersistenceException: org.hibernate.exception.GenericJDBCException: could not execute query
    at org.hibernate.ejb.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1387) ~[hibernate-entitymanager-4.2.1.Final.jar:4.2.1.Final]
    at org.hibernate.ejb.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1310) ~[hibernate-entitymanager-4.2.1.Final.jar:4.2.1.Final]
    at org.hibernate.ejb.QueryImpl.getResultList(QueryImpl.java:273) ~[hibernate-entitymanager-4.2.1.Final.jar:4.2.1.Final]
    at org.hibernate.ejb.criteria.CriteriaQueryCompiler$3.getResultList(CriteriaQueryCompiler.java:254) ~[hibernate-entitymanager-4.2.1.Final.jar:4.2.1.Final]
    at com.abcd.data.model.filter.JPAQueryBuilder.retrieveResults(JPAQueryBuilder.java:333) ~[classes/:na]
    at com.abcd.data.repo.trend.TrendDao.getTrend(TrendDao.java:33) ~[classes/:na]
    at com.abcd.data.repo.trend.TrendDao$$FastClassByCGLIB$$b47f3dbd.invoke(<generated>) ~[spring-core-3.2.2.RELEASE.jar:na]
    at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:204) ~[spring-core-3.2.2.RELEASE.jar:3.2.2.RELEASE]
    at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:698) ~[spring-aop-3.2.2.RELEASE.jar:3.2.2.RELEASE]
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:150) ~[spring-aop-3.2.2.RELEASE.jar:3.2.2.RELEASE]
    at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:155) ~[spring-tx-3.2.2.RELEASE.jar:3.2.2.RELEASE]
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172) ~[spring-aop-3.2.2.RELEASE.jar:3.2.2.RELEASE]
    at org.springframework.cache.interceptor.CacheInterceptor$1.invoke(CacheInterceptor.java:58) ~[spring-context-3.2.2.RELEASE.jar:3.2.2.RELEASE]
    at org.springframework.cache.interceptor.CacheAspectSupport.execute(CacheAspectSupport.java:214) ~[spring-context-3.2.2.RELEASE.jar:3.2.2.RELEASE]
    at org.springframework.cache.interceptor.CacheInterceptor.invoke(CacheInterceptor.java:66) ~[spring-context-3.2.2.RELEASE.jar:3.2.2.RELEASE]
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172) ~[spring-aop-3.2.2.RELEASE.jar:3.2.2.RELEASE]
    at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:631) ~[spring-aop-3.2.2.RELEASE.jar:3.2.2.RELEASE]
    at com.abcd.data.repo.trend.TrendDao$$EnhancerByCGLIB$$664630bd.getTrend(<generated>) ~[spring-core-3.2.2.RELEASE.jar:na]
    at com.abcd.data.service.trend.TrendService.getTrend(TrendService.java:56) ~[classes/:na]
    at com.abcd.data.service.trend.TrendService.getTrend(TrendService.java:61) ~[classes/:na]
    at com.abcd.data.service.trend.TrendService$1.call(TrendService.java:80) ~[classes/:na]
    at com.abcd.data.service.trend.TrendService$1.call(TrendService.java:77) ~[classes/:na]
    at java.util.concurrent.FutureTask.run(FutureTask.java:262) ~[na:1.7.0_55]
    ... 3 common frames omitted
Caused by: org.hibernate.exception.GenericJDBCException: could not execute query
    at org.hibernate.exception.internal.StandardSQLExceptionConverter.convert(StandardSQLExceptionConverter.java:54) ~[hibernate-core-4.2.1.Final.jar:4.2.1.Final]
    at org.hibernate.engine.jdbc.spi.SqlExceptionHelper.convert(SqlExceptionHelper.java:125) ~[hibernate-core-4.2.1.Final.jar:4.2.1.Final]
    at org.hibernate.loader.Loader.doList(Loader.java:2525) ~[hibernate-core-4.2.1.Final.jar:4.2.1.Final]
    at org.hibernate.loader.Loader.doList(Loader.java:2508) ~[hibernate-core-4.2.1.Final.jar:4.2.1.Final]
    at org.hibernate.loader.Loader.listIgnoreQueryCache(Loader.java:2338) ~[hibernate-core-4.2.1.Final.jar:4.2.1.Final]
    at org.hibernate.loader.Loader.list(Loader.java:2333) ~[hibernate-core-4.2.1.Final.jar:4.2.1.Final]
    at org.hibernate.loader.hql.QueryLoader.list(QueryLoader.java:490) ~[hibernate-core-4.2.1.Final.jar:4.2.1.Final]
    at org.hibernate.hql.internal.ast.QueryTranslatorImpl.list(QueryTranslatorImpl.java:355) ~[hibernate-core-4.2.1.Final.jar:4.2.1.Final]
    at org.hibernate.engine.query.spi.HQLQueryPlan.performList(HQLQueryPlan.java:195) ~[hibernate-core-4.2.1.Final.jar:4.2.1.Final]
    at org.hibernate.internal.SessionImpl.list(SessionImpl.java:1269) ~[hibernate-core-4.2.1.Final.jar:4.2.1.Final]
    at org.hibernate.internal.QueryImpl.list(QueryImpl.java:101) ~[hibernate-core-4.2.1.Final.jar:4.2.1.Final]
    at org.hibernate.ejb.QueryImpl.getResultList(QueryImpl.java:264) ~[hibernate-entitymanager-4.2.1.Final.jar:4.2.1.Final]
    ... 23 common frames omitted
Caused by: java.sql.SQLException: Cannot convert value 'testString' from column 2 to TIMESTAMP.
    at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:1078) ~[mysql-connector-java-5.1.25.jar:na]
    at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:989) ~[mysql-connector-java-5.1.25.jar:na]
    at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:975) ~[mysql-connector-java-5.1.25.jar:na]
    at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:920) ~[mysql-connector-java-5.1.25.jar:na]
    at com.mysql.jdbc.ResultSetRow.getTimestampFast(ResultSetRow.java:1404) ~[mysql-connector-java-5.1.25.jar:na]
    at com.mysql.jdbc.ByteArrayRow.getTimestampFast(ByteArrayRow.java:127) ~[mysql-connector-java-5.1.25.jar:na]
    at com.mysql.jdbc.ResultSetImpl.getTimestampInternal(ResultSetImpl.java:6592) ~[mysql-connector-java-5.1.25.jar:na]
    at com.mysql.jdbc.ResultSetImpl.getTimestamp(ResultSetImpl.java:6192) ~[mysql-connector-java-5.1.25.jar:na]
    at com.mysql.jdbc.ResultSetImpl.getTimestamp(ResultSetImpl.java:6230) ~[mysql-connector-java-5.1.25.jar:na]
    at com.mchange.v2.c3p0.impl.NewProxyResultSet.getTimestamp(NewProxyResultSet.java:3394) ~[c3p0-0.9.1.2.jar:0.9.1.2]
    at org.hibernate.type.descriptor.sql.TimestampTypeDescriptor$2.doExtract(TimestampTypeDescriptor.java:67) ~[hibernate-core-4.2.1.Final.jar:4.2.1.Final]
    at org.hibernate.type.descriptor.sql.BasicExtractor.extract(BasicExtractor.java:64) ~[hibernate-core-4.2.1.Final.jar:4.2.1.Final]
    at org.hibernate.type.AbstractStandardBasicType.nullSafeGet(AbstractStandardBasicType.java:261) ~[hibernate-core-4.2.1.Final.jar:4.2.1.Final]
    at org.hibernate.type.AbstractStandardBasicType.nullSafeGet(AbstractStandardBasicType.java:257) ~[hibernate-core-4.2.1.Final.jar:4.2.1.Final]
    at org.hibernate.type.AbstractStandardBasicType.nullSafeGet(AbstractStandardBasicType.java:247) ~[hibernate-core-4.2.1.Final.jar:4.2.1.Final]
    at org.hibernate.loader.hql.QueryLoader.getResultRow(QueryLoader.java:443) ~[hibernate-core-4.2.1.Final.jar:4.2.1.Final]
    at org.hibernate.loader.hql.QueryLoader.getResultColumnOrRow(QueryLoader.java:427) ~[hibernate-core-4.2.1.Final.jar:4.2.1.Final]
    at org.hibernate.loader.Loader.getRowFromResultSet(Loader.java:740) ~[hibernate-core-4.2.1.Final.jar:4.2.1.Final]
    at org.hibernate.loader.Loader.processResultSet(Loader.java:942) ~[hibernate-core-4.2.1.Final.jar:4.2.1.Final]
    at org.hibernate.loader.Loader.doQuery(Loader.java:910) ~[hibernate-core-4.2.1.Final.jar:4.2.1.Final]
    at org.hibernate.loader.Loader.doQueryAndInitializeNonLazyCollections(Loader.java:341) ~[hibernate-core-4.2.1.Final.jar:4.2.1.Final]
    at org.hibernate.loader.Loader.doList(Loader.java:2522) ~[hibernate-core-4.2.1.Final.jar:4.2.1.Final]
    ... 32 common frames omitted
Caused by: java.lang.NumberFormatException: testString
    at com.mysql.jdbc.StringUtils.getInt(StringUtils.java:791) ~[mysql-connector-java-5.1.25.jar:na]
    at com.mysql.jdbc.ResultSetRow.getTimestampFast(ResultSetRow.java:1347) ~[mysql-connector-java-5.1.25.jar:na]
    ... 49 common frames omitted

I have found references to explicitly register the converter in persistence.xml. But, I am not using persistence.xml so far and want to continue this way. My model classes with annotation @Entity are getting detected automatically. This is the code I am using for this:

factory.setPackagesToScan("com.abcd.data.model")

All my @Entity classes inside this package(or any subpackage) are getting detected. But, not by DateConverter annotated with @Converter. What am I missing here.

I have also tried adding the following in properties:

Properties properties = new Properties();
properties.put("hibernate.archive.autodetection", "class, hbm");
factory.setJpaProperties(properties);

PS: Please don't get into the details of why I want to convert a random string into date. This is just an example.

like image 960
azi Avatar asked Jun 02 '14 10:06

azi


2 Answers

I'm actually not yet familiar with JPA 2.1. However according to your stacktrace you are using hibernate 4.2.1.

According to the SO post listed below and the hibernate version list, JPA 2.1 support is added in Hibernate 4.3.0

Have you tried updating your version of Hibernate?

SO: Which version of hibernate support jpa 2.1?

Hibernate version list: https://hibernate.atlassian.net/browse/HHH?selectedTab=com.atlassian.jira.jira-projects-plugin%3aversions-panel&subset=-1

like image 66
Frans Oosterhof Avatar answered Oct 27 '22 00:10

Frans Oosterhof


If you decide to configure JPA manually (eg. you want to configure multiple data sources), then LocalContainerEntityManagerFactoryBean should scan package where Converter is placed.

@Bean
LocalContainerEntityManagerFactoryBean yourEntityManagerFactory() {
    final LocalContainerEntityManagerFactoryBean factoryBean = new LocalContainerEntityManagerFactoryBean();
    factoryBean.setDataSource(arcEditorsDataSource());
    final HibernateJpaVendorAdapter jpaVendorAdapter = new HibernateJpaVendorAdapter();
    jpaVendorAdapter.setDatabase(Database.POSTGRESQL);
    factoryBean.setJpaVendorAdapter(jpaVendorAdapter);
    factoryBean.setPackagesToScan(
            "your.model",
            "your.jpa.config" //where converter is placed
    );
    return factoryBean;
}
like image 38
Karol Król Avatar answered Oct 27 '22 01:10

Karol Król