web-dev-qa-db-ja.com

@Converterアノテーション付きクラスがjpaによって自動検出されない

@Converter(introduced since JPA2.1)は、データベースの値をJavaコードで表示したい値に切り替えるための非常に便利な方法のようです。しかし、これを機能させることはできません。 JPAは、私が作成したコンバーターを認識していないようで、値を適切なクラスに変換しようとしています。

これは私が書いたコードです:

@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();
    }
}

モデルで書かれた対応する部分は次のとおりです。

@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;
    }
}

クエリを実行すると、次のエラーが発生します。

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

コンバーターをpersistence.xmlに明示的に登録するための参照を見つけました。しかし、私は今のところpersistence.xmlを使用しておらず、この方法を継続したいと考えています。アノテーションが@Entityのモデルクラスが自動的に検出されます。これは私がこれに使用しているコードです:

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

このパッケージ(または任意のサブパッケージ)内のすべての@Entityクラスが検出されています。ただし、@Converterで注釈が付けられたDateConverterではありません。ここで何が欠けていますか。

また、プロパティに次のものを追加してみました。

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

PS:ランダムな文字列を日付に変換したい理由の詳細には触れないでください。これはほんの一例です。

11
azi

私は実際にはまだJPA2.1に精通していません。ただし、スタックトレースによると、Hibernate4.2.1を使用しています。

以下にリストされているSO投稿とHibernateバージョンリストによると、JPA2.1サポートはHibernate4.3.0で追加されています

Hibernateのバージョンを更新してみましたか?

SO: どのバージョンのHibernateがJPA 2.1をサポートしますか?

Hibernateバージョンリスト: https://hibernate.atlassian.net/browse/HHH?selectedTab=com.atlassian.jira.jira-projects-plugin%3aversions-panel&subset=-1

7
Frans Oosterhof

JPAを手動で構成することにした場合(たとえば、複数のデータソースを構成したい場合)、LocalContainerEntityManagerFactoryBeanはConverterが配置されているパッケージをスキャンする必要があります。

@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;
}
4
Karol Król