我在启动时启用了架构自动更新。一切顺利,但有一点:在每次启动时,我都会为我的架构中的每个索引获得以下异常(并且其中有一百个)。显然Hibernate无法检测到索引已经存在或根本没有尝试检测到这一点,我该如何解决这个问题呢?它破坏了日志文件,并且很难注意到是否出现了问题。
03:35:45,553 WARN [AnnotationSessionFactoryBean:1119] Unsuccessful schema statement: create index statusIndex on Application (status)
org.postgresql.util.PSQLException: ERROR: relation "statusindex" already exists
at org.postgresql.core.v3.QueryExecutorImpl.receiveErrorResponse(QueryExecutorImpl.java:2103)
at org.postgresql.core.v3.QueryExecutorImpl.processResults(QueryExecutorImpl.java:1836)
at org.postgresql.core.v3.QueryExecutorImpl.execute(QueryExecutorImpl.java:257)
at org.postgresql.jdbc2.AbstractJdbc2Statement.execute(AbstractJdbc2Statement.java:512)
at org.postgresql.jdbc2.AbstractJdbc2Statement.executeWithFlags(AbstractJdbc2Statement.java:374)
at org.postgresql.jdbc2.AbstractJdbc2Statement.executeUpdate(AbstractJdbc2Statement.java:302)
at org.apache.commons.dbcp.DelegatingStatement.executeUpdate(DelegatingStatement.java:228)
at org.springframework.orm.hibernate3.LocalSessionFactoryBean.executeSchemaStatement(LocalSessionFactoryBean.java:1115)
at org.springframework.orm.hibernate3.LocalSessionFactoryBean.executeSchemaScript(LocalSessionFactoryBean.java:1087)
at org.springframework.orm.hibernate3.LocalSessionFactoryBean$1.doInHibernate(LocalSessionFactoryBean.java:942)
at org.springframework.orm.hibernate3.HibernateTemplate.doExecute(HibernateTemplate.java:406)
at org.springframework.orm.hibernate3.HibernateTemplate.execute(HibernateTemplate.java:339)
at org.springframework.orm.hibernate3.LocalSessionFactoryBean.updateDatabaseSchema(LocalSessionFactoryBean.java:935)
at org.springframework.orm.hibernate3.LocalSessionFactoryBean.afterSessionFactoryCreation(LocalSessionFactoryBean.java:883)
at org.springframework.orm.hibernate3.AbstractSessionFactoryBean.afterPropertiesSet(AbstractSessionFactoryBean.java:190)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1514)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1452)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:519)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:456)
at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:294)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:225)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:291)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:193)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:591)
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:918)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:469)
at org.springframework.web.context.ContextLoader.configureAndRefreshWebApplicationContext(ContextLoader.java:383)
at org.springframework.web.context.ContextLoader.initWebApplicationContext(ContextLoader.java:283)
at org.springframework.web.context.ContextLoaderListener.contextInitialized(ContextLoaderListener.java:111)
at org.mortbay.jetty.handler.ContextHandler.startContext(ContextHandler.java:548)
at org.mortbay.jetty.servlet.Context.startContext(Context.java:136)
at org.mortbay.jetty.webapp.WebAppContext.startContext(WebAppContext.java:1250)
at org.mortbay.jetty.handler.ContextHandler.doStart(ContextHandler.java:517)
at org.mortbay.jetty.webapp.WebAppContext.doStart(WebAppContext.java:467)
at org.mortbay.component.AbstractLifeCycle.start(AbstractLifeCycle.java:50)
at org.mortbay.jetty.handler.HandlerCollection.doStart(HandlerCollection.java:152)
at org.mortbay.jetty.handler.ContextHandlerCollection.doStart(ContextHandlerCollection.java:156)
at org.mortbay.component.AbstractLifeCycle.start(AbstractLifeCycle.java:50)
at org.mortbay.jetty.handler.HandlerCollection.doStart(HandlerCollection.java:152)
at org.mortbay.component.AbstractLifeCycle.start(AbstractLifeCycle.java:50)
at org.mortbay.jetty.handler.HandlerWrapper.doStart(HandlerWrapper.java:130)
at org.mortbay.jetty.Server.doStart(Server.java:224)
at org.mortbay.component.AbstractLifeCycle.start(AbstractLifeCycle.java:50)
at org.mortbay.xml.XmlConfiguration.main(XmlConfiguration.java:985)
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:606)
at org.mortbay.start.Main.invokeMain(Main.java:194)
at org.mortbay.start.Main.start(Main.java:534)
at org.mortbay.start.Main.start(Main.java:441)
at org.mortbay.start.Main.main(Main.java:119)
答案 0 :(得分:1)
好的,所以这并不是对这个问题的直接回答,因为我忘了提到我也使用Spring,但是,我们要替换的类在堆栈跟踪中被提及。
当我一年后最初提出这个问题时,我回到了我一直在研究的项目。例外仍然存在,没有人愿意处理它们,但这次他们真的搞乱了我的调试。当我打开AnnotationSessionFactoryBean源并查找#executeSchemaStatement()(在其父LocalSessionFactoryBean中)时,我发现了以下javadoc:
/**
* Execute the given schema SQL on the given JDBC Statement.
* <p>Note that the default implementation will log unsuccessful statements
* and continue to execute. Override this method to treat failures differently.
* @param stmt the JDBC Statement to execute the SQL on
* @param sql the SQL statement to execute
* @throws SQLException if thrown by JDBC methods (and considered fatal)
*/
所以,“覆盖此方法以不同方式处理故障。”
基本上就是这样。我已经将AnnotationSessionFactoryBean子类化并重写了方法:
public class IndexErrorWrappingSessionFactoryBean extends AnnotationSessionFactoryBean {
@Override
protected void executeSchemaStatement(Statement stmt, String sql) throws SQLException {
if (logger.isDebugEnabled()) {
logger.debug("Executing schema statement: " + sql);
}
try {
stmt.executeUpdate(sql);
}
catch (SQLException ex) {
if (logger.isWarnEnabled()) {
if (ex instanceof PSQLException
&& sql.startsWith("create index")
&& ex.getMessage() != null
&& ex.getMessage().endsWith("already exists")) {
logger.warn("Unsuccessful schema statement: " + sql + " (index already exists)");
} else {
logger.warn("Unsuccessful schema statement: " + sql, ex);
}
}
}
}
}
现在我的输出中没有那些垃圾。