`

dbunit入门 (二)数据的备份与恢复

阅读更多
这里讲如何将我们将要测试的数据库的表的数据进行备份,然后测试, 最后恢复数据库数据。


这里的核心过程就是
-> QueryDataSet获取数据库信息。
-> FlatXmlDataSet.write写入数据库数据到xml文件中。
-> 进行测试
-> 测试完成, 从xml文件恢复数据到数据库中

这里的几个核心的Dbunit类:

1. org.dbunit.dataset.IDataSet
这个接口是关于存放所有table信息的,包括xml文件的table数据信息以及数据库中读取到的table数据信息。

2. org.dbunit.dataset.xml.FlatXmlDataSet
这个类用于读写上面的IDataSet所存储的信息。
它可以从xml文件中读取信息,并写入到IDataSet中。
或者从IDataSet中读取信息,并写入到xml文件中。

3. org.dbunit.database.QueryDataSet
这个类保存所有根据sql语句查询到的表的内容。
它通过如下的构造函数获取IDatabaseConnection。
private final IDatabaseConnection _connection;
  public QueryDataSet(IDatabaseConnection connection)。

这个类的核心方法是addTable(), 源码如下:
 
  /**
     *  Adds a table and it's associated query to this dataset.
     *
     * @param tableName The name of the table
     * @param query The query to retrieve data with for this table. Can be null which will select
     * all data (see {@link #addTable(String)} for details)
     * @throws AmbiguousTableNameException 
     */
    public void addTable(String tableName, String query) throws AmbiguousTableNameException
    {
        logger.debug("addTable(tableName={}, query={}) - start", tableName, query);
        _tables.add(tableName, new TableEntry(tableName, query));
    }

    /**
     *  Adds a table with using 'SELECT * FROM <code>tableName</code>' as query.
     *
     * @param tableName The name of the table
     * @throws AmbiguousTableNameException 
     */
    public void addTable(String tableName) throws AmbiguousTableNameException
    {
        logger.debug("addTable(tableName={}) - start", tableName);
        this.addTable(tableName, null);
    }


它会将select语句和自己的OrderedTableNameMap对象绑定在一起。在后面需要查询数据库数据时, 便会执行SQL语句。(跟hibernate的session比较类似吧)。

================================================

完整的AbstractDbUnitTestCase代码:

package com.lj.basic.test.util;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.sql.SQLException;

import junit.framework.Assert;

import org.dbunit.DatabaseUnitException;
import org.dbunit.database.DatabaseConnection;
import org.dbunit.database.IDatabaseConnection;
import org.dbunit.database.QueryDataSet;
import org.dbunit.dataset.DataSetException;
import org.dbunit.dataset.IDataSet;
import org.dbunit.dataset.xml.FlatXmlDataSet;
import org.dbunit.dataset.xml.FlatXmlProducer;
import org.dbunit.operation.DatabaseOperation;
import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.xml.sax.InputSource;

import com.lj.basic.test.util.AbstractDbUnitTestCase;
import com.lj.basic.test.util.DbUtil;
import com.lj.basic.util.MyLog4jLogger;


/**
 * 此处我们使用lingling这个数据库schema来专门进行测试
 * alleni用来存储我们的正式信息。
 * lingling->在dbutil中配置的  -jdbc connection
 * alleni-> 在beans.xml中配置的 -hibernate
 * @author Administrator
 *
 */
public class AbstractDbUnitTestCase {
	public static IDatabaseConnection dbunitCon;
	
	
	/**
	 * tempFile用来存放备份的数据信息<br/>
	 * 当测试数据时,会将数据信息存放到这个文件中。<br/>
	 * 测试完成之后,再将数据导回数据库。
	 */
	private File tempFile;
	
	/**
	 * Beforeclass是在创建这个类之前所做的操作<br/>
	 * 这个方法必须为static<br/>
	 * 该方法在junit测试中会被最先调用,并且只会调用一次。
	 */
	@BeforeClass
	public static void init() throws DatabaseUnitException{
		//System.out.println("BEFOREclass init");
		MyLog4jLogger.debug("AbstractDbUnitTestCase init() BeforeClass");
		//在测试运行之前,便给dbunitCon初始化并赋值。
		dbunitCon=new DatabaseConnection(DbUtil.getCon());
	}
	
	/**
	 * 测试完成之后,此方法便会被运行,关闭dbunitCon
	 */
	@AfterClass
	public static void destory(){
		try {
			if(dbunitCon!=null)dbunitCon.close();
			
		} catch (Exception e) {
			 e.printStackTrace();
		}
		MyLog4jLogger.debug("AbstractDbUnitTestCase destory() @AfterClass finished");
	}
	
	/**
	 * 通过项目中的xml文件获取测试数据<br/>
	 * @param table_name 数据表的名称
	 * @return 返回FlatXmlDataSet类型对象,包含了xml文件中的所有内容
	 */
	protected IDataSet createDataSet(String dataSource_name) throws DataSetException{
		
		if(!dataSource_name.endsWith(".xml")){
			dataSource_name+=".xml";
		}
		InputStream is=AbstractDbUnitTestCase.class.getClassLoader().getResourceAsStream(dataSource_name);
		
		Assert.assertNotNull("dbunit的基本数据文件不存在", is);
		
		return new FlatXmlDataSet(new FlatXmlProducer(new InputSource(is)));
	}
	
	/**
	 * 这个方法用于备份指定的几个表名
	 * @param tname 要备份的数据库中的表名称
	 */
	protected void backupCustomTable(String[] tname) throws DataSetException, IOException{
		QueryDataSet backup=new QueryDataSet(dbunitCon);
		
		for(String name:tname){
			//这里将表名捆绑到QueryDataSet里面,这样在后面读取数据库的时候,就会产生对应的SQL语句。
			backup.addTable(name);
		}
		
		//将IDataSet的数据信息写入tempFile中。
		//里面调用了FlatXmlDataSet的write方法。
		writeBackupFile(backup);
	}
	
	
	/**
	 * 将IDataSet的数据信息写入tempFile中。
	 * @param backupDataSet
	 */
	private void writeBackupFile(IDataSet ds) throws DataSetException, IOException{
		if(tempFile==null||!tempFile.exists()){
		tempFile = File.createTempFile("backup", ".xml");}
		//System.out.println(tempFile.exists());
		FlatXmlDataSet.write(ds, new FileWriter(tempFile));
	}
	
	/**
	 * 不建议在Oracle数据库中使用。因为dbunitCon.createDataSet()会获取oracle里面的各种表,其中很多jvm是没有权限修改的。
	 */
	@Deprecated
	protected void backupAllTable() throws SQLException, DataSetException, IOException{
	 	IDataSet ds=dbunitCon.createDataSet();
	 //	System.out.println(ds.getTable("t_user").getRowCount());
		
	//	QueryDataSet qds=new QueryDataSet(dbunitCon);
		 
		writeBackupFile(ds);
		
	}
	

	
	protected void backupOneTable(String tname) throws DataSetException, IOException{
		this.backupCustomTable(new String[]{tname});
	}
	
	/**
	 *  读取tempFile里的数据,从而恢复数据库原始的信息。
	 */
	protected void resumeTable() throws FileNotFoundException, DatabaseUnitException, SQLException{
		IDataSet ds=new FlatXmlDataSet(new FlatXmlProducer(new InputSource(new FileInputStream(tempFile))));
		DatabaseOperation.CLEAN_INSERT.execute(dbunitCon, ds);
	}
	
	
	
	
}




当我们新建一个测试代码的时候, 只要让该代码继承AbstractDbUnitTestCase就行了。

简例如下:

package com.lj.core.dao;

import java.io.FileNotFoundException;
import java.io.IOException;
import java.sql.SQLException;

import javax.inject.Inject;

import org.dbunit.DatabaseUnitException;
import org.dbunit.dataset.DataSetException;
import org.dbunit.dataset.IDataSet;
import org.dbunit.operation.DatabaseOperation;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.orm.hibernate4.SessionHolder;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.transaction.support.TransactionSynchronizationManager;

import com.lj.basic.test.util.AbstractDbUnitTestCase;



@RunWith(SpringJUnit4ClassRunner.class)
//这里的test_beans.xml中的数据库信息必须和dbutil中通过jdbc连接的数据库信息一致!
@ContextConfiguration("/test_beans.xml")//这里运行src/test/resources里面的test_beans.xml,该文件指定了lingling这个测试数据库对象
public class TestDbunit extends AbstractDbUnitTestCase
{	
	@Inject
	private IUserDao userDao;
	
	
	@Inject
	private SessionFactory sessionFactory;
	
	@Before
	public void setUp() throws DatabaseUnitException, SQLException, IOException{
//		Session s=sessionFactory.openSession();
//		TransactionSynchronizationManager.bindResource(sessionFactory, new SessionHolder(s));
//		
 		//这里的t_user就是t_user.xml,包含了我们要进行测试的信息
		IDataSet ds=createDataSet("test_user");
		
		//备份数据库信息,Oracle下不能使用该方法,要指定table名来备份
		//this.backupAllTable();
		this.backupOneTable("t_user");
//		
 		DatabaseOperation.CLEAN_INSERT.execute(dbunitCon, ds);
 		
 		
		
	}
	
	@Test
	public void testUser(){
		//test code
	}
	
	
	@After
	public void tearDown() throws FileNotFoundException, DatabaseUnitException, SQLException{
		//teardown code
		 this.resumeTable();
	}
	
}





============================================

最后还是要说, 这东西不熟练的情况下还是不要和运行数据库混淆。
测试就用测试的数据库, 网站运行就用运行的数据库。
虽然dbunit可以备份恢复数据, 但是一旦出了差错,还是非常麻烦的。
分享到:
评论

相关推荐

    DBUnit最佳实践之数据备份与恢复

    在“DBUnit最佳实践”中,作者可能还会讨论如何结合使用DBUnit与其他工具,如Ant或Maven构建工具,以及持续集成服务器如Jenkins,来自动化数据备份和恢复的过程。这样可以节省手动操作的时间,并减少人为错误的可能...

    如何使用DBUnit做数据备份恢复

    DBUnit 是一个开源的 Java 库,专门用于数据库测试,它提供了一种方式来管理和操作数据库的数据,包括数据的导入导出、备份和恢复。在本文中,我们将深入探讨如何利用 DBUnit 进行数据库的备份与恢复。 首先,我们...

    dbunit-2.4.7所有jar以及dbunit入门教程

    DBUnit 的核心概念包括数据集、操作模式和数据类型映射。数据集是 DBUnit 的基础,它通常是一个 XML 文件或者 CSV 文件,描述了测试用例中的预期数据库状态。这些文件包含了表的行和列,模拟了数据库中的数据。操作...

    DbUnit入门实战

    DbUnit 入门实战 DbUnit 是一个专门针对数据库测试的 JUnit 扩展,它可以将测试对象数据库置于一个测试轮回之间的状态。DbUnit 的设计理念是,在测试之前,备份数据库,然后给对象数据库植入我们需要的准备数据,...

    dbunit入门实例

    **DbUnit 入门指南** DbUnit 是一个用于数据库测试的开源 Java 工具,它提供了数据驱动测试的框架,可以有效地管理和填充测试数据库。在软件开发中,尤其是在进行单元测试时,确保数据库状态的一致性至关重要。...

    dbunit使用实例

    DBUnit 提供了一种简单且结构化的机制来导入和导出数据库数据,帮助开发者有效地管理和维护测试数据。 ### DBUnit 的基本概念 1. **数据集(Dataset)**: 数据集是 DBUnit 的核心概念,它代表了数据库中的一组记录...

    通过DBUNIT做批量对比测试

    DBUNIT 提供了一种高效的方式来进行这种比较,它允许测试人员定义数据集(通常以 CSV 或 XML 格式),并将这些数据加载到数据库中,然后在测试完成后进行验证,确认数据库的实际状态与预期相符。 以下是使用 DBUNIT...

    dbunit-2.4.9 源码

    3. 数据清理:测试结束后,DBUnit 可以清理数据库,恢复到初始状态,避免测试数据污染生产环境。 在 `dbunit-2.4.9` 压缩包中,可能包含以下组件和资源: 1. `lib/` 目录:包含了 DBUnit 运行所需的依赖库,如...

    dbunit帮助文档(HTML版)

    1. **数据导入/导出**:DBUnit可以将数据从数据库导出到XML或CSV文件,也可以将这些文件中的数据导入到数据库,这在数据迁移或备份时非常有用。 2. **数据比较**:DBUnit提供了断言机制,可以比较数据库的实际状态...

    dbunit2.2

    2. **操作模式**:DBUnit 提供了三种操作模式:CLEAN_INSERT(清空表后再插入新的数据)、UPDATE(更新已有数据)和OVERWRITE(覆盖原有数据)。这些模式可以根据不同的测试需求来选择。 3. **数据集**:在DBUnit中...

    dbunit测试demo

    通常,`@Before` 会使用 `IDatabaseConnection` 和 `IDataSet` 清理和填充数据,`@After` 用于恢复初始状态或清理数据。 6. **执行测试**:在测试方法中,使用 `DatabaseTester` 或 `DBUnitHelper` 类来运行 DBUnit...

    dbunit开发文档

    1. JUnit 集成:DBUnit 可以很容易地与 JUnit 结合使用,通过 `@Before` 和 `@After` 注解来设置和清理数据库。 2. Spring 集成:如果你的项目使用 Spring,可以利用 Spring's `DbUnitTestExecutionListener` 来...

    Dbunit数据库连接下载

    Dbunit 是一个强大的Java库,专门用于数据库的测试和数据管理。它被广泛应用于软件开发过程中,特别是对于那些依赖于数据库的应用程序,因为Dbunit能够帮助开发者有效地管理和控制数据库的状态,确保测试的一致性...

    DBUNIT使用

    DbUnit 还可以与 JUnit 集成,使用 DbUnit 的 TestCase 子类来编写测试用例。DbUnit 的使用可以使数据库测试变得更方便快捷。 DbUnit 还提供了多种方式来访问数据库,例如使用 IDatabaseConnection 接口来访问实际...

    spring与dbunit集成测试

    本文将深入探讨如何将Spring与DBUnit整合,以实现高效、可靠的数据库集成测试。 首先,理解Spring的核心功能是至关重要的。Spring是一个开源的Java平台,它为构建应用程序提供了全面的支持,包括依赖注入...

    DBUnit 进行单元测试

    DBUnit 提供了一种结构化的方式来导入和导出数据库数据,使得测试环境可以被精确地设置和还原,避免了因为测试数据污染而引起的错误。 在进行单元测试时,DBUnit 允许我们将数据库的状态定义为“预期状态”(通常在...

    dbunit单元测试

    2. **连接数据库**:在测试开始前,DBUnit需要与目标数据库建立连接,这通常通过配置JDBC驱动和连接参数实现。 3. **初始化数据库**:使用`IDatabaseConnection`接口的`createDataSet()`方法加载数据集到数据库,...

    DBUnit导数据报表名超长和MBCS字段被截断日志

    在IT行业中,数据库管理和数据导入导出是至关重要的任务,特别是在使用DBUnit这样的工具时。DBUnit是一款用于数据库测试的Java库,它允许开发者在测试前后对比数据库状态,确保数据处理的正确性。然而,当遇到...

    DBUNIT 基类DBUNIT 基类DBUNIT 基类DBUNIT 基类DBUNIT 基类

    DBUNIT 基类DBUNIT 基类DBUNIT 基类DBUNIT 基类DBUNIT 基类DBUNIT 基类DBUNIT 基类DBUNIT 基类DBUNIT 基类DBUNIT 基类DBUNIT 基类DBUNIT 基类DBUNIT 基类DBUNIT 基类DBUNIT 基类DBUNIT 基类DBUNIT 基类DBUNIT 基类...

Global site tag (gtag.js) - Google Analytics