【问题标题】:How to use Hibernate SchemaExport to create DB schema at runtime?如何在运行时使用 Hibernate SchemaExport 创建数据库模式?
【发布时间】:2013-08-10 22:46:17
【问题描述】:

我正在尝试在我的应用程序中使用 SchemaExport 在应用程序启动时创建数据库架构。我使用的是 Spring 3.2,并且在我的 Spring 配置文件中已经定义了一个 SessionFactory bean。

我正在尝试按如下方式使用它:

@Autowired
private LocalSessionFactoryBean session;

@Override
public void buildTable() throws Exception {
    SchemaExport export = new SchemaExport(session.getConfiguration());
    export.setDelimiter(";");
    export.execute(false, true, false, true);
}

我的 LocalSessionFactoryBean 在我的 spring 配置文件中定义为:

 <!-- application datasource -->
<bean id="dataSource.jndi" class="org.springframework.jndi.JndiObjectFactoryBean" scope="singleton">
    <property name="jndiName" value="java:comp/env/jdbc/db" />
</bean>

<!-- hibernate session -->
<bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean" scope="singleton">
    <property name="dataSource" ref="dataSource.jndi" />
    <property name="configLocation" value="classpath:domain/hibernate/hibernate.cfg.xml" />
    <property name="hibernateProperties">
        <props>
            <prop key="hibernate.dialect">org.hibernate.dialect.MySQL5InnoDBDialect</prop>
        </props>
    </property>
</bean>

但是,当我尝试运行该方法时,出现以下错误:

org.hibernate.HibernateException: No local DataSource found for configuration - 'dataSource' property must be set on LocalSessionFactoryBean
    at org.springframework.orm.hibernate3.LocalDataSourceConnectionProvider.configure(LocalDataSourceConnectionProvider.java:51)
    at org.hibernate.connection.ConnectionProviderFactory.newConnectionProvider(ConnectionProviderFactory.java:143)
    at org.hibernate.connection.ConnectionProviderFactory.newConnectionProvider(ConnectionProviderFactory.java:84)
    at org.hibernate.tool.hbm2ddl.ManagedProviderConnectionHelper.prepare(ManagedProviderConnectionHelper.java:51)
    at org.hibernate.tool.hbm2ddl.SchemaExport.execute(SchemaExport.java:263)

我试图追踪问题,似乎当 SchemaExport 尝试将架构写入数据库时​​,它会创建一个新的 LocalSessionFactory:

来自 org.hibernate.connection.ConnectionProviderFactory(为清晰起见进行了编辑):

private static ConnectionProvider initializeConnectionProviderFromConfig(String providerClass) {
    ConnectionProvider connections;
        connections = (ConnectionProvider) ReflectHelper.classForName( providerClass ).newInstance();
    return connections;
}

其中 providerClass = org.springframework.orm.hibernate3.LocalDataSourceConnectionProvider

因此,它不使用我的 SessionFactory bean 中定义的现有 ConnectionProvider,而是尝试创建一个新的。

如何在 SchemaExport 中使用现有的 Spring 配置的 SessionFactory / ConnectionProvider / Hibernate 配置对象?为了在我的应用程序中使用它,我还需要做些什么来设置/配置 SchemaExport?

【问题讨论】:

  • 它是一个网络应用程序吗?你如何运行 buildTable()?当您运行 buildTable() 时,您确定您的应用程序能够读取您的 jndi 吗?你会考虑使用 hibernate.hbm2ddl.auto 吗?
  • 不幸的是,我被要求不要使用hibernate.hbm2dll.auto,这就是我现在需要使用 SchemaExport 的原因。 buildTable() 是什么?我在 SchemaExport 的 API 文档中的任何地方都没有看到该方法。
  • @YoriKusanagi - 是的 - 它是一个网络应用程序。
  • buildTable() 是你的方法“public void buildTable() throws Exception”你如何运行它?是 jUnit 还是 main 方法还是服务...?
  • buildTable() 在 bean 初始化过程中被调用(即:init-method="buildTable()")。 init-method 和 buildTable() 调用之间有很多代码,但它本质上是在定义 SessionFactory bean 之后运行,并且在定义 TransactionManager bean 之前(即:TransactionManager bean - 此处未列出 - 取决于执行buildTable的bean,依赖于SessionFactory)

标签: java hibernate schema schemaexport


【解决方案1】:

您的数据源似乎设置错误。

这是一个 Spring + Hibernate 3 示例:http://www.cavalr.com/blog/Spring_3_and_Hibernate_4_Example

为了它的价值,在你的 XML 中:

<!-- hibernate session -->
<bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean" scope="singleton">
    <property name="dataSource" >
        <bean id="dataSource.jndi" class="org.springframework.jndi.JndiObjectFactoryBean" scope="singleton">
            <property name="jndiName" value="java:comp/env/jdbc/db" />
        </bean>
    </property>
    <property name="configLocation" value="classpath:domain/hibernate/hibernate.cfg.xml" />
    <property name="hibernateProperties">
        <props>
            <prop key="hibernate.dialect">org.hibernate.dialect.MySQL5InnoDBDialect</prop>
        </props>
    </property>
</bean>

像 dataSource.jndi 这样的属性(内部)bean 不能声明为“单例”范围。它们是原型,如果您想要单例范围,您必须将其创建为外部 bean,并在 property 标记上使用 ref 进行设置。

另外,&lt;property name="dataSource"&gt; 会导致调用 .getDataSource(),将 bean 定义为 dataSource.jndi 并不重要。如果要在dataSource中设置jndi属性,就必须做&lt;property name="dataSource.jndi"&gt;之类的操作。

【讨论】:

  • 实际上,为了清晰起见,我尝试剪切和粘贴一些内容。我可能忘记清理一些东西了。
  • 我已经编辑了 Spring 配置,使其更加清晰。
猜你喜欢
  • 1970-01-01
  • 2011-08-19
  • 2010-10-24
  • 2013-05-24
  • 1970-01-01
  • 2011-08-31
  • 1970-01-01
  • 1970-01-01
  • 2015-04-22
相关资源
最近更新 更多