MyEclipse 10.7生成Hibernate 4.1时的一个BUG

因为工作需要,研究了一下Hibernate 4,在使用MyEclise 10.7自动生成代码时,程序始终报错如下:
org.hibernate.InvalidMappingException: Unable to read XML
at org.hibernate.internal.util.xml.MappingReader.readMappingDocument(MappingReader.java:109)
at org.hibernate.cfg.Configuration.add(Configuration.java:478)
at org.hibernate.cfg.Configuration.add(Configuration.java:474)
at org.hibernate.cfg.Configuration.add(Configuration.java:647)
at org.hibernate.cfg.Configuration.addResource(Configuration.java:730)
at org.hibernate.cfg.Configuration.parseMappingElement(Configuration.java:2109)
at org.hibernate.cfg.Configuration.parseSessionFactory(Configuration.java:2081)
at org.hibernate.cfg.Configuration.doConfigure(Configuration.java:2061)
at org.hibernate.cfg.Configuration.doConfigure(Configuration.java:2014)
at org.hibernate.cfg.Configuration.configure(Configuration.java:1929)
at org.hibernate.cfg.Configuration.configure(Configuration.java:1908)
at HibernateSessionFactory.rebuildSessionFactory(HibernateSessionFactory.java:69)
at HibernateSessionFactory.getSession(HibernateSessionFactory.java:53)
at BaseHibernateDAO.getSession(BaseHibernateDAO.java:13)
at SaleVolumeDAO.save(SaleVolumeDAO.java:28)
at Demo.main(Demo.java:16)
Caused by: org.dom4j.DocumentException: Connection timed out: connect Nested exception: Connection timed out: connect
at org.dom4j.io.SAXReader.read(SAXReader.java:484)
at org.hibernate.internal.util.xml.MappingReader.readMappingDocument(MappingReader.java:78)
... 15 more

因为在最后一行看到了Connection timed out,我就想当然地认为是连接数据库出现了问题,于是检查了jdbc url的配置,并且重启了数据库,还是没能解决问题。
经过近2个小时的折腾,我终于注意到在Connection timed out前面的Caused by: org.dom4j.DocumentException。这说明连接超时并不是由数据库引起的,而是由DOM4J解析XML时导致的。DOM4J在解析XML时,惟一可能连接网络的情况就是在DOCTYPE中声明的那个网址。于是我检查了,DOCTYPE,发现在hbm文件中的DOCTYPE是这样写的:

<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd ">
注意,在http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd后面有一个空格。我去除了这个空格,重新运行,问题解决了。

这里普及一下DOCTYPE格式的含义。DOCTYPE主要是在解析XML时,指定DTD文档的。DTD文件在xml中可以以两种形式给出:
<!DOCTYPE xml文档根元素的名称 (SYSTEM | PUBLIC)[DTD的名称] "外部文件DTD的uri">
<!DOCTYPE xml文档根元素的名称 [
    <!ELEMENT xml文档根元素的名称(#PCDATA)>
]>
其中外部DTD申明的时候可以用SYSTEM关键字或者PUBLIC关键字,一个表示是私有的DTD文件,一个表示公开的DTD文件.在使用PUBLIC的时候就必须给出一个DTD的名称,这个名称被称为公共标识符,多数xml处理程序会按照这个公共标识符在本地检索这个DTD,如果找不到则按照URI去引用这个DTD.其中uri地址可以是相对URI或者绝对URI。
公共DTD的名称要遵循一些约定.如果是ISO标准,那么要以ISO开头,如果是非ISO的标准组织要以+号开头,如果不是标准组织要以-号开头.然后紧跟一个//加上DTD所有者的名字//加上DTD描述的文档类型,再加上//和ISO 639语言标识符。

所以,按说DOM4J应该可以通过公共标识符识别出DTD来,而不用去连接网络。我没有看DOM4J的源代码,但估计它可能是对个整个DOCTYPE都验证了一下,结果发现和标准的不一致,就去连接网络了,结果网址又是错误的,就出错了。

就这么一个空格,浪费了我两个多小时的时间。

你可能感兴趣的:(Hibernate)