[编辑] 这个问题已经在 Hibernate 5.0.7 中得到解决,参见HHH-4161。
根据HHH-4161 的最新更新,此问题也出现在 Hibernate 5.0.2 上,并计划在 Hibernate 5.0.5 中解决。
在本期中,I proposed a workaround 基于一个自定义的 Scanner 类,该类管理相对 URL 并将它们绝对化。我将AbstractScannerImpl源代码复制到test.MyCustomScanner中,添加StandardScanner的构造函数,在environment.getNonRootUrls()循环中添加如下代码:
if (!url.getPath().startsWith("/")) {
// relative URL => make it processed relatively to the root URL of the META-INF/persistence.xml
// This means that rootUrl has a META-INF directory (but the rootUrl has no META-INF in path).
// See JPA 2.1 specification page 366-368: http://download.oracle.com/otn-pub/jcp/persistence-2_1-fr-eval-spec/JavaPersistence.pdf
// Note: while the solution looks smart, the getNonRootUrls may include more
// than the <jar-file>. Thus, it may have side effects.
try {
URL absoluteUrl = new URL(environment.getRootUrl(),url.getPath());
url=absoluteUrl;
} catch (MalformedURLException e) {
throw new RuntimeException("cannot make the relative URL as absolute:"+url);
}
}
精神与 Lauri Harpf 的拉取请求 (https://github.com/hibernate/hibernate-orm/pull/889/files) 相同,但优先考虑相对 URL,并使用相对 URL 测试而不是异常捕获机制。
这种方法的风险在于,所有非根 URL 都以相同的方式进行管理,而不仅仅是 <jar-file> 标记的那些。因此,可能会出现副作用。
然后将自定义扫描仪添加到 persistence.xml:
<property name="hibernate.ejb.resource_scanner" value="test.MyCustomScanner" />
运行时,执行日志没有显示异常,只提示MyEntity表不存在,说明entities.jar已经被正确处理:
oct. 30, 2015 8:11:50 PM org.hibernate.jpa.internal.util.LogHelper logPersistenceUnitInformation
INFO: HHH000204: Processing PersistenceUnitInfo [
name: test-hibernate2
...]
oct. 30, 2015 8:11:51 PM org.hibernate.Version logVersion
INFO: HHH000412: Hibernate Core {5.0.2.Final}
oct. 30, 2015 8:11:51 PM org.hibernate.cfg.Environment <clinit>
INFO: HHH000206: hibernate.properties not found
oct. 30, 2015 8:11:51 PM org.hibernate.cfg.Environment buildBytecodeProvider
INFO: HHH000021: Bytecode provider name : javassist
oct. 30, 2015 8:11:51 PM org.hibernate.boot.internal.MetadataBuilderImpl$MetadataBuildingOptionsImpl <init>
INFO: HHH90000001: Found usage of deprecated setting for specifying Scanner [hibernate.ejb.resource_scanner]; use [hibernate.archive.scanner] instead
oct. 30, 2015 8:11:51 PM org.hibernate.annotations.common.reflection.java.JavaReflectionManager <clinit>
INFO: HCANN000001: Hibernate Commons Annotations {5.0.0.Final}
oct. 30, 2015 8:11:51 PM org.hibernate.engine.jdbc.connections.internal.DriverManagerConnectionProviderImpl configure
WARN: HHH000402: Using Hibernate built-in connection pool (not for production use!)
oct. 30, 2015 8:11:51 PM org.hibernate.engine.jdbc.connections.internal.DriverManagerConnectionProviderImpl buildCreator
INFO: HHH000401: using driver [org.hsqldb.jdbcDriver] at URL [jdbc:hsqldb:mem:testdb]
oct. 30, 2015 8:11:51 PM org.hibernate.engine.jdbc.connections.internal.DriverManagerConnectionProviderImpl buildCreator
INFO: HHH000046: Connection properties: {user=sa}
oct. 30, 2015 8:11:51 PM org.hibernate.engine.jdbc.connections.internal.DriverManagerConnectionProviderImpl buildCreator
INFO: HHH000006: Autocommit mode: false
oct. 30, 2015 8:11:51 PM org.hibernate.engine.jdbc.connections.internal.DriverManagerConnectionProviderImpl configure
INFO: HHH000115: Hibernate connection pool size: 20 (min=1)
oct. 30, 2015 8:11:51 PM org.hibernate.dialect.Dialect <init>
INFO: HHH000400: Using dialect: org.hibernate.dialect.HSQLDialect
oct. 30, 2015 8:11:52 PM org.hibernate.tool.hbm2ddl.SchemaUpdate execute
INFO: HHH000228: Running hbm2ddl schema update
oct. 30, 2015 8:11:52 PM org.hibernate.tool.schema.extract.internal.InformationExtractorJdbcDatabaseMetaDataImpl processGetTableResults
INFO: HHH000262: Table not found: MyEntity
oct. 30, 2015 8:11:52 PM org.hibernate.tool.schema.extract.internal.InformationExtractorJdbcDatabaseMetaDataImpl processGetTableResults
INFO: HHH000262: Table not found: MyEntity
我在以前的一位客户中使用的另一种解决方法是在构建时根据应用程序类路径中 JAR 的依赖关系构建 <class> 标记列表。乍一看有点复杂,但它对应用程序提供了很好的控制:开发人员可以查看persistence.xml 以立即知道在运行时将加载哪些实体类。请注意,这种方法是在 2007 年使用的,早在我想到自定义 Scanner 解决方法之前。