【问题标题】:Spring-boot+JPA EntityManager inject failsSpring-boot+JPA EntityManager 注入失败
【发布时间】:2015-08-25 13:01:01
【问题描述】:

在我的 J2EE 应用程序中,我尝试使用 spring-boot 和 JPA 技术,并将 EntityManager 注入 DAO 层。但是,我有一些问题......我的用户 CRUD 存储库:

@Repository
public class UserRepositoryImpl implements UserRepository {

@PersistenceContext(unitName = "data")
private EntityManager entityManager;
// and crud methods
}

我的 spring-boot 应用类:

@SpringBootApplication
public class App {
    public static void main(String [] args) {
        SpringApplication.run(App.class, args);
    }

}

最后是我的 persistence.xml,位于 src/main/resources/META-INF 文件夹中:

<?xml version="1.0" encoding="UTF-8"?>
<persistence version="2.0"
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">
<persistence-unit name="data" transaction-type="RESOURCE_LOCAL">
    <provider>org.hibernate.jpa.HibernatePersistenceProvider</provider>
    <class>com.example.domain.User</class>
    <exclude-unlisted-classes>true</exclude-unlisted-classes>
    <properties>
        <property name="hibernate.connection.autocommit" value="false" />
        <property name="hibernate.dialect" value="org.hibernate.dialect.SQLServerDialect" />
        <property name="hibernate.c3p0.min_size" value="4" />
        <property name="hibernate.c3p0.max_size" value="128" />
        <property name="javax.persistence.jdbc.url" value="jdbc:sqlserver://localhost:1433;databaseName=qwerty;sendStringParametersAsUnicode=false" />
        <property name="javax.persistence.jdbc.user" value="sa" />
        <property name="javax.persistence.jdbc.driver" value="com.microsoft.sqlserver.jdbc.SQLServerDriver" />
        <property name="javax.persistence.jdbc.password" value="" />
        <property name="hibernate.hbm2ddl.auto" value="update" />
        <property name="hibernate.show_sql" value="false" />
    </properties>
</persistence-unit>

所以,当我尝试使用这个注入的 entityManager 时,我得到了 NullPointerException。注入其他@Autowired 字段没有任何问题。这段代码有什么问题?我需要一些额外的配置吗? 我是一个初学者(甚至不是初级开发人员),我确实对 Spring-boot 是什么以及如何配置它有一些误解,比如 xml 文件中的 Spring。如果由于注入EM需要这样的xml配置,请说明如何做。

更新2。依赖关系

<dependencies>
    <!-- logger -->
    <dependency>
        <groupId>org.slf4j</groupId>
        <artifactId>slf4j-api</artifactId>
    </dependency>

    <!-- db -->
    <dependency>
        <groupId>org.hibernate</groupId>
        <artifactId>hibernate-core</artifactId>
    </dependency>
    <dependency>
        <groupId>org.hibernate</groupId>
        <artifactId>hibernate-entitymanager</artifactId>
    </dependency>
    <dependency>
        <groupId>org.hibernate</groupId>
        <artifactId>hibernate-c3p0</artifactId>
    </dependency>
    <dependency>
        <groupId>org.javassist</groupId>
        <artifactId>javassist</artifactId>
    </dependency>
    <dependency>
        <groupId>com.microsoft</groupId>
        <artifactId>sqljdbc4</artifactId>
    </dependency>
    <dependency>
        <groupId>org.quartz-scheduler</groupId>
        <artifactId>quartz</artifactId>
        <version>2.2.1</version>
    </dependency>

    <dependency>
        <groupId>com.fasterxml.jackson.core</groupId>
        <artifactId>jackson-annotations</artifactId>
        <version>2.5.3</version>
    </dependency>

    <!-- csv -->
    <dependency>
        <groupId>com.opencsv</groupId>
        <artifactId>opencsv</artifactId>
        <version>3.3</version>
    </dependency>

    <!-- spring-boot -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-data-jpa</artifactId>
        <version>1.2.4.RELEASE</version>

        <exclusions>
            <exclusion>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-logging</artifactId>
            </exclusion>
        </exclusions>

    </dependency>

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-log4j</artifactId>
        <version>1.2.4.RELEASE</version>
    </dependency>

    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-tx</artifactId>
        <version>4.1.6.RELEASE</version>
    </dependency>

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
        <version>1.2.4.RELEASE</version>

        <exclusions>
            <exclusion>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-logging</artifactId>
            </exclusion>
        </exclusions>

    </dependency>

【问题讨论】:

  • 发布您的依赖项
  • 你定义了entityManager bean,稍后注入?您似乎没有定义它。
  • 我应该在哪里定义这个bean?你能举个例子吗?

标签: spring jpa spring-boot cdi


【解决方案1】:

你应该使用 spring-boot-starter-data-jpa 的依赖项

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>

