我有一个使用基本Hibernate会话工厂的Java程序。我遇到了hibernate hbm.xml映射文件的问题,即使我在try catch中调用了getSessionFactory()
,它也崩溃了我的程序
try
{
session = SessionFactoryUtil.getSessionFactory().openStatelessSession();
session.beginTransaction();
rh = getRunHistoryEntry(session);
if(rh == null)
{
throw new Exception("No run history information found in the database for run id " + runId_ + "!");
}
}
catch(Exception ex)
{
logger.error("Error initializing hibernate");
}
它仍然设法突破这个try / catch并使主线程崩溃。我如何防止它这样做?主要问题是我有一堆清理命令,需要在主线程关闭之前运行,并且需要能够保证即使在失败之后它仍然可以清理并且稍微优雅地下降。会话工厂看起来像这样:
public class SessionFactoryUtil {
private static final SessionFactory sessionFactory;
static {
try
{
// Create the SessionFactory from hibernate.cfg.xml
sessionFactory = new Configuration().configure().buildSessionFactory();
}
catch (Throwable ex)
{
// Make sure you log the exception, as it might be swallowed
System.err.println("Initial SessionFactory creation failed." + ex);
throw new ExceptionInInitializerError(ex);
}
}
public static SessionFactory getSessionFactory()
{ try
{
return sessionFactory;
}
catch(Exception ex)
{
return null;
}
}
}
抛出的错误如下,我已修复它,但我想防止任何hibernate初始化错误停止主线程。
Initial SessionFactory creation failed.org.hibernate.InvalidMappingException: Could not parse mapping document from resource hibernate/TmdIndataLine.hbm.xml
Exception in thread "main" java.lang.ExceptionInInitializerError
at com.ryanco.db.SessionFactoryUtil.<clinit>(SessionFactoryUtil.java:19)
at com.ryanco.rta.RtaMain.main(RtaMain.java:148)
Caused by: org.hibernate.InvalidMappingException: Could not parse mapping document from resource hibernate/TmdIndataLine.hbm.xml
at org.hibernate.cfg.Configuration.addResource(Configuration.java:616)
at org.hibernate.cfg.Configuration.parseMappingElement(Configuration.java:1635)
at org.hibernate.cfg.Configuration.parseSessionFactory(Configuration.java:1603)
at org.hibernate.cfg.Configuration.doConfigure(Configuration.java:1582)
at org.hibernate.cfg.Configuration.doConfigure(Configuration.java:1556)
at org.hibernate.cfg.Configuration.configure(Configuration.java:1476)
at org.hibernate.cfg.Configuration.configure(Configuration.java:1462)
at com.ryanco.db.SessionFactoryUtil.<clinit>(SessionFactoryUtil.java:13)
... 1 more
Caused by: org.hibernate.InvalidMappingException: Could not parse mapping document from input stream
at org.hibernate.cfg.Configuration.addInputStream(Configuration.java:555)
at org.hibernate.cfg.Configuration.addResource(Configuration.java:613)
... 8 more
Caused by: org.dom4j.DocumentException: Error on line 114 of document : The element type "class" must be terminated by the matching end-tag "</class>". Nested exception: The element type "class" must be terminated by the matching end-tag "</class>".
at org.dom4j.io.SAXReader.read(SAXReader.java:482)
at org.hibernate.cfg.Configuration.addInputStream(Configuration.java:546)
... 9 more
答案 0 :(得分:1)
SessionFactoryUtil中的静态初始化程序对所有Throwable实例都有一个try / catch,但是你的主try / catch块只捕获异常。我会改变它以捕捉Throwables,看看是否能解决问题。
答案 1 :(得分:0)
那么,根据您编写的应用程序类型,静态初始化程序执行任何到达JVM外部的操作通常都是一个坏主意。
问题:如果我正确地读了你的代码,你首先会在Throwable
的静态初始化器中捕获所有SessionFactoryUtil
,向标准错误写一条错误消息然后抛出一个新的ExceptionInInitializerError
自己,将cat Throwable
包裹在其中。
在加载类之后,首先调用IIRC静态初始化器。堆栈跟踪告诉我们这可能来自类RtaMain
中的main方法,因为SessionFactoryUtil.getSessionFactory()
似乎是从那里调用的,这会触发类加载。
要捕获此错误,您需要在类getSessionFactory()
的main方法中调用RtaUtil
周围的try / catch,捕获Throwable,或至少在静态初始化程序中抛出的特定throwable你自己,ExceptionInInitializerError
。
HTH
答案 2 :(得分:0)
它仍然设法突破这个try / catch并使主线程崩溃。
如前所述,main方法中的这个bloc不会捕获静态初始值设定项中抛出的ExceptionInInitializerError
:
catch(Exception ex) {
logger.error("Error initializing hibernate")
}
如果你想同时抓住Exception
和Error
,你应该catch (Throwable t)
(顺便说一句,我注意到你说你改变了但是我想知道你改变了什么确切地说,你得到的错误。
但说实话,如果SessionFactory
未能初始化,我想知道你在main
方法中要做什么,实际上通常的做法是让程序失败。情况下。
最后,这部分的try/catch
似乎完全没用:
public static SessionFactory getSessionFactory() {
try {
return sessionFactory;
} catch(Exception ex) {
return null;
}
}
您可以安全地将其删除。