0

我正在尝试使用 Spring + Spring Data + Hibernate 功能创建一个简单的 JAR。当我刚刚将 Spring 或 Hibernate + JPA 分开时,这是可行的,但当我将它们放在一起时却不行。

这种配置可能吗?

我使用 Maven 程序集插件只是为了创建一个具有依赖项的 JAR。

我还指出了扫描 JPA 实体的具体包,它适用于 eclipse,但在我执行单个 JAR 时不起作用。

我的配置是无 XML 的(没有 persistence.xml 或 application.xml),现在正在寻找 persistence.xml。如果我把文件放在 META-INF/persisntece.xml 中,错误是一样的。

更新:ConfigPersistence

@Configuration
@ComponentScan(basePackageClasses=_PackageTypeSafeClassModel.class)
@EnableJpaRepositories(basePackageClasses=_PackageTypeSafeClassModelRepositories.class)
@EnableTransactionManagement
@Import(ConfigProperties.class)
public class ConfigPersistence {

    private static final Logger LOGGER = LoggerFactory.getLogger(LogNames.CONFIGURATION.toString());

    /* Connection properties */ 
    @Value("${db.user}") private String propDBUser;
    @Value("${db.pass}") private String propDBPass;
    @Value("${db.host}") private String propDBHost;
    @Value("${db.port}") private String propDBPort;
    @Value("${db.database}") private String propDBDatabase;

    /* Pool properties */
    @Value("${db.pool.datasource}") private String propDatasource;
    @Value("${db.pool.setMinimumIdle}") private Integer propSetMinimumIdle;
    @Value("${db.pool.setIdleTimeout}") private Integer propSetIdleTimeout;
    @Value("${db.pool.setMaximumPoolSize}") private Integer propSetMaximumPoolSize;
    @Value("${db.pool.setConnectionTimeout}") private Integer propSetConnectionTimeout;

    /* Hibernate properties */  
    @Value("${db.hibernate.hbm2ddl.auto}") private String propHibernateHbm2ddl;
    @Value("${db.hibernate_dialect}") private String propHibernateDialect;
    @Value("${db.hibernate.show_sql}") private String propHibernateShowSql;
    @Value("${db.hibernate.format_sql}") private String propHibernateFormatSql;
    @Value("${db.hibernate.generate_statistics}") private String propHibernateStatistics;
    @Value("${db.hibernate.use_sql_comments}") private String propHibernateSqlComments;
    @Value("${db.hibernate.connection.autocommit}") private String propHibernateAutocommit;
    @Value("${db.hibernate.mapping.precedence}") private String propHibernatePrecedence;

    @Bean
    public EntityManagerFactory  entityManagerFactory() {

        LocalContainerEntityManagerFactoryBean entityManagerFactoryBean = new LocalContainerEntityManagerFactoryBean();
        entityManagerFactoryBean.setDataSource(dataSource());
        entityManagerFactoryBean.setPackagesToScan(_PackageTypeSafeClassModelEntities.class.getPackage().getName());
        entityManagerFactoryBean.setJpaVendorAdapter( new HibernateJpaVendorAdapter() );
        entityManagerFactoryBean.setJpaProperties(hibernateProperties());        
        entityManagerFactoryBean.afterPropertiesSet();

        return entityManagerFactoryBean.getObject();
    }

    @Bean
    public DataSource dataSource() {

        HikariDataSource hikariDS = new HikariDataSource();

        /* Hikari Pool configuration */
        hikariDS.setPoolName( "HikariCP pool" );
        hikariDS.setDataSourceClassName( propDatasource );
        hikariDS.setMinimumIdle( propSetMinimumIdle );
        hikariDS.setIdleTimeout( propSetIdleTimeout );              // Minutes
        hikariDS.setMaximumPoolSize( propSetMaximumPoolSize );      // Connection pool size
        hikariDS.setConnectionTimeout( propSetConnectionTimeout );  // Miliseconds

        /* Database configuration */
        hikariDS.addDataSourceProperty("serverName", propDBHost );
        hikariDS.addDataSourceProperty("portNumber", propDBPort );
        hikariDS.addDataSourceProperty("databaseName", propDBDatabase );
        hikariDS.addDataSourceProperty("user", propDBUser );
        hikariDS.addDataSourceProperty("password", propDBPass );

        LOGGER.info("Database connection to: {}:{}, database {} with user {}", 
                propDBHost, propDBPort, propDBDatabase, propDBUser);    

        return hikariDS;
    }

