【问题标题】:Spring data JPA configurationSpring数据JPA配置
【发布时间】:2014-08-27 13:18:03
【问题描述】:

我最近正在使用 Spring Data JPA 开发一个 Spring Web 应用程序

我遇到了持久性配置问题

@Configuration
@EnableTransactionManagement
@PropertySource({ "/resources/hibernate.properties" })
@EnableJpaRepositories(basePackages = "com.servmed.repositories")

public class PersistenceConfig {

    @Autowired
    private Environment env;


    Properties jpaProperties() {
        return new Properties() {
            {
                setProperty("hibernate.hbm2ddl.auto", env.getProperty("hibernate.hbm2ddl.auto"));
                setProperty("hibernate.dialect", env.getProperty("hibernate.dialect")); //allows Hibernate to generate SQL optimized for a particular relational database.
                setProperty("hibernate.show_sql",env.getProperty("hibernate.show_sql"));
            }
        };
    }

    @Bean
    public LocalContainerEntityManagerFactoryBean entityManagerFactory()
    {
        HibernateJpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
        vendorAdapter.setGenerateDdl(true);
        vendorAdapter.setShowSql(true);

        LocalContainerEntityManagerFactoryBean factory = new LocalContainerEntityManagerFactoryBean();
        factory.setDataSource(dataSource());
        factory.setJpaVendorAdapter(vendorAdapter);
        factory.setJpaProperties(jpaProperties());
        factory.setPackagesToScan("com.servmed.models");

        factory.setLoadTimeWeaver(new InstrumentationLoadTimeWeaver());
        return factory;
    }

    @Bean
    public PlatformTransactionManager transactionManager()
    {
        EntityManagerFactory factory = entityManagerFactory().getObject();
        return new JpaTransactionManager(factory);
    }

    @Bean
    public HibernateExceptionTranslator hibernateExceptionTranslator(){
        return new HibernateExceptionTranslator();
    }


    @Bean
    public DataSource dataSource() {
        BasicDataSource dataSource = new BasicDataSource();
        dataSource.setDriverClassName(env.getProperty("jdbc.driverClassName"));
        dataSource.setUrl(env.getProperty("jdbc.url"));
        dataSource.setUsername(env.getProperty("jdbc.user"));
        dataSource.setPassword(env.getProperty("jdbc.pass"));

        return dataSource;
    }
}

这是我的 pom.xml

