【问题标题】:Is there a way to get Hibernate's hbm2ddl Ant task to exclude specific tables?有没有办法让 Hibernate 的 hbm2ddl Ant 任务排除特定的表?
【发布时间】:2011-01-09 14:07:04
【问题描述】:

我使用 Hibernate 自动生成我的数据库进行测试,并且我的架构中有一些表包含需要很长时间才能导入的静态数据。过去,我在构建文件中使用以下代码(从映射文件)生成数据库:

<target name="schema-gen" depends="hibernate-gen">
    <taskdef name="schemaexport" classname="org.hibernate.tool.hbm2ddl.SchemaExportTask" classpathref="project.classpath" />

    <schemaexport properties="resources/hibernate.properties" text="false" quiet="false" delimiter=";" output="schema.sql">
        <fileset dir="${build.doclets}">
            <include name="**/*.hbm.xml" />
            <exclude name="**/inert/*.hbm.xml" />
        </fileset>
    </schemaexport>
</target>

.hbm.xml 文件是使用 XDoclet 生成的。我正在迁移到使用 Hibernate Annotations 进行映射,所以我正在迁移到 hibernatetools 来生成架构:

<target name="annotations-export" depends="hibernate-gen">
    <hibernatetool destdir="${basedir}">
        <annotationconfiguration configurationfile="${basedir}/resources/hibernate.cfg.xml" propertyfile="${basedir}/resources/hibernate.properties" />
        <classpath>
            <path refid="project.classpath" />
        </classpath>
        <hbm2ddl drop="true" create="true" export="true" outputfilename="schema.sql" delimiter=";" format="true" />
    </hibernatetool>
</target>

我希望能够告诉 hbm2ddl 省略“惰性”包中的类,就像我过去使用 schemaexport 一样。有谁知道有没有办法?

【问题讨论】:

    标签: java hibernate ant annotations hbm2ddl


    【解决方案1】:

    如果你遇到这种情况,又不希望 Hibernate 更新表中的数据,那么你可以替换:

    <class name="FooClass" table="FOO_TABLE"></class>
    

    <class name="Foo" subselect="select * from FOO_TABLE">
      <synchronize table="FOO_TABLE">
    </class>
    

    然后架构导出工具将忽略它,但任何写入也会如此。至少,这是文档所建议的。

    subselect(可选):将一个不可变的只读实体映射到一个 数据库子选择。

    我通过查看Table.isPhysicalTable 函数发现了这一点。您还可以考虑使用 AbstractUnionTables,这是另一个例外。

    我碰巧想要不可变的对象。

    我的用例是我想加载一些形状略有不同的不可变版本的一些休眠托管对象,而不会有意外更改架构导出的风险。所以 subselect 非常适合。

    不幸的是,它会在您的所有查询中添加该子选择,而数据库应该能够对其进行优化,但人们对数据库优化的信任程度各不相同,这是有充分理由的。

    【讨论】:

    • 显然我在第一次测试时欺骗了自己。最初我用 subselect="select * from table_name" 进行了测试,并检查它没有更新模式,并且工作,然后我必须将它改进为 subselect="table_name" 并且只检查它是否工作。因为再次测试,仅使用 subselect="table_name" 仍然会更新架构。我将更新答案以使此评论使用 select from 语法,即使它更丑陋:(
    • 我探索了另一个选项,设置 abstract="true"。这似乎适用于我也有 mutable="false" 的情况。在更新此答案或添加另一个答案之前,我会更仔细地探讨这一点,因为它确实不同。
    【解决方案2】:

    我最终采用的解决方案是创建一个单独的 Hibernate 配置,其中包含我想要映射的类,并将其用于导出任务,而不是其他包含所有映射类的 Hibernate 配置。

    【讨论】:

      【解决方案3】:

      这应该可行:

      <target name="annotations-export" depends="hibernate-gen">
          <hibernatetool destdir="${basedir}">
              <annotationconfiguration configurationfile="${basedir}/resources/hibernate.cfg.xml" propertyfile="${basedir}/resources/hibernate.properties">
                  <fileset dir="${build.doclets}">
                      <include name="**/*.class" />
                      <exclude name="**/inert/*.class" />
                  </fileset>
              </annotationconfiguration>
              <classpath>
                  <path refid="project.classpath" />
              </classpath>
              <hbm2ddl drop="true" create="true" export="true" outputfilename="schema.sql" delimiter=";" format="true" />
          </hibernatetool>
      </target>
      

      【讨论】:

      • 这是个好主意,但它不起作用,因为我永远无法让文件集完全正常工作。让它准确地包含我想要的文件而不包含我不想要的文件是太多的工作。
      【解决方案4】:

      您是否尝试过 hbmddl 标签上的 update 属性?

      <hbm2ddl update="true" ...
      

      详情请见here

      应该可以的

      【讨论】:

      • 这不是我要找的。我想重新创建大部分表(为我的测试重置东西),但我想跳过一些表。 update 将保留所有存在的内容,这不是我想要的行为。
      猜你喜欢
      • 1970-01-01
      • 2013-12-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-01-15
      • 2022-01-25
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多