要使用持久性 xml,您应该按照文档中的说明定义一个 bean。

Spring 不需要使用 XML 来配置 JPA 提供程序,并且 Spring Boot 假定您想要利用该功能。如果您更喜欢使用 persistence.xml,那么您需要定义自己的 LocalEntityManagerFactoryBean 类型的 @Bean(id 为“entityManagerFactory”,并在那里设置持久性单元名称。

http://docs.spring.io/spring-boot/docs/current/reference/html/howto-data-access.html#howto-use-traditional-persistence-xml

或者您可以完全跳过 persistence.xml 并在 application.properties 文件中定义连接属性。

引用自文档

DataSource 配置由 spring.datasource.* 中的外部配置属性控制。例如,您可以在 application.properties 中声明以下部分:

spring.datasource.url=jdbc:mysql://localhost/test
spring.datasource.username=dbuser
spring.datasource.password=dbpass
spring.datasource.driver-class-name=com.mysql.jdbc.Driver

http://docs.spring.io/spring-boot/docs/current/reference/html/boot-features-sql.html#boot-features-connect-to-production-database

(更改驱动程序和其他数据以匹配您的环境)

祝你好运!

【讨论】:

  • 谢谢!这很有帮助,现在用于读取操作的 entityManager 不为空,但对于带有 @Transactional 注释的方法,它为空。我应该以某种方式配置事务管理器吗?怎么办?
  • 哦,对不起,这是我的错误......现在一切都很好!非常感谢!
  • 不幸的是,我有一个新问题 :( EntityManager 现在被注入,但事务没有被管理。我需要在 application.properties 文件中指定任何其他依赖项或属性吗?
  • 您应该添加 spring-tx &lt;groupId&gt;org.springframework&lt;/groupId&gt;&lt;artifactId&gt;spring-tx&lt;/artifactId&gt; 的依赖项。看看这里spring.io/guides/gs/managing-transactions
  • 我已经更新了帖子中的依赖项。使用事务管理器是否正确?
【解决方案2】:

如果您想继续使用 persistence.xml 文件,只需在您的配置类中添加以下代码

    @Bean
public LocalEntityManagerFactoryBean entityManagerFactory(){
    LocalEntityManagerFactoryBean factoryBean = new LocalEntityManagerFactoryBean();
    factoryBean.setPersistenceUnitName("data");
    return factoryBean;
}

【讨论】:

    【解决方案3】:

    您可以使用 java 配置来配置 jpa 持久性。下面的代码向您展示了配置示例:

    @Component
    public class JpaConfiguration {
    
        @Bean
        @Primary
        public DataSource dataSource() {
    
            final SimpleDriverDataSource dataSource = new SimpleDriverDataSource();
            dataSource.setDriver(new org.postgresql.Driver());
            dataSource.setUrl("jdbc:postgresql://localhost:5432/users"); 
            dataSource.setUsername("postgres");
            dataSource.setPassword("admin");
    
            return dataSource;
        }
    
        @Bean
        public JpaVendorAdapter jpaVendorAdapter() {
            HibernateJpaVendorAdapter jpaVendorAdapter = new HibernateJpaVendorAdapter();
            jpaVendorAdapter.setGenerateDdl(true);
            jpaVendorAdapter.setShowSql(true);
            jpaVendorAdapter.setDatabasePlatform("org.hibernate.dialect.PostgreSQLDialect");
    
            return jpaVendorAdapter;
        }  
    
        @Bean
        public LocalContainerEntityManagerFactoryBean entityManagerFactory() {
    
            LocalContainerEntityManagerFactoryBean lef = new LocalContainerEntityManagerFactoryBean();
            lef.setPackagesToScan("tn.bergit.crud.entity");
            lef.setDataSource(dataSource());
            lef.setJpaVendorAdapter(jpaVendorAdapter());
    
            Properties properties = new Properties();
            properties.setProperty("hibernate.show_sql", "true");
            properties.setProperty("hibernate.jdbc.fetch_size", "100");
            properties.setProperty("hibernate.hbm2ddl.auto", "update");
    
            lef.setJpaProperties(properties);
            return lef;
        }    
    
    
    }
    

    你可以在 github 上看到这个例子 (click here)

    【讨论】:

      【解决方案4】:

      如果您使用以下内容,您请求 EntityManager 的类应该是 Spring Bean

      public class Foo {
        @PersistenceContext
        private EntityManager entityManager;
      }
      

      这里,如果你使用 new 关键字来获取上面的 Foo 类的实例,那么 EntityManager 将是 null。 p>

      希望这对某人有所帮助!

      【讨论】:

        猜你喜欢
        • 2015-08-11
        • 2021-06-29
        • 2015-05-02
        • 1970-01-01
        • 2017-04-07
        • 2012-03-01
        • 1970-01-01
        • 2014-10-06
        • 1970-01-01
        相关资源
        最近更新 更多