HibernateでPostgreSQLを利用する場合に、アプリケーションの初期化時に以下のようなエラーが出たので調査した結果をまとめます。
結論から言うと、無視して良さそうなエラーでした。
java.sql.SQLFeatureNotSupportedException: org.postgresql.jdbc.PgConnection.createClob() メソッドはまだ実装されていません。
at org.postgresql.Driver.notImplemented(Driver.java:646) ~[postgresql-9.4.1208.jar:9.4.1208]
at org.postgresql.jdbc.PgConnection.createClob(PgConnection.java:1281) ~[postgresql-9.4.1208.jar:9.4.1208]
at org.apache.commons.dbcp2.DelegatingConnection.createClob(DelegatingConnection.java:868) ~[commons-dbcp2-2.1.1.jar:2.1.1]
at org.apache.commons.dbcp2.DelegatingConnection.createClob(DelegatingConnection.java:868) ~[commons-dbcp2-2.1.1.jar:2.1.1]
at net.sf.log4jdbc.ConnectionSpy.createClob(ConnectionSpy.java:496) ~[log4jdbc-remix-0.2.7.jar:na]
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_77]
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:1.8.0_77]
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_77]
at java.lang.reflect.Method.invoke(Method.java:498) ~[na:1.8.0_77]
at org.hibernate.engine.jdbc.internal.LobCreatorBuilder.useContextualLobCreation(LobCreatorBuilder.java:112) [hibernate-core-4.3.11.Final.jar:4.3.11.Final]
at org.hibernate.engine.jdbc.internal.LobCreatorBuilder.<init>(LobCreatorBuilder.java:63) [hibernate-core-4.3.11.Final.jar:4.3.11.Final]
at org.hibernate.engine.jdbc.internal.JdbcServicesImpl.configure(JdbcServicesImpl.java:192) [hibernate-core-4.3.11.Final.jar:4.3.11.Final]
at org.hibernate.boot.registry.internal.StandardServiceRegistryImpl.configureService(StandardServiceRegistryImpl.java:111) [hibernate-core-4.3.11.Final.jar:4.3.11.Final]
at org.hibernate.service.internal.AbstractServiceRegistryImpl.initializeService(AbstractServiceRegistryImpl.java:234) [hibernate-core-4.3.11.Final.jar:4.3.11.Final]
at org.hibernate.service.internal.AbstractServiceRegistryImpl.getService(AbstractServiceRegistryImpl.java:206) [hibernate-core-4.3.11.Final.jar:4.3.11.Final]
at org.hibernate.cfg.Configuration.buildTypeRegistrations(Configuration.java:1887) [hibernate-core-4.3.11.Final.jar:4.3.11.Final]
at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:1845) [hibernate-core-4.3.11.Final.jar:4.3.11.Final]
at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl$4.perform(EntityManagerFactoryBuilderImpl.java:857) [hibernate-entitymanager-4.3.11.Final.jar:4.3.11.Final]
at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl$4.perform(EntityManagerFactoryBuilderImpl.java:850) [hibernate-entitymanager-4.3.11.Final.jar:4.3.11.Final]
at org.hibernate.boot.registry.classloading.internal.ClassLoaderServiceImpl.withTccl(ClassLoaderServiceImpl.java:425) [hibernate-core-4.3.11.Final.jar:4.3.11.Final]
at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.build(EntityManagerFactoryBuilderImpl.java:849) [hibernate-entitymanager-4.3.11.Final.jar:4.3.11.Final]
at org.springframework.orm.jpa.vendor.SpringHibernateJpaPersistenceProvider.createContainerEntityManagerFactory(SpringHibernateJpaPersistenceProvider.java:60) [spring-orm-4.2.4.RELEASE.jar:4.2.4.RELEASE]
at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.createNativeEntityManagerFactory(LocalContainerEntityManagerFactoryBean.java:343) [spring-orm-4.2.4.RELEASE.jar:4.2.4.RELEASE]
at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.afterPropertiesSet(AbstractEntityManagerFactoryBean.java:318) [spring-orm-4.2.4.RELEASE.jar:4.2.4.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1637) [spring-beans-4.2.4.RELEASE.jar:4.2.4.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1574) [spring-beans-4.2.4.RELEASE.jar:4.2.4.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:545) [spring-beans-4.2.4.RELEASE.jar:4.2.4.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:482) [spring-beans-4.2.4.RELEASE.jar:4.2.4.RELEASE]
at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:306) [spring-beans-4.2.4.RELEASE.jar:4.2.4.RELEASE]
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230) [spring-beans-4.2.4.RELEASE.jar:4.2.4.RELEASE]
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:302) [spring-beans-4.2.4.RELEASE.jar:4.2.4.RELEASE]
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197) [spring-beans-4.2.4.RELEASE.jar:4.2.4.RELEASE]
at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1054) [spring-context-4.2.4.RELEASE.jar:4.2.4.RELEASE]
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:829) [spring-context-4.2.4.RELEASE.jar:4.2.4.RELEASE]
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:538) [spring-context-4.2.4.RELEASE.jar:4.2.4.RELEASE]
at org.springframework.web.context.ContextLoader.configureAndRefreshWebApplicationContext(ContextLoader.java:446) [spring-web-4.2.4.RELEASE.jar:4.2.4.RELEASE]
at org.springframework.web.context.ContextLoader.initWebApplicationContext(ContextLoader.java:328) [spring-web-4.2.4.RELEASE.jar:4.2.4.RELEASE]
at org.springframework.web.context.ContextLoaderListener.contextInitialized(ContextLoaderListener.java:107) [spring-web-4.2.4.RELEASE.jar:4.2.4.RELEASE]
at org.apache.catalina.core.StandardContext.listenerStart(StandardContext.java:4813) [catalina.jar:8.0.35]
at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5272) [catalina.jar:8.0.35]
at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:147) [catalina.jar:8.0.35]
at org.apache.catalina.core.ContainerBase.addChildInternal(ContainerBase.java:725) [catalina.jar:8.0.35]
at org.apache.catalina.core.ContainerBase.addChild(ContainerBase.java:701) [catalina.jar:8.0.35]
at org.apache.catalina.core.StandardHost.addChild(StandardHost.java:717) [catalina.jar:8.0.35]
at org.apache.catalina.startup.HostConfig.deployWAR(HostConfig.java:940) [catalina.jar:8.0.35]
at org.apache.catalina.startup.HostConfig$DeployWar.run(HostConfig.java:1816) [catalina.jar:8.0.35]
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511) [na:1.8.0_77]
at java.util.concurrent.FutureTask.run(FutureTask.java:266) [na:1.8.0_77]
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) [na:1.8.0_77]
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) [na:1.8.0_77]
at java.lang.Thread.run(Thread.java:745) [na:1.8.0_77]
環境
- PostgreSQL 9.4.5
- PostgreSQL JDBC Driver postgresql-9.4.1208.jar
- Hibernate 4.3.11
- OpenJDK 1.8.0.91
スタックトレースからわかること
JDBCのcreateClob APIを実行してSQLFeatureNotSupportedExceptionが発生しています。
PostgreSQLにはCLOB型は無いので、妥当といえば妥当です。
PostgreSQL JDBC Driverのソースコード
以下のように、createClog()が呼ばれるとSQLFeatureNotSupportedExceptionが投げられるようになっています。
public Clob createClob() throws SQLException {
checkClosed();
throw org.postgresql.Driver.notImplemented(this.getClass(), "createClob()");
}
public static SQLFeatureNotSupportedException notImplemented(Class<?> callClass,
String functionName) {
return new SQLFeatureNotSupportedException(
GT.tr("Method {0} is not yet implemented.", callClass.getName() + "." + functionName),
PSQLState.NOT_IMPLEMENTED.getState());
}
Hibernateのソースコード
どうやらJDBC接続の初期化時に、JDBC APIが実装されているかをチェックしてフラグを立てているだけの様子。ということで、エラーになってもそのJDBC APIは使わないようになるはず。
69 /**
70 * Basically here we are simply checking whether we can call the {@link Connection} methods for
71 * LOB creation added in JDBC 4. We not only check whether the {@link Connection} declares these methods,
72 * but also whether the actual {@link Connection} instance implements them (i.e. can be called without simply
73 * throwing an exception).
74 *
75 * @param jdbcConnection The connection which can be used in level-of-support testing.
76 *
77 * @return True if the connection can be used to create LOBs; false otherwise.
78 */
79 @SuppressWarnings("unchecked")
80 private static boolean useContextualLobCreation(Map configValues, Connection jdbcConnection) {
81 final boolean isNonContextualLobCreationRequired =
82 ConfigurationHelper.getBoolean( Environment.NON_CONTEXTUAL_LOB_CREATION, configValues );
83 if ( isNonContextualLobCreationRequired ) {
84 LOG.disablingContextualLOBCreation( Environment.NON_CONTEXTUAL_LOB_CREATION );
85 return false;
86 }
87 if ( jdbcConnection == null ) {
88 LOG.disablingContextualLOBCreationSinceConnectionNull();
89 return false;
90 }
<<略>>
107 if ( createClobMethod.getDeclaringClass().equals( Connection.class ) ) {
108 // If we get here we are running in a jdk 1.6 (jdbc 4) environment...
109 // Further check to make sure the driver actually implements the LOB creation methods. We
110 // check against createClob() as indicative of all; should we check against all 3 explicitly?
111 try {
112 final Object clob = createClobMethod.invoke( jdbcConnection, NO_ARGS );
113 try {
114 final Method freeMethod = clob.getClass().getMethod( "free", NO_ARG_SIG );
115 freeMethod.invoke( clob, NO_ARGS );
116 }
117 catch ( Throwable ignore ) {
118 LOG.tracef( "Unable to free CLOB created to test createClob() implementation : %s", ignore );
119 }
120 return true;
121 }
122 catch ( Throwable t ) {
123 LOG.disablingContextualLOBCreationSinceCreateClobFailed( t );
124 }
125 }
126 }
127 catch ( NoSuchMethodException ignore ) {
128 }
129
130 return false;
131 }
<<略>>
56 * The public factory method for obtaining the appropriate (according to given JDBC {@link java.sql.Connection}.
57 *
58 * @param configValues The map of settings
59 * @param jdbcConnection A JDBC {@link java.sql.Connection} which can be used to gauge the drivers level of support,
60 * specifically for creating LOB references.
61 */
62 public LobCreatorBuilder(Map configValues, Connection jdbcConnection) {
63 this.useContextualLobCreation = useContextualLobCreation( configValues, jdbcConnection );
64 }
70 /**
71 * Standard implementation of the {@link JdbcServices} contract
72 *
73 * @author Steve Ebersole
74 */
75 public class JdbcServicesImpl implements JdbcServices, ServiceRegistryAwareService, Configurable {
<<略>>
91
92 @Override
93 public void configure(Map configValues) {
<<略>>
192 lobCreatorBuilder = new LobCreatorBuilder( configValues, connection );
480 /**
481 * Should we not use contextual LOB creation (aka based on {@link java.sql.Connection#createBlob()} et al).
482 */
483 String NON_CONTEXTUAL_LOB_CREATION = "hibernate.jdbc.lob.non_contextual_creation";
ここまで読んでググったところ以下のページを発見!
Spring Boot でメール送信する Web アプリケーションを作る ( その3 )( Project の作成 )[かんがるーさんの日記]
http://ksby.hatenablog.com/entry/2015/04/12/113912
上記のリンク先に書かれているように
hibernate.propertiesに
hibernate.jdbc.lob.non_contextual_creation = true
と設定すると当初のエラーが出なくなりました。
以上!