<dependencies>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>3.8.1</version>
            <scope>test</scope>
        </dependency>

        <!--Spring dependencies-->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-webmvc</artifactId>
            <version>${spring.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-core</artifactId>
            <version>${spring.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-web</artifactId>
            <version>${spring.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>${spring.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-aop</artifactId>
            <version>${spring.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-expression</artifactId>
            <version>${spring.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-orm</artifactId>
            <version>${spring.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-jdbc</artifactId>
            <version>${spring.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-dao</artifactId>
            <version>2.0.8</version>
        </dependency>


        <!-- spring security-->
        <dependency>
            <groupId>org.springframework.security</groupId>
            <artifactId>spring-security-web</artifactId>
            <version>${spring-security.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.security</groupId>
            <artifactId>spring-security-core</artifactId>
            <version>${spring-security.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.security</groupId>
            <artifactId>spring-security-config</artifactId>
            <version>${spring-security.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.security</groupId>
            <artifactId>spring-security-taglibs</artifactId>
            <version>${spring-security.version}</version>
        </dependency>
        <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjweaver</artifactId>
            <version>${aspectj.version}</version>
        </dependency>
        <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjrt</artifactId>
            <version>${aspectj.version}</version>
        </dependency>

        <!-- Spring Data JPA dependencies -->
        <dependency>
            <groupId>org.springframework.data</groupId>
            <artifactId>spring-data-jpa</artifactId>
            <version>1.6.1.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate-entitymanager</artifactId>
            <version>${hibernate.version}</version>
        </dependency>


        <!--com.mysema.querydsl dependencies-->
        <dependency>
            <groupId>com.mysema.querydsl</groupId>
            <artifactId>querydsl-sql</artifactId>
            <version>${com.mysema.querydsl.version}</version>
        </dependency>
        <dependency>
            <groupId>com.mysema.querydsl</groupId>
            <artifactId>querydsl-jpa</artifactId>
            <version>${com.mysema.querydsl.version}</version>
        </dependency>
        <dependency>
            <groupId>com.mysema.querydsl</groupId>
            <artifactId>querydsl-core</artifactId>
            <version>${com.mysema.querydsl.version}</version>
        </dependency>


        <!--Hibernate dependencies-->
         <dependency>
          <groupId>org.hibernate</groupId>
          <artifactId>hibernate-core</artifactId>
          <version>${hibernate.version}</version>
        </dependency>

        <!--db-->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.23</version>
        </dependency>
        <dependency>
            <groupId>commons-dbcp</groupId>
            <artifactId>commons-dbcp</artifactId>
            <version>1.4</version>
        </dependency>

        <!--connection pool-->
        <dependency>
            <groupId>org.apache.tomcat</groupId>
            <artifactId>tomcat-dbcp</artifactId>
            <version>8.0.9</version>
        </dependency>


        <!--thymeleaf and servlet api-->
        <dependency>
            <groupId>org.thymeleaf</groupId>
            <artifactId>thymeleaf-spring4</artifactId>
            <version>2.1.2.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>servlet-api</artifactId>
            <version>2.5</version>
        </dependency>

    </dependencies>
    <build>
        <finalName>${project.artifactId}</finalName>
    </build>

这似乎对我不起作用,我收到此错误:

Caused by: org.springframework.beans.factory.BeanDefinitionStoreException: Factory method [public org.springframework.transaction.interceptor.BeanFactoryTransactionAttributeSourceAdvisor org.springframework.transaction.annotation.ProxyTransactionManagementConfiguration.transactionAdvisor()] threw exception; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'transactionInterceptor' defined in class path resource [org/springframework/transaction/annotation/ProxyTransactionManagementConfiguration.class]: Invocation of init method failed; nested exception is java.lang.IllegalArgumentException: Property 'transactionManager' is required

知道为什么吗?

编辑

entityManagerFactory 方法似乎没有正确创建 transactionManager 中使用的 bean,我在 hibernate 中遇到了同样的问题(sessionFactory bean 没有创建,并且不能在 transactionManager 方法中使用)

编辑 2

我摆脱了这个问题(这是因为一个错误的属性文件)但现在我又遇到了另一个错误:

Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'entityManagerFactory' defined in class path resource [com/servmed/configuration/PersistenceConfig.class]: Invocation of init method failed; nested exception is javax.persistence.PersistenceException: [PersistenceUnit: default] Unable to build Hibernate SessionFactory

【问题讨论】:

    标签: spring spring-data spring-data-jpa


    【解决方案1】:

    我是这样定义我的事务管理器的:

      @Bean
      public Object transactionManager() {
        return new org.springframework.orm.jpa.JpaTransactionManager();
      }
    

    而不是调用entityFactory 方法,您或许应该注入它:这将避免entityManagerFactory 中的依赖注入错误。

    @Bean
    public PlatformTransactionManager transactionManager(EntityManagerFactory factory)
    {
        return new JpaTransactionManager(factory);
    }
    

    编辑

    除了persistence.xmlafterPropertiesSet()setLoadTimeWeaver的调用,我们的代码是一样的。

    @Bean
    public LocalContainerEntityManagerFactoryBean entityManagerFactory()
    {
        HibernateJpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
        vendorAdapter.setGenerateDdl(true);
        vendorAdapter.setShowSql(true);
    
        Properties jpaProperties = new Properties();
        jpaProperties.put("hibernate.hbm2ddl.auto", env.getProperty("hibernate.hbm2ddl.auto"));
        jpaProperties.put("hibernate.dialect"     , env.getProperty("hibernate.dialect"));
        jpaProperties.put("hibernate.show_sql"    , pgadenv.getProperty("hibernate.show_sql"));
    
        LocalContainerEntityManagerFactoryBean factory = new LocalContainerEntityManagerFactoryBean();
        factory.setDataSource(dataSource());
        factory.setJpaVendorAdapter(vendorAdapter);
        factory.setJpaProperties(jpaProperties);
        factory.setPackagesToScan("com.servmed.models");
    
        // factory.afterPropertiesSet(); <-- why ?
        // does it work without Weaving ?
        factory.setLoadTimeWeaver(new InstrumentationLoadTimeWeaver());
        return factory;
    }
    

    编辑(2)

    我没有时间回答你,这里是一个示例persistence.xml

    <?xml version="1.0"  encoding="UTF-8"?>
    <persistence version="2.1"
      xmlns="http://xmlns.jcp.org/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistence
     http://xmlns.jcp.org/xml/ns/persistence/persistence_2_1.xsd">
      <!-- transaction-type="JTA" -->
      <persistence-unit name="persistenceUnit" transaction-type="RESOURCE_LOCAL">
        <provider>org.hibernate.jpa.HibernatePersistenceProvider</provider>
    
        <!-- Your probably won't need it. -->
        <!-- <class>com.servmed.models.YourClass</class> -->
        <exclude-unlisted-classes>false</exclude-unlisted-classes>
        <shared-cache-mode>ENABLE_SELECTIVE</shared-cache-mode>
    
        <properties>
          <property name="javax.persistence.schema-generation.database.action"       value="none" />
          <property name="javax.persistence.schema-generation.scripts.action"        value="none" />
          <!-- <property name="javax.persistence.schema-generation.scripts.create-target" value="" /> -->
          <!-- <property name="javax.persistence.schema-generation.scripts.drop-target"   value=""/> -->
        </properties>
      </persistence-unit>
    </persistence>
    

    您可能不需要列出您的类(如注释示例中所示),否则请列出它们。

    并在 Spring 配置中,添加:

    factory.setPersistenceXmlLocation("classpath:META-INF/persistence.xml");
    factory.setPersistenceUnitName("persistenceUnit");
    

    但是,我开始认为这可能是一个完全不相关的问题。

    【讨论】:

    • 感谢您的回复,但我仍然收到相同的错误,我尝试添加 @Autowied ,但似乎无法检测到 EntityManagerFactory Bean(即使使用 @Resource),知道为什么吗?
    • 你使用 persistence.xml 吗?如果有,你有transaction-type="RESOURCE_LOCAL" 吗?如果我没记错的话,其他事务类型(JTA)只有在使用 JTA DataSource 时才有效
    • 我使用的是无 xml 配置,所以我的项目中没有 xml
    • 我还删除了几乎所有的 XML,除了 persistence.xml。你可以试试看是否有效吗?
    • 我对xml配置不是很熟悉,毕竟我是新手
    【解决方案2】:

    @Aissasa-你可以使用类似的JPA配置类,你也不必有任何xm文件。

    JpaConfiguration

    import java.util.HashMap;
    import java.util.Map;
    import java.util.Properties;
    import javax.persistence.EntityManagerFactory;
    import javax.sql.DataSource;
    import org.eclipse.persistence.config.BatchWriting;
    import org.eclipse.persistence.config.PersistenceUnitProperties;
    import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
    import org.springframework.boot.autoconfigure.orm.jpa.JpaBaseConfiguration;
    import org.springframework.boot.orm.jpa.EntityManagerFactoryBuilder;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
    import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
    import org.springframework.orm.jpa.vendor.AbstractJpaVendorAdapter;
    import org.springframework.orm.jpa.vendor.EclipseLinkJpaVendorAdapter;
    import org.springframework.transaction.PlatformTransactionManager;
    import org.springframework.transaction.annotation.EnableTransactionManagement;
    import com.zaxxer.hikari.HikariConfig;
    import com.zaxxer.hikari.HikariDataSource;
    
    @Configuration
    @EnableTransactionManagement
    @EnableAutoConfiguration
    @EnableJpaRepositories(basePackages = "com.subu")
    public class JpaConfiguration extends JpaBaseConfiguration {
    
    @Bean
    public LocalContainerEntityManagerFactoryBean entityManagerFactory(final EntityManagerFactoryBuilder builder) {
            final LocalContainerEntityManagerFactoryBean ret =
                    builder.dataSource(dataSource())
                    .packages("com.subu")
                    .properties(jpaProperties())
                    .persistenceUnit("com.subu")
                    .build();
            return ret;
    }
    
    @Bean
    public DataSource dataSource() {
            // In classpath from spring-boot-starter-web
            final Properties props = new Properties();
            props.put("driverClassName", "com.mysql.jdbc.Driver");
            props.put("jdbcUrl", "jdbc:mysql://localhost:3306/master?createDatabaseIfNotExist=false");
            props.put("username", "root");
            props.put("password", "mysql");
            HikariConfig hc = new HikariConfig(props);
            HikariDataSource ds = new HikariDataSource(hc);
            return ds;
    }
    
    @Bean
    public Map<String, String> jpaProperties() {
            Map<String, String> props = new HashMap<>();
            props.put("eclipselink.weaving", "false");
            props.put("eclipselink.logging.level.sql", "FINE");
            props.put("eclipselink.logging.parameters", "true");
            props.put("javax.persistence.schema-generation.database.action", "create");
            //props.put("javax.persistence.sql-load-script-source", "sql/import.sql");
            return props;
    }
    @Bean
    public PlatformTransactionManager transactionManager(EntityManagerFactory emf) {
            final MultiTenantJpaTransactionManager transactionManager = new MultiTenantJpaTransactionManager();
            transactionManager.setEntityManagerFactory(emf);
            return transactionManager;
    }
    
    @Override
    protected AbstractJpaVendorAdapter createJpaVendorAdapter() {
            return new EclipseLinkJpaVendorAdapter();
    }
    
    
    
    @Override
    protected Map<String, Object> getVendorProperties() {
            final Map<String, Object> ret = new HashMap<>();
            ret.put(PersistenceUnitProperties.BATCH_WRITING, BatchWriting.JDBC);
            return ret;
    }
    
    
    }
    

    MultiTenantJpaTransactionManager

    import java.io.Serializable;
    import javax.persistence.EntityManager;
    import org.springframework.orm.jpa.EntityManagerHolder;
    import org.springframework.orm.jpa.JpaTransactionManager;
    import org.springframework.transaction.TransactionDefinition;
    import org.springframework.transaction.support.TransactionSynchronizationManager;
    
    public class MultiTenantJpaTransactionManager extends JpaTransactionManager {
    
    @Override
    protected void doBegin(final Object transaction, final TransactionDefinition definition) {
            super.doBegin(transaction, definition);
            final EntityManagerHolder emHolder = (EntityManagerHolder) TransactionSynchronizationManager
                                                 .getResource(getEntityManagerFactory());
            final EntityManager em = emHolder.getEntityManager();
    
    }
    }
    

    【讨论】:

      猜你喜欢
      • 2012-05-10
      • 2019-07-24
      • 1970-01-01
      • 1970-01-01
      • 2012-11-30
      • 2015-06-25
      • 2013-04-22
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多