休眠:是不是可以仅在测试时“保存级联”?

Posted

技术标签:

【中文标题】休眠:是不是可以仅在测试时“保存级联”?【英文标题】:Hibernate : Is it possible to "save cascade" only on test?休眠:是否可以仅在测试时“保存级联”? 【发布时间】:2016-11-30 09:03:40 【问题描述】:

我想知道是否可以保存级联我的实体但仅在我运行测试时?

我希望能够保存级联,但仅在我运行测试时。为了测试我的 dao,如果我可以保存级联实体并且不会因为子实体尚未保存而出现错误,这将为我节省大量时间。

@Test
public void addGetEntityTests()

    Entity entity1 = ...;
    Entity entity2 = ...; //same as entity1

    getDao().addEntity(entity1);
    assertEquals(entity1, entity2);

谢谢。

【问题讨论】:

【参考方案1】:

如果不修改实体声明或您正在测试的查询,您将无法执行您想要实现的目标。 而且您不应该这样做,因为在这种情况下,您的测试执行的逻辑与您的实现不同,而测试应该检查实现是否按预期工作。 如果您在测试开始时需要一个上下文,您应该在您的类的 @Before 方法之前创建此上下文。 您可以通过自己的服务(如果经过测试)或使用 DBunit 等工具的 SQL 将数据注入数据库。


编辑:DBunit 示例

您在评论中解释说在您的对象中设置所有数据是乏味的。所以,我想你有多个行和关系要设置来创建你的上下文。 在这种情况下,您可以使用 DBunit 并分两步进行:

在数据集中写入每一行也很乏味。另一种方法是根据现有数据库的查询动态创建数据集,该数据库包含您要检索的数据。 此步骤将执行一次,以创建您要在单元测试中使用的数据集。 在测试开始前使用这个生成的数据集

我使用了来自http://dbunit.sourceforge.net/howto.html 的示例,我稍作改编。

第一步(生成数据集):

public class DatabaseExportSample

    public static void main(String[] args) throws Exception 
        // database connection
        Class driverClass = Class.forName("org.hsqldb.jdbcDriver");
        Connection jdbcConnection = DriverManager.getConnection(
                "jdbc:hsqldb:sample", "sa", "");
        IDatabaseConnection connection = new DatabaseConnection(jdbcConnection);

        // partial database export
        QueryDataSet partialDataSet = new QueryDataSet(connection);
        partialDataSet.addTable("FOO", "SELECT * FROM TABLE WHERE COL='VALUE'");
        partialDataSet.addTable("BAR");
        FlatXmlDataSet.write(partialDataSet, new FileOutputStream("partial.xml"));

        // full database export
        IDataSet fullDataSet = connection.createDataSet();
        FlatXmlDataSet.write(fullDataSet, new FileOutputStream("full.xml"));

        // dependent tables database export: export table X and all tables that
        // have a PK which is a FK on X, in the right order for insertion
        String[] depTableNames = 
          TablesDependencyHelper.getAllDependentTables( connection, "X" );
        IDataSet depDataset = connection.createDataSet( depTableNames );
        FlatXmlDataSet.write(depDataSet, new FileOutputStream("dataset.xml"));                      
    

它会生成一个xml文件(这里是一个示例):

<!DOCTYPE dataset SYSTEM "dataset.dtd">
<dataset>
    <table name="TEST_TABLE">
        <column>COL0</column>
        <column>COL1</column>
        <column>COL2</column>
        <row>
            <value>row 0 col 0</value>
            <value>row 0 col 1</value>
            <value>row 0 col 2</value>
        </row>
        <row>
            <null/>
            <value>row 1 col 1</value>
            <null/>
        </row>
    </table>
    <table name="SECOND_TABLE">
        <column>COLUMN0</column>
        <column>COLUMN1</column>
        <row>
            <value>row 0 col 0</value>
            <value>row 0 col 1</value>
        </row>
    </table>
    <table name='EMPTY_TABLE'>
        <column>COLUMN0</column>
        <column>COLUMN1</column>
    </table>
</dataset>

第二步(在你的测试数据库中注入这个数据集):

public class SampleTest 

  @Before
  protected void setUp() throws Exception
  
    super.setUp();

    // initialize your database connection here
    IDatabaseConnection connection = null;
    // ...

    // initialize your dataset here
    IDataSet dataSet = null;
    // ...

    try1
    
        DatabaseOperation.CLEAN_INSERT.execute(connection, "dataset.xml");
    
    finally
    
        connection.close();
    
  
  ...
  // when your test method starts you have the required data in your test database
  @Test
  public void addGetEntityTests()
    Entity entity1 = ...;
    getDao().addEntity(entity1);
  

【讨论】:

是的,但在应用程序中我只想测试“添加”方法。在我的应用程序中,如果子对象不存在,则出现错误是正常的。我已经在 before 方法中添加了子对象,但它真的很乏味...... 如果太繁琐,您应该在 DBunit 数据集中提取所需数据并在调用测试方法之前注入此数据集。如果你有很多行要获取,你甚至可以使用 DBunit 帮助类来初始化它们。我刚刚使用官方文档编辑了我的答案以显示一个简单的示例。

以上是关于休眠:是不是可以仅在测试时“保存级联”?的主要内容,如果未能解决你的问题,请参考以下文章

hibernate中多表映射关系配置

hibernate中多表映射关系配置

hibernate---级联保存级联删除

OneToMany Hibernate 保存级联问题

2018.11.4 Hibernate中多对多的关系

大型连通图上的休眠 SaveOrUpdate