    @Bean
    public JpaTransactionManager transactionManager() {
        JpaTransactionManager transactionManager = new JpaTransactionManager();
        transactionManager.setEntityManagerFactory(entityManagerFactory());
        return transactionManager;
    }

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

    private Properties hibernateProperties(){

        Properties hibernateProperties = new Properties();
        hibernateProperties.setProperty("hibernate.dialect", propHibernateDialect );
        hibernateProperties.setProperty("hibernate.ejb.entitymanager_factory_name", "myEntityManager");
        hibernateProperties.setProperty("hibernate.hbm2ddl.auto", propHibernateHbm2ddl );
        hibernateProperties.setProperty("hibernate.show_sql", propHibernateShowSql );
        hibernateProperties.setProperty("hibernate.format_sql", propHibernateFormatSql  );
        hibernateProperties.setProperty("hibernate.generate_statistics", propHibernateStatistics );
        hibernateProperties.setProperty("hibernate.use_sql_comments", propHibernateSqlComments );
        hibernateProperties.setProperty("hibernate.connection.autocommit", propHibernateAutocommit );   
        hibernateProperties.setProperty("hibernate.mapping.precedence", propHibernatePrecedence);

        LOGGER.info("Setting {} hibernateProperties {}", hibernateProperties.size(), hibernateProperties);      
        return hibernateProperties;
    }

}

我得到的错误:

Caused by: javax.persistence.PersistenceException: Unable to resolve persistence unit root URL
    at org.springframework.orm.jpa.persistenceunit.DefaultPersistenceUnitManager.determineDefaultPersistenceUnitRootUrl(DefaultPersistenceUnitManager.java:591) ~[company-monitor-jar-with-dependencies.jar:na]
    at org.springframework.orm.jpa.persistenceunit.DefaultPersistenceUnitManager.preparePersistenceUnitInfos(DefaultPersistenceUnitManager.java:443) ~[company-monitor-jar-with-dependencies.jar:na]
    at org.springframework.orm.jpa.persistenceunit.DefaultPersistenceUnitManager.afterPropertiesSet(DefaultPersistenceUnitManager.java:424) ~[company-monitor-jar-with-dependencies.jar:na]
    at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.createNativeEntityManagerFactory(LocalContainerEntityManagerFactoryBean.java:310) ~[company-monitor-jar-with-dependencies.jar:na]
    at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.afterPropertiesSet(AbstractEntityManagerFactoryBean.java:318) ~[company-monitor-jar-with-dependencies.jar:na]
    at com.company.config.ConfigPersistence.entityManagerFactory(ConfigPersistence.java:88) ~[company-monitor-jar-with-dependencies.jar:na]
    at com.company.config.ConfigPersistence$$EnhancerBySpringCGLIB$$a1e8e6cc.CGLIB$entityManagerFactory$1(<generated>) ~[company-monitor-jar-with-dependencies.jar:na]
    at com.company.config.ConfigPersistence$$EnhancerBySpringCGLIB$$a1e8e6cc$$FastClassBySpringCGLIB$$17999b5a.invoke(<generated>) ~[company-monitor-jar-with-dependencies.jar:na]
    at org.springframework.cglib.proxy.MethodProxy.invokeSuper(MethodProxy.java:228) ~[company-monitor-jar-with-dependencies.jar:na]
    at org.springframework.context.annotation.ConfigurationClassEnhancer$BeanMethodInterceptor.intercept(ConfigurationClassEnhancer.java:318) ~[company-monitor-jar-with-dependencies.jar:na]
    at com.company.config.ConfigPersistence$$EnhancerBySpringCGLIB$$a1e8e6cc.entityManagerFactory(<generated>) ~[company-monitor-jar-with-dependencies.jar:na]
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_91]
    at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source) ~[na:1.8.0_91]
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source) ~[na:1.8.0_91]
    at java.lang.reflect.Method.invoke(Unknown Source) ~[na:1.8.0_91]
    at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:162) ~[company-monitor-jar-with-dependencies.jar:na]
    ... 13 common frames omitted
Caused by: java.io.FileNotFoundException: class path resource [] cannot be resolved to URL because it does not exist
    at org.springframework.core.io.ClassPathResource.getURL(ClassPathResource.java:187) ~[company-monitor-jar-with-dependencies.jar:na]
    at org.springframework.orm.jpa.persistenceunit.DefaultPersistenceUnitManager.determineDefaultPersistenceUnitRootUrl(DefaultPersistenceUnitManager.java:588) ~[company-monitor-jar-with-dependencies.jar:na]
    ... 28 common frames omitted
