`

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 是一个用于数据库测试的开源 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能够帮助开发者有效地管理和控制数据库的状态,确保测试的一致性...

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

    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