在完成了几次与guice的合作之后,我尝试使用注释在当前版本中重新演绎spring框架。但是,我似乎无法在测试期间使用EntityManager
注释弹出@PersistenceContext
。这是我的设置:
的persistence.xml
<persistence
xmlns="http://java.sun.com/xml/ns/persistence"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/persistence
http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd" version="2.0">
<persistence-unit name="com.whatever.shop.database" transaction-type="RESOURCE_LOCAL">
<provider>org.hibernate.jpa.HibernatePersistenceProvider</provider>
<class>com.whatever.shop.domain.Product</class>
<class>com.whatever.shop.domain.Order</class>
<properties>
<property name="javax.persistence.jdbc.driver" value="org.hsqldb.jdbcDriver" />
<property name="javax.persistence.jdbc.url" value="jdbc:hsqldb:mem:testdb" />
<property name="javax.persistence.jdbc.user" value="sa" />
<property name="javax.persistence.jdbc.password" value="" />
<property name="hibernate.dialect" value="org.hibernate.dialect.HSQLDialect" />
<property name="hibernate.hbm2ddl.auto" value="update" />
</properties>
</persistence-unit>
</persistence>
具有持久化上下文的通用DAO实现
public abstract class GenericDAOImpl<T, PK extends Serializable> implements GenericDAO<T, PK> {
@PersistenceContext(unitName="com.whatever.shop.database")
private EntityManager entityManager;
private Class<T> entityType;
public GenericDAOImpl(Class<T> entityType) {
this.entityType = entityType;
}
@Override
public T getById(PK id) {
return entityManager.find(entityType, id);
}
// Some more methods
}
ProductDAOImpl
@Repository
public class ProductDAOImpl extends GenericDAOImpl<Product, Long> implements ProductDAO {
@PersistenceContext(unitName="com.whatever.shop.database")
private EntityManager entityManager;
public ProductDAOImpl() {
super(Product.class);
}
}
BeanConfig类,用于类定义的bean定义:
package com.whatever.shop.database;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
@Configuration
@ComponentScan(basePackages = {"com.whatever.shop.database.jpa"})
public class BeanConfig {
@Bean
public EntityManagerFactory entityManagerFactory() {
return Persistence.createEntityManagerFactory("com.whatever.shop.database");
}
@Bean
public EntityManager entityManager() {
return entityManagerFactory().createEntityManager();
}
}
最后,测试类我尝试注入:
package com.whatever.shop.database.jpa;
import static org.junit.Assert.fail;
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.whatever.shop.database.BeanConfig;
import com.whatever.shop.domain.Product;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes={BeanConfig.class})
public class ProductDAOTest {
@Autowired
private ProductDAO productDao;
/**
* Test method for {@link com.whatever.shop.database.GenericDAOImpl#getById(java.lang.Object)}.
*/
@Test
public void testGetById() {
productDao.save(new Product());
}
}
我对这应该如何运作的理解如下
EntityManagerFactory
@ComponentScan
注释应遍历我的所有DAO实现,检测@Repository
注释并执行PersistenceAnnotationBeanPostProcessor
类型位和bob。但是每当我运行测试时,NullPointerException
都会得到EntityManager
。 bean正在被实例化,但它没有连接到DAO。
答案 0 :(得分:0)
解决:
这里的问题是我试图像EntityManager
那样对待SessionFactory
。 Spring需要自己的工厂对象才能出现在上下文中,因此它知道在遇到@PersistenceContext
注释时要做什么。更改位于BeanConfig类中。
@Configuration
@ComponentScan(basePackages = {"com.whatever.shop.database.jpa"})
public class BeanConfig {
@Bean
public LocalContainerEntityManagerFactoryBean entityManagerFactory() {
LocalContainerEntityManagerFactoryBean thing = new LocalContainerEntityManagerFactoryBean();
thing.setPersistenceUnitName("com.whatever.shop.database");
return thing;
}
@Bean
public JpaTransactionManager transactionManager() {
JpaTransactionManager transactionManager = new JpaTransactionManager();
transactionManager.setEntityManagerFactory(entityManagerFactory().nativeEntityManagerFactory);
return transactionManager;
}
}