如何检索Spring的实体经理工厂?

时间:2018-01-31 15:52:45

标签: java spring classcastexception applicationcontext

我正在尝试write some JUnit tests for a Spring 2.0.7 application

在我的应用程序上下文XML文件中,我有这个bean:

<bean class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean" 
      id="entityManagerFactory"> ... </bean>

在我的DAO中,我只是注释了实体管理器的setter,Spring完成了所有的魔术:

@PersistenceContext
public void setEntityManager(EntityManager em) {
    this.em = em;
}

在Spring 2.5+中,我只想用@RunWith(SpringJUnit4ClassRunner.class)@ContextConfiguration(locations = {"/applicationContext-test.xml"})注释我的测试类。但是我的Spring版本太旧了,没有SpringJUnit4ClassRunner。因此,我的JUnit测试没有Spring魔法。相反,我自己就是这样做的:

// Load the XML file myself
XmlWebApplicationContext appContext = new XmlWebApplicationContext();
appContext.setConfigLocations(new String[] { "classpath:applicationContext-test.xml" });
appContext.refresh();

// Retrieve the entity manager factory
Object obj = appContext.getBean("entityManagerFactory");
// ***** The following line throws an exception: *****
LocalContainerEntityManagerFactoryBean aux = (LocalContainerEntityManagerFactoryBean) obj;
EntityManagerFactory emf = aux.getObject();

// Instantiate the EM and inject it into the DAOs
EntityManager em = emf.createEntityManager();
myDAO.setEntityManager(em);

我遇到 ClassCastException:当我尝试将obj转换为aux时,无法转换$ Proxy23 ... 异常。但是,如果我在Eclipse中设置断点并检查obj,那么它实际上 LocalContainerEntityManagerFactoryBean的一个实例。

我已经尝试了this approach,我在这里看到了很多问题。但是,AopUtils.isJdkDynamicProxy(obj)返回false。此外,即使尝试施放(Advised) obj也会引发相同的异常。

我还尝试将obj投射到FactoryBean,这是one of the interfaces implemented by LocalContainerEntityManagerFactoryBean ...是的,它会抛出相同的异常。这是令人困惑的,因为几乎每个“类强制转换异常代理”的答案都说“你只能转换为接口而不是类”。

所以,我的问题是:

  • 有没有办法修复我发布的代码? (是的,我希望我可以升级Spring!但不,我不能)。
  • OR:有没有其他方法可以使用XML文件中定义的EMF 实例化实体管理器?请注意,我不能这样做:
emf = Persistence.createEntityManagerFactory("myPersistenceUnit");
em = emf.createEntityManager();

工作正常,但我丢失了applicationContext-test.xml文件中定义的<aop:config><tx:advice>条目。

1 个答案:

答案 0 :(得分:2)

您可以使用其他版本的<template> <div style="height: 100%" class="table-chart" ref="root"> <div class="title" ref="title">{{ objectData.title }}</div> <div class="ag-dashboard" style="height: 100%; width: 90%; margin: 0 auto"> <ag-grid-vue :style="{ height: tableHeight }" :gridOptions="gridOptions" :columnDefs="columnDefs" :rowData="rowData" /> </div> </div> </template> <script> export default { components: { 'HeaderComponent': { template: '<span>{{this.params.displayName}} <span @click="custom">CLICK</span></span>', methods: { custom() { // emmit an event here or find a way to comunnicate with the function "customEvent" below } } } }, methods: { customEvent() { console.log('Event from header'); } }, beforeMount() { // ... setup Ag-Grid and the HeaderComponent in the columns' headerComponentFramework } } </script> 方法更严格地定义所需类型,请参阅official Spring 2.0 JavaDoc

getBean(...)

指出:

  

requiredType - 键入bean必须匹配。可以是实际类的接口或超类,也可以是任何匹配的null。例如,如果值为Object.class,则无论返回实例的类是什么,此方法都将成功。

因此,要解决使用强制转换的问题,您需要以这种方式实现它:

public Object getBean(String name, Class requiredType)

有了这个,你将直接检索一个&#34;中立&#34; // Retrieve the entity manager factory EntityManagerFactory emf = (EntityManagerFactory) appContext.getBean("entityManagerFactory", javax.persistence.EntityManagerFactory.class); ,与JPA规范中描述的接口兼容。在运行时,这将是一个代理对象,但您可以按照原先的预期方式使用它:

EMF

希望它有所帮助。