1

根据我的 Spring Profile Hibernate 应该更新(开发)或验证(生产)数据库模式。但我得到了这个例外:

java.sql.SQLException: The url cannot be null
    at java.sql.DriverManager.getConnection(DriverManager.java:556)
    at java.sql.DriverManager.getConnection(DriverManager.java:187)
    at org.springframework.jdbc.datasource.DriverManagerDataSource.getConnectionFromDriverManager(DriverManagerDataSource.java:173)
    at org.springframework.jdbc.datasource.DriverManagerDataSource.getConnectionFromDriver(DriverManagerDataSource.java:164)
    at org.springframework.jdbc.datasource.AbstractDriverBasedDataSource.getConnectionFromDriver(AbstractDriverBasedDataSource.java:153)
    at org.springframework.jdbc.datasource.AbstractDriverBasedDataSource.getConnection(AbstractDriverBasedDataSource.java:119)
    at org.hibernate.service.jdbc.connections.internal.DatasourceConnectionProviderImpl.getConnection(DatasourceConnectionProviderImpl.java:141)
    at org.hibernate.tool.hbm2ddl.SuppliedConnectionProviderConnectionHelper.prepare(SuppliedConnectionProviderConnectionHelper.java:51)
    at org.hibernate.tool.hbm2ddl.SchemaUpdate.execute(SchemaUpdate.java:194)
    at org.hibernate.tool.hbm2ddl.SchemaUpdate.execute(SchemaUpdate.java:178)
    at org.hibernate.internal.SessionFactoryImpl.<init>(SessionFactoryImpl.java:505)
    at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:1769)
    at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:1840)
    at org.springframework.orm.hibernate4.LocalSessionFactoryBuilder.buildSessionFactory(LocalSessionFactoryBuilder.java:247)
    at com.example.config.MainConfig.sessionFactory(MainConfig.java:42)
    at com.example.config.MainConfig$$EnhancerByCGLIB$$3cbd4ba6.CGLIB$sessionFactory$2(<generated>)
    at com.example.config.MainConfig$$EnhancerByCGLIB$$3cbd4ba6$$FastClassByCGLIB$$524bdff7.invoke(<generated>)
    at org.springframework.cglib.proxy.MethodProxy.invokeSuper(MethodProxy.java:228)
    at org.springframework.context.annotation.ConfigurationClassEnhancer$BeanMethodInterceptor.intercept(ConfigurationClassEnhancer.java:286)
    at com.example.config.MainConfig$$EnhancerByCGLIB$$3cbd4ba6.sessionFactory(<generated>)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:606)
    at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:160)
    at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:570)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:1025)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:921)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:487)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:458)
    at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:295)
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:223)
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:292)
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:194)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:626)
    at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:932)
    at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:479)
    at org.springframework.web.context.ContextLoader.configureAndRefreshWebApplicationContext(ContextLoader.java:389)
    at org.springframework.web.context.ContextLoader.initWebApplicationContext(ContextLoader.java:294)
    at org.springframework.web.context.ContextLoaderListener.contextInitialized(ContextLoaderListener.java:112)
    at org.apache.catalina.core.StandardContext.listenerStart(StandardContext.java:4797)
    at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5291)
    at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150)
    at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1559)
    at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1549)
    at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:334)
    at java.util.concurrent.FutureTask.run(FutureTask.java:166)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
    at java.lang.Thread.run(Thread.java:724)

这是我的配置:

@Configuration
@Profile("development")
public class DevelopmentConfig {
    public @Bean String profile() {
        return "development";
    }
}

@Configuration
@ComponentScan(basePackages = "com.example", excludeFilters = { @ComponentScan.Filter(Configuration.class) })
@PropertySource("classpath:application.properties")
@EnableTransactionManagement
public class MainConfig {
    private @Autowired Environment env;
    private @Autowired String profile;

    public @Bean DataSource dataSource() throws IOException {
        DriverManagerDataSource ret = new DriverManagerDataSource();
        ret.setConnectionProperties(PropertyUtils.getProperties(profile, "jdbc"));
        return ret;
    }

    @SuppressWarnings("deprecation") // http://stackoverflow.com/questions/14806400/configure-sessionfactory-with-spring-hibernate-and-localsessionfactorybuilder
    public @Bean SessionFactory sessionFactory() throws IOException {
        return new LocalSessionFactoryBuilder(dataSource())
        .scanPackages("com.example.entity")
        .addProperties(PropertyUtils.getProperties(profile, "hibernate"))
        .buildSessionFactory();
    }

    public @Bean HibernateTransactionManager transactionManager() throws IOException {
        return new HibernateTransactionManager(sessionFactory());
    }
}

public class PropertyUtils {
    private static final Logger log = LoggerFactory.getLogger(PropertyUtils.class);

    public static Properties getProperties(String profile, String filename) throws IOException {
        log.debug("Read " + filename + ".properties for profile " + profile);

        Properties ret = new Properties();
        ClassPathResource resource;

        resource = new ClassPathResource("properties/common/" + filename + ".properties");
        ret.putAll(PropertiesLoaderUtils.loadProperties(resource));

        resource = new ClassPathResource("properties/" + profile + "/" + filename + ".properties");
        if (resource.exists()) {
            ret.putAll(PropertiesLoaderUtils.loadProperties(resource));
        }

        log.debug(ret.toString());
        return ret;
    }
}

第一类指示要使用哪个配置文件(也有类似ProductionConfig的)。第二个类创建所有必要的东西(dataSource、sessionFactory 和 transactionManager)。第三个合并了公共属性和配置文件相关属性。

根据开发配置文件,我的属性是(合并的):

休眠.属性:

hibernate.dialect=org.hibernate.dialect.PostgreSQLDialect
hibernate.show_sql=true
hibernate.hbm2ddl.auto=update

jdbc.properties:

driverClassName=org.postgresql.Driver
url=jdbc:postgresql://localhost:5432/mydb
username=********
password=********

但是,我没有更新数据库架构,而是遇到了异常。我从来没有得到调试日志输出Read jdbc.properties for profile development。所以,它们永远不会被阅读……但是为什么呢?

4

1 回答 1

0

知道了。我认为org.springframework.jdbc.datasource.AbstractDriverBasedDataSource.setConnectionPropertiessetDriverClassName, setUsername, setPassword,的快捷方式setUrl。不是,我需要明确设置所有内容:

public @Bean DataSource dataSource() throws IOException {
    Properties jdbcProperties = PropertyUtils.getProperties(profile, "jdbc");

    DriverManagerDataSource ret = new DriverManagerDataSource();
    ret.setDriverClassName(jdbcProperties.getProperty("driverClassName"));
    ret.setUsername(jdbcProperties.getProperty("username"));
    ret.setPassword(jdbcProperties.getProperty("password"));
    ret.setUrl(jdbcProperties.getProperty("url"));
    return ret;
}
于 2013-08-07T21:20:15.653 回答