Spring数据JPA配置

时间:2014-08-27 13:18:03

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

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

我遇到了persistanceConfiguration

的问题
@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

2 个答案:

答案 0 :(得分:2)

以下是我定义事务管理器的方法:

  @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");

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

答案 1 :(得分:0)

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

        Code :::

                        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;
                            }


                        }





                        ===================================================================================================================================





                        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();

                            }
                        }