JPA:NoSuchBeanDefinitionException:没有定义名为 'myPU' 的 bean
JPA: NoSuchBeanDefinitionException: No bean named 'myPU' is defined
我正在将我们的网络应用程序从基于 XML 的 IoC、直接的 Hibernate 网络应用程序转换为使用注释和 JPA 2.1 的网络应用程序。我们的应用程序服务器是 WebLogic 12.1.3,我们使用 Spring 3.2.13 和 Hibernate 4.3.9。我们的架构是分层的,每一层都以其自己的 JAR 文件结尾。 EAR文件的布局如下:
|-EAR
|-- my-app.ear
|-- my-app.war
|-- lib
|-- my-web.jar
|-- my-services.jar
|-- my-jpa.jar
| |-- META-INF
| |-- persistence.xml
|-- someotherlib.jar
在 IoC 链的顶端是我们的 DelegateFactory,它被 Struts1 动作使用(我们稍后会升级它)。
@Configuration
@ComponentScan({"com.mycompany.myapp.dao.jpa"})
public class DelegateFactory
{
public static DelegateFactory getInstance()
{
if (singleton == null)
{
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
ctx.register(DelegateFactory.class);
ctx.refresh();
singleton = ctx.getBean(DelegateFactory.class);
ctx.close();
}
return singleton;
}
}
IoC 在查找 Web、服务和 DAO bean 时有效,但在尝试查找持久性单元时失败。下面是我们的 JPA DAO 的基础 class。它是一个普通的 DAO,而不是 Spring DAO。为了使其工作,我尝试同时注入 em 和 emf。
public abstract class AbstractMyProjectJpaDao extends AbstractJpaTypedDao
{
public static final String PERSISTENCE_UNIT_NAME = "myPU";
@PersistenceUnit(unitName = PERSISTENCE_UNIT_NAME, name = PERSISTENCE_UNIT_NAME)
@Override
public void setEntityManagerFactory(
EntityManagerFactory emf)
{
super.setEntityManagerFactory(emf);
}
@PersistenceContext(unitName = PERSISTENCE_UNIT_NAME, name = PERSISTENCE_UNIT_NAME, type = PersistenceContextType.TRANSACTION)
@Override
public void setEm(
EntityManager em)
{
super.setEm(em);
}
}
到目前为止,我们似乎唯一需要的 XML 文件是下面的 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="myPU" transaction-type="JTA">
<provider>org.hibernate.jpa.HibernatePersistenceProvider</provider>
<jta-data-source>java:/jdbc/myDS</jta-data-source>
(declaration of persistent entities here)
</persistence-unit>
</persistence>
这是失败的原因:
Caused By: org.springframework.beans.factory.NoSuchBeanDefinitionException: No bean named 'myPU' is defined
at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBeanDefinition(DefaultListableBeanFactory.java:575)
at org.springframework.beans.factory.support.AbstractBeanFactory.getMergedLocalBeanDefinition(AbstractBeanFactory.java:1111)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:276)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:195)
at org.springframework.orm.jpa.EntityManagerFactoryUtils.findEntityManagerFactory(EntityManagerFactoryUtils.java:110)
我的猜测是它找不到 persistence.xml 文件,但根据我的阅读,它在一个有效的位置。
我错过了什么?
尝试创建 PersistenceConfiguration。 repo.package
指向您可能使用的任何存储库位置,例如 Springs CRUD/JPA 存储库。 entity.package
指向您的 JPA DAO 所在的包。
@Configuration
@EnableTransactionManagement
@EnableJpaRepositories(
basePackages = {"repo.package"},
entityManagerFactoryRef = "entityManagerFactory",
transactionManagerRef = "transactionManager"
)
public class PersistenceConfiguration {
public static final HashSet<String> cacheNames = new HashSet<>();
private static final String[] PACKAGES_TO_SCAN = {"entities.package"};
private static final Properties hibernateProperties;
static {
hibernateProperties = new Properties();
hibernateProperties.setProperty("hibernate.connection.zeroDateTimeBehavior", "convertToNull");
hibernateProperties.setProperty("hibernate.dbcp.maxActive", "50");
hibernateProperties.setProperty("hibernate.dbcp.maxIdle", "10");
hibernateProperties.setProperty("hibernate.dbcp.maxWait", "5000");
hibernateProperties.setProperty("hibernate.jdbc.batch_size property", "50");
hibernateProperties.setProperty("hibernate.connection.charSet", "UTF-8");
hibernateProperties.setProperty("hibernate.connection.characterEncoding", "UTF-8");
hibernateProperties.setProperty("hibernate.connection.useUnicode", "true");
}
@Bean
public DataSource dataSource(){
DriverManagerDataSource dataSource = new DriverManagerDataSource();
dataSource.setDriverClassName("database.driver");
dataSource.setUrl("database url");
dataSource.setUsername( "tutorialuser" );
dataSource.setPassword( "tutorialmy5ql" );
return dataSource;
}
/**
* Create the entity manager factory bean used in the database connection
* @return entityManagerFactoryBean
*/
@Primary
@Bean
public LocalContainerEntityManagerFactoryBean entityManagerFactory() {
LocalContainerEntityManagerFactoryBean lef = new LocalContainerEntityManagerFactoryBean();
lef.setDataSource(dataSource);
lef.setJpaVendorAdapter(portalJpaVendorAdapter());
lef.setPackagesToScan(PACKAGES_TO_SCAN);
lef.setJpaProperties(hibernateProperties);
lef.setPersistenceUnitName("my_pu");
return lef;
}
/**
* Create the session factory bean
* @return sessionFactoryBean
*/
@Bean
public LocalSessionFactoryBean sessionFactory() {
LocalSessionFactoryBean sessionBean = new LocalSessionFactoryBean();
sessionBean.setDataSource(dataSource);
sessionBean.setPackagesToScan(PACKAGES_TO_SCAN);
sessionBean.setHibernateProperties(hibernateProperties);
return sessionBean;
}
/**
* Create the JPA Vendor adaptor bean that is used in the entity manager factory
* @return jpaVendorAdaptor
*/
@Primary
@Bean
public JpaVendorAdapter jpaVendorAdapter() {
HibernateJpaVendorAdapter hibernateJpaVendorAdapter = new HibernateJpaVendorAdapter();
hibernateJpaVendorAdapter.setShowSql(false);
hibernateJpaVendorAdapter.setGenerateDdl(false);
hibernateJpaVendorAdapter.setDatabase(Database.MYSQL);
return hibernateJpaVendorAdapter;
}
/**
* Create the transaction manager bean
* @return transactionManager
*/
@Primary
@Bean
public PlatformTransactionManager transactionManager() {
JpaTransactionManager manager = new JpaTransactionManager();
manager.setEntityManagerFactory(portalEntityManagerFactory().getObject());
return new JpaTransactionManager();
}
}
如果您已经创建了数据源 bean,则可以自动装配它而不是直接创建 bean。
问题的第一部分是我没有插入 EntityManagerFactory。我最终创建了一个 dao-beans.xml 文件:
<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalEntityManagerFactoryBean">
<property name="persistenceUnitName" value="myPU" />
</bean>
然后我必须将 @ImportResource 注释添加到我的 DelegateFactory 以便可以找到 XML 文件。
@Configuration
@ComponentScan({"com.mycompany.myapp.dao.jpa"})
@ImportResource("classpath:dao-beans.xml")
public class DelegateFactory
{
...
}
我还必须将 persistence.xml 中数据源的 JNDI 名称从 "java:/jdbc/myDS" 更改为 "jdbc/myDS"。我认为这是 WebLogic 的事情。
我正在将我们的网络应用程序从基于 XML 的 IoC、直接的 Hibernate 网络应用程序转换为使用注释和 JPA 2.1 的网络应用程序。我们的应用程序服务器是 WebLogic 12.1.3,我们使用 Spring 3.2.13 和 Hibernate 4.3.9。我们的架构是分层的,每一层都以其自己的 JAR 文件结尾。 EAR文件的布局如下:
|-EAR
|-- my-app.ear
|-- my-app.war
|-- lib
|-- my-web.jar
|-- my-services.jar
|-- my-jpa.jar
| |-- META-INF
| |-- persistence.xml
|-- someotherlib.jar
在 IoC 链的顶端是我们的 DelegateFactory,它被 Struts1 动作使用(我们稍后会升级它)。
@Configuration
@ComponentScan({"com.mycompany.myapp.dao.jpa"})
public class DelegateFactory
{
public static DelegateFactory getInstance()
{
if (singleton == null)
{
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
ctx.register(DelegateFactory.class);
ctx.refresh();
singleton = ctx.getBean(DelegateFactory.class);
ctx.close();
}
return singleton;
}
}
IoC 在查找 Web、服务和 DAO bean 时有效,但在尝试查找持久性单元时失败。下面是我们的 JPA DAO 的基础 class。它是一个普通的 DAO,而不是 Spring DAO。为了使其工作,我尝试同时注入 em 和 emf。
public abstract class AbstractMyProjectJpaDao extends AbstractJpaTypedDao
{
public static final String PERSISTENCE_UNIT_NAME = "myPU";
@PersistenceUnit(unitName = PERSISTENCE_UNIT_NAME, name = PERSISTENCE_UNIT_NAME)
@Override
public void setEntityManagerFactory(
EntityManagerFactory emf)
{
super.setEntityManagerFactory(emf);
}
@PersistenceContext(unitName = PERSISTENCE_UNIT_NAME, name = PERSISTENCE_UNIT_NAME, type = PersistenceContextType.TRANSACTION)
@Override
public void setEm(
EntityManager em)
{
super.setEm(em);
}
}
到目前为止,我们似乎唯一需要的 XML 文件是下面的 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="myPU" transaction-type="JTA">
<provider>org.hibernate.jpa.HibernatePersistenceProvider</provider>
<jta-data-source>java:/jdbc/myDS</jta-data-source>
(declaration of persistent entities here)
</persistence-unit>
</persistence>
这是失败的原因:
Caused By: org.springframework.beans.factory.NoSuchBeanDefinitionException: No bean named 'myPU' is defined
at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBeanDefinition(DefaultListableBeanFactory.java:575)
at org.springframework.beans.factory.support.AbstractBeanFactory.getMergedLocalBeanDefinition(AbstractBeanFactory.java:1111)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:276)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:195)
at org.springframework.orm.jpa.EntityManagerFactoryUtils.findEntityManagerFactory(EntityManagerFactoryUtils.java:110)
我的猜测是它找不到 persistence.xml 文件,但根据我的阅读,它在一个有效的位置。
我错过了什么?
尝试创建 PersistenceConfiguration。 repo.package
指向您可能使用的任何存储库位置,例如 Springs CRUD/JPA 存储库。 entity.package
指向您的 JPA DAO 所在的包。
@Configuration
@EnableTransactionManagement
@EnableJpaRepositories(
basePackages = {"repo.package"},
entityManagerFactoryRef = "entityManagerFactory",
transactionManagerRef = "transactionManager"
)
public class PersistenceConfiguration {
public static final HashSet<String> cacheNames = new HashSet<>();
private static final String[] PACKAGES_TO_SCAN = {"entities.package"};
private static final Properties hibernateProperties;
static {
hibernateProperties = new Properties();
hibernateProperties.setProperty("hibernate.connection.zeroDateTimeBehavior", "convertToNull");
hibernateProperties.setProperty("hibernate.dbcp.maxActive", "50");
hibernateProperties.setProperty("hibernate.dbcp.maxIdle", "10");
hibernateProperties.setProperty("hibernate.dbcp.maxWait", "5000");
hibernateProperties.setProperty("hibernate.jdbc.batch_size property", "50");
hibernateProperties.setProperty("hibernate.connection.charSet", "UTF-8");
hibernateProperties.setProperty("hibernate.connection.characterEncoding", "UTF-8");
hibernateProperties.setProperty("hibernate.connection.useUnicode", "true");
}
@Bean
public DataSource dataSource(){
DriverManagerDataSource dataSource = new DriverManagerDataSource();
dataSource.setDriverClassName("database.driver");
dataSource.setUrl("database url");
dataSource.setUsername( "tutorialuser" );
dataSource.setPassword( "tutorialmy5ql" );
return dataSource;
}
/**
* Create the entity manager factory bean used in the database connection
* @return entityManagerFactoryBean
*/
@Primary
@Bean
public LocalContainerEntityManagerFactoryBean entityManagerFactory() {
LocalContainerEntityManagerFactoryBean lef = new LocalContainerEntityManagerFactoryBean();
lef.setDataSource(dataSource);
lef.setJpaVendorAdapter(portalJpaVendorAdapter());
lef.setPackagesToScan(PACKAGES_TO_SCAN);
lef.setJpaProperties(hibernateProperties);
lef.setPersistenceUnitName("my_pu");
return lef;
}
/**
* Create the session factory bean
* @return sessionFactoryBean
*/
@Bean
public LocalSessionFactoryBean sessionFactory() {
LocalSessionFactoryBean sessionBean = new LocalSessionFactoryBean();
sessionBean.setDataSource(dataSource);
sessionBean.setPackagesToScan(PACKAGES_TO_SCAN);
sessionBean.setHibernateProperties(hibernateProperties);
return sessionBean;
}
/**
* Create the JPA Vendor adaptor bean that is used in the entity manager factory
* @return jpaVendorAdaptor
*/
@Primary
@Bean
public JpaVendorAdapter jpaVendorAdapter() {
HibernateJpaVendorAdapter hibernateJpaVendorAdapter = new HibernateJpaVendorAdapter();
hibernateJpaVendorAdapter.setShowSql(false);
hibernateJpaVendorAdapter.setGenerateDdl(false);
hibernateJpaVendorAdapter.setDatabase(Database.MYSQL);
return hibernateJpaVendorAdapter;
}
/**
* Create the transaction manager bean
* @return transactionManager
*/
@Primary
@Bean
public PlatformTransactionManager transactionManager() {
JpaTransactionManager manager = new JpaTransactionManager();
manager.setEntityManagerFactory(portalEntityManagerFactory().getObject());
return new JpaTransactionManager();
}
}
如果您已经创建了数据源 bean,则可以自动装配它而不是直接创建 bean。
问题的第一部分是我没有插入 EntityManagerFactory。我最终创建了一个 dao-beans.xml 文件:
<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalEntityManagerFactoryBean">
<property name="persistenceUnitName" value="myPU" />
</bean>
然后我必须将 @ImportResource 注释添加到我的 DelegateFactory 以便可以找到 XML 文件。
@Configuration
@ComponentScan({"com.mycompany.myapp.dao.jpa"})
@ImportResource("classpath:dao-beans.xml")
public class DelegateFactory
{
...
}
我还必须将 persistence.xml 中数据源的 JNDI 名称从 "java:/jdbc/myDS" 更改为 "jdbc/myDS"。我认为这是 WebLogic 的事情。