[ERROR][CONFIGURATION] - [Main.java:30] - 24/05/2016 11:57:05.614 - Exception: Error creating bean with name 'entityManagerFactory' defined in com.company.config.ConfigPersistence: Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [javax.persistence.EntityManagerFactory]: Factory method 'entityManagerFactory' threw exception; nested exception is javax.persistence.PersistenceException: Unable to resolve persistence unit root URL

更新:POM 依赖项

<dependencies>

        <!-- Spring Boot dependencies -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-jpa</artifactId>
            <exclusions>
                <exclusion>
                    <groupId>org.apache.tomcat</groupId>
                    <artifactId>tomcat-jdbc</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
            <exclusions>
                <exclusion>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-starter-tomcat</artifactId>
                </exclusion>
                <exclusion>
                    <groupId>org.apache.tomcat.embed</groupId>
                    <artifactId>tomcat-embed-el</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-undertow</artifactId>
            <exclusions>
                <exclusion>
                    <groupId>io.undertow</groupId>
                    <artifactId>undertow-websockets-jsr</artifactId>
                </exclusion>
            </exclusions>
        </dependency>

        <!-- Databases dependencies -->
        <dependency>
            <groupId>com.oracle</groupId>
            <artifactId>ojdbc6</artifactId>
            <version>${database.oracle.version}</version>
        </dependency>

        <!-- Hibernate dependencies -->
        <dependency>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate-core</artifactId>
        </dependency>
        <dependency>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate-entitymanager</artifactId>
        </dependency>

        <!-- Connection pool -->
        <dependency>
            <groupId>com.zaxxer</groupId>
            <artifactId>HikariCP</artifactId>
        </dependency>

        <!-- Logging: SL4J and LogBack dependencies -->
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-api</artifactId>
        </dependency>
        <dependency>
            <groupId>ch.qos.logback</groupId>
            <artifactId>logback-classic</artifactId>
        </dependency>

        <!-- JCommander -->
        <dependency>
            <groupId>com.beust</groupId>
            <artifactId>jcommander</artifactId>
            <version>${jcommander.version}</version>
        </dependency>

    </dependencies>
4

2 回答 2

1

maven-assembly-plugin我建议使用 Spring Boot,而不是尝试使用 Spring Boot 来获得可行的解决方案。这已经处理了诸如设置适当的类加载器等这些事情。

首先将您的配置转换为application.properties并使用Spring Boot 属性名称。然后你可以简单地删除你的配置类(因为 Spring Boot 会自动检测你的类路径上的内容并进行相应的配置)。

尽管作为一种迁移策略,您可以从自己的配置类开始,让它运行,然后剥离为您提供的所有内容(基本上就是您在此处显示的所有内容)。

接下来创建一个入门类(在顶级包中,以便它涵盖所有包)。

@SpringBootApplication
public class MyApplication {

    public static void main(String... args) throws Exception {

        SpringApplication.run(MyApplication.class, args);
    }
}

您的依赖项应如下所示。(从你的问题中推断出来,但我认为还有更多)。

<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-data-jpa</artifactId>
    </dependency>
    <dependency>
        <groupId>com.zaxxer</groupId>
        <artifactId>HikariCP</artifactId>
    </dependency>
</dependencies>

这是假设您使用 Spring Boot 作为项目的父项。

使用 spring boot 插件代替程序集插件。

<!-- Package as an executable jar -->
<build>
    <plugins>
        <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>
        </plugin>
    </plugins>
</build>

这应该会给你一个可执行的 jar,而不用付出太多的努力,并自动引导你的应用程序。

于 2016-05-24T10:36:23.353 回答
0

根据提供的堆栈跟踪,您正在使用LocalContainerEntityManagerFactoryBean

LocalContainerEntityManagerFactoryBean 根据 JPA 的标准容器引导契约(source)创建一个 JPA EntityManagerFactory

但是 Spring 也提供了 LocalEntityManagerFactoryBean

LocalEntityManagerFactoryBean 根据 JPA 的标准独立引导契约(source)创建一个 JPA EntityManagerFactory

所以首先要做的是使用 LocalEntityManagerFactoryBean。我不知道它是否能解决你所有的问题,但至少,如果你不在容器中运行,这是第一步。

于 2016-05-24T10:25:55.977 回答