JPA:NoSuchBeanDefinitionException:没有定义名为'myPU'的bean

时间:2018-02-01 23:32:30

标签: spring hibernate jpa spring-bean

我正在将我们的webapp从基于XML的IoC,直接Hibernate webapp转换为使用注释和JPA 2.1的webapp。我们的应用服务器是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的基类。它是一个简单的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文件,但根据我所读到的,它位于有效位置。

我错过了什么?

2 个答案:

答案 0 :(得分:0)

尝试创建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。

答案 1 :(得分:0)

问题的第一部分是我没有插入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
{
...
}

我还必须从&#34; java:/ jdbc / myDS&#34;更改persistence.xml中数据源的JNDI名称。只是&#34; jdbc / myDS&#34;。我认为这是一个WebLogic的事情。