Spring 引导 *.hbm.xml 映射文件未在测试中加载
Spring Boot *.hbm.xml mapping files not loaded in test
问题比较难解释,请看项目:https://github.com/darzz/boot_bug
这是重现错误的最小设置。
描述:
应用程序堆栈是 Spring Boot with Spring Data 和 Spring Batch。
src/main/resources/queries.
下有testNamedQuery.hbm.xml文件
当 运行 from Application class 批处理作业成功完成,日志中没有异常。但是,当运行 from ApplicationNotWorking class时,也就是精确拷贝,直接放到测试源根目录下,批处理作业失败:
Caused by: org.hibernate.MappingException: Named query not known: findPersonNames
at org.hibernate.internal.AbstractSessionImpl.getNamedQuery(AbstractSessionImpl.java:177) ~[hibernate-core-4.3.11.Final.jar:4.3.11.Final]
at org.springframework.batch.item.database.HibernateItemReaderHelper.createQuery(HibernateItemReaderHelper.java:146) ~[spring-batch-infrastructure-3.0.5.RELEASE.jar:3.0.5.RELEASE]
at org.springframework.batch.item.database.HibernateItemReaderHelper.getForwardOnlyCursor(HibernateItemReaderHelper.java:123) ~[spring-batch-infrastructure-3.0.5.RELEASE.jar:3.0.5.RELEASE]
at org.springframework.batch.item.database.HibernateCursorItemReader.doOpen(HibernateCursorItemReader.java:185) ~[spring-batch-infrastructure-3.0.5.RELEASE.jar:3.0.5.RELEASE]
at org.springframework.batch.item.support.AbstractItemCountingItemStreamItemReader.open(AbstractItemCountingItemStreamItemReader.java:144) ~[spring-batch-infrastructure-3.0.5.RELEASE.jar:3.0.5.RELEASE]
... 39 common frames omitted
所以看起来当运行测试时,*.hbm.xml文件没有加载!
经过研究和调试,我想,我可能找到了原因——持久性单元根 url 被设置为测试 target/test-classes,但映射文件在 /target/classes 中。
我认为可能的原因可能与此处描述的内容相似http://blog.carbonfive.com/2007/05/17/using-classpath-vs-classpath-when-loading-spring-resources/
但我不知道如何在 Spring 引导中解决此问题,而不创建 persistence.xml 配置仅用于测试目的。也不想将 *.hbm.xml 文件从 main/resources 复制到 test/resources。
有人知道吗?
如果我对问题的理解正确,你想要 运行 Spring 引导测试应该从 classpath.
中获取 *.hbm 文件
您将 *.hbm 文件保存在哪里?
您必须确保所有 *.hbm 文件都保存在 src/main/resources. 因此当您 运行 测试 class 时调用实际的 class,它引用 src/main/resources.
中的 *.hbm 文件
如果上述解决方案没有帮助,那么您需要共享您的项目文件结构。
我调查了 git 项目。看来您需要更改 ApplicationNotWorking.java 因为它是一个测试 class 因此应该如下所示:
//src/test/java
package bug;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import com.Whosebug.springboot.BatchProcessing;
@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(classes = Application.class )
public class ApplicationNotWorking {
//Inject required bean which you want to test.
@Autowired
private BatchProcessing bProcess;
//If above @Autowired BatchProcessing do not work then you can object
//directly to kick off the test. BatchProcessing bProcess = new
//BatchProcessing();
//This way you can test each method
@Test
public void testBatchProcessing(){
System.out.println("***BatchProcessing: " + bProcess.batchProcess());
}
}
@Autowired
private ResourceLoader rl;
@Bean
public LocalSessionFactoryBean sessionFactory() throws IOException {
LocalSessionFactoryBean sessionFactoryBean = new LocalSessionFactoryBean();
sessionFactoryBean.setMappingLocations(loadResources());
return sessionFactoryBean;
}
public Resource[] loadResources() {
Resource[] resources = null;
try {
resources = ResourcePatternUtils.getResourcePatternResolver(rl)
.getResources("classpath:/hibernate/*.hbm.xml");
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return resources;
}
问题比较难解释,请看项目:https://github.com/darzz/boot_bug 这是重现错误的最小设置。
描述: 应用程序堆栈是 Spring Boot with Spring Data 和 Spring Batch。 src/main/resources/queries.
下有testNamedQuery.hbm.xml文件当 运行 from Application class 批处理作业成功完成,日志中没有异常。但是,当运行 from ApplicationNotWorking class时,也就是精确拷贝,直接放到测试源根目录下,批处理作业失败:
Caused by: org.hibernate.MappingException: Named query not known: findPersonNames
at org.hibernate.internal.AbstractSessionImpl.getNamedQuery(AbstractSessionImpl.java:177) ~[hibernate-core-4.3.11.Final.jar:4.3.11.Final]
at org.springframework.batch.item.database.HibernateItemReaderHelper.createQuery(HibernateItemReaderHelper.java:146) ~[spring-batch-infrastructure-3.0.5.RELEASE.jar:3.0.5.RELEASE]
at org.springframework.batch.item.database.HibernateItemReaderHelper.getForwardOnlyCursor(HibernateItemReaderHelper.java:123) ~[spring-batch-infrastructure-3.0.5.RELEASE.jar:3.0.5.RELEASE]
at org.springframework.batch.item.database.HibernateCursorItemReader.doOpen(HibernateCursorItemReader.java:185) ~[spring-batch-infrastructure-3.0.5.RELEASE.jar:3.0.5.RELEASE]
at org.springframework.batch.item.support.AbstractItemCountingItemStreamItemReader.open(AbstractItemCountingItemStreamItemReader.java:144) ~[spring-batch-infrastructure-3.0.5.RELEASE.jar:3.0.5.RELEASE]
... 39 common frames omitted
所以看起来当运行测试时,*.hbm.xml文件没有加载! 经过研究和调试,我想,我可能找到了原因——持久性单元根 url 被设置为测试 target/test-classes,但映射文件在 /target/classes 中。
我认为可能的原因可能与此处描述的内容相似http://blog.carbonfive.com/2007/05/17/using-classpath-vs-classpath-when-loading-spring-resources/
但我不知道如何在 Spring 引导中解决此问题,而不创建 persistence.xml 配置仅用于测试目的。也不想将 *.hbm.xml 文件从 main/resources 复制到 test/resources。
有人知道吗?
如果我对问题的理解正确,你想要 运行 Spring 引导测试应该从 classpath.
中获取 *.hbm 文件您将 *.hbm 文件保存在哪里?
您必须确保所有 *.hbm 文件都保存在 src/main/resources. 因此当您 运行 测试 class 时调用实际的 class,它引用 src/main/resources.
中的 *.hbm 文件如果上述解决方案没有帮助,那么您需要共享您的项目文件结构。
我调查了 git 项目。看来您需要更改 ApplicationNotWorking.java 因为它是一个测试 class 因此应该如下所示:
//src/test/java
package bug;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import com.Whosebug.springboot.BatchProcessing;
@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(classes = Application.class )
public class ApplicationNotWorking {
//Inject required bean which you want to test.
@Autowired
private BatchProcessing bProcess;
//If above @Autowired BatchProcessing do not work then you can object
//directly to kick off the test. BatchProcessing bProcess = new
//BatchProcessing();
//This way you can test each method
@Test
public void testBatchProcessing(){
System.out.println("***BatchProcessing: " + bProcess.batchProcess());
}
}
@Autowired
private ResourceLoader rl;
@Bean
public LocalSessionFactoryBean sessionFactory() throws IOException {
LocalSessionFactoryBean sessionFactoryBean = new LocalSessionFactoryBean();
sessionFactoryBean.setMappingLocations(loadResources());
return sessionFactoryBean;
}
public Resource[] loadResources() {
Resource[] resources = null;
try {
resources = ResourcePatternUtils.getResourcePatternResolver(rl)
.getResources("classpath:/hibernate/*.hbm.xml");
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return resources;
}