我不确定我的DAO或DBUnit Test是否需要一些重构。有人可以指导我面临的情况吗?

我有一个DAO,它通过获取Connection对象从数据库中获取一些数据,然后关闭所有资源(ResultSetStatementConnection)。

我正在使用DBUnit框架测试此DAO,在此DBUnit测试中,我正在执行两个数据库操作:
1)创建一个表,然后从XML数据集文件加载数据
2)测试DAO中存在的实际getDataById(int id)方法

问题是我的第二个getDataById(id)方法无法获取数据库连接对象,因为我的DAO在执行上述步骤1时已将其关闭。

实际释放所有资源的代码段如下所示。

DAO.java(代码段)

public void releaseResources(ResultSet rs, Statement stmt, Connection cn) {
        System.out.println("rs = " + rs);
        System.out.println("stmt = " + stmt);
        System.out.println("cn = " + cn);
        try {
            if (rs != null) {
                rs.close();
            }
            if (stmt != null) {
                stmt.close();
            }
            if (cn != null) {
                cn.close();
            }
        } catch (SQLException ex) {
            System.out.println("Exception while closing DB resources rs, stmt or cn......." + ex);
        }
    }


因此,为了使我的DBUnit测试正常工作,我不得不重载上述releaseResources()方法,以便它不会关闭可以在getDataById(int id)单元测试中使用的连接对象。如下所示。

** DAO.java(带有重载方法的代码段)**

//OVERLOADED JUST TO GET DBUNIT TESTS WORKING !!! :(
public void releaseResources(Statement stmt) {
    System.out.println("\nReleasing db resources now.... 1111");
    System.out.println("stmt = " + stmt);
    try {
        if (stmt != null) {
            stmt.close();
        }
    } catch (SQLException ex) {
        System.out.println("Exception while closing DB resources stmt......." + ex);
    }
}


我不确定这是否是正确的设计。我可以如何改善呢?

完整的代码如下所示,以供进一步参考。

StateDaoTest.java

public class StateDaoTest {

    protected static Connection connection;
    protected static HsqldbConnection dbunitConnection;
    protected static StateDao dao = new StateDao();

    @BeforeClass
    public static void setupDatabase() throws Exception {
        Class.forName("org.hsqldb.jdbcDriver");
        connection = DriverManager.getConnection("jdbc:hsqldb:mem:my-project-test;shutdown=true");
        dbunitConnection = new HsqldbConnection(connection, null);
    }

    @Before
    public void createTable() throws SQLException {
        dao.setConnection(connection);
        dao.createTables();
    }

    protected IDataSet getDataSet(String name) throws Exception {
        InputStream inputStream = getClass().getResourceAsStream(name);
        assertNotNull("file" + name + " not found in classpath", inputStream);
        Reader reader = new InputStreamReader(inputStream);
        FlatXmlDataSet dataset = new FlatXmlDataSet(reader);
        return dataset;
    }

    @AfterClass
    public static void closeDatabase() throws Exception {
        System.out.println("\ninto the closeDatabase() method...");
        System.out.println("connection = " + connection);
        System.out.println("dbunitConnection = " + dbunitConnection);
        if (connection != null) {
            connection.close();
            connection = null;
        }
        if (dbunitConnection != null) {
            dbunitConnection.close();
            dbunitConnection = null;
        }
    }

    @Test
    public void testGetStateById() throws Exception {
        IDataSet setupDataSet = getDataSet("/states.xml");
        DatabaseOperation.CLEAN_INSERT.execute(dbunitConnection, setupDataSet);
        State state = dao.getStateById(1);
        assertNotNull(state);
        assertEquals("Pennsylvania", state.getName());
        assertEquals("PA", state.getStateCode());
        assertNotNull(state.getTaxPct());
        assertEquals("Y", state.getActive());
    }

}


StateDao.java

public class StateDao {

    private Connection connection;

    public void setConnection(Connection connection) {
        this.connection = connection;
    }

    //added for dbunit tests
    public void createTables() throws SQLException {
        String sql = "CREATE TABLE states (stateId INTEGER GENERATED BY DEFAULT AS IDENTITY(START WITH 1), "
                + "stateCd VARCHAR(10), name VARCHAR(20), taxPct NUMERIC, active CHAR(1))";
        Statement stmt = null;
        try {
            stmt = connection.createStatement();
            stmt.execute(sql);
        } finally {
            releaseResources(stmt);
        }
    }

    public State getStateById(long id) {
        String sql = "SELECT * FROM states WHERE stateId = " + id;

        Statement stmt = null;
        ResultSet rs = null;
        State state = null;

        System.out.println(sql);

        try {
            stmt = connection.createStatement();
            rs = stmt.executeQuery(sql);
            while (rs != null && rs.next()) {
                String stateId = StringUtils.defaultString(rs.getString("stateId"));
                String stateCd = StringUtils.defaultString(rs.getString("stateCd"));
                String name = StringUtils.defaultString(rs.getString("name"));
                String taxPct = StringUtils.defaultIfEmpty(rs.getString("taxPct"), "0");
                String active = StringUtils.defaultString(rs.getString("active"));
                state = new State(new Integer(stateId), stateCd, name, new BigDecimal(taxPct), active);
                System.out.println("state = " + state);
            }
            System.out.println("state = " + state);
        } catch (SQLException ex) {
            System.out.println("Exception whiile fetching data for a state......." + ex);
        } finally {
            releaseResources(rs, stmt, connection);
        }
        return state;
    }

    public void releaseResources(ResultSet rs, Statement stmt, Connection cn) {
        System.out.println("\nReleasing db resources now....2222");
        System.out.println("rs = " + rs);
        System.out.println("stmt = " + stmt);
        System.out.println("cn = " + cn);
        try {
            if (rs != null) {
                rs.close();
            }
            if (stmt != null) {
                stmt.close();
            }
            if (cn != null) {
                cn.close();
            }
        } catch (SQLException ex) {
            System.out.println("Exception while closing DB resources rs, stmt or cn......." + ex);
        }
    }

    //added for dbunit tests
    public void releaseResources(Statement stmt) {
        System.out.println("\nReleasing db resources now.... 1111");
        System.out.println("stmt = " + stmt);
        try {
            if (stmt != null) {
                stmt.close();
            }
        } catch (SQLException ex) {
            System.out.println("Exception while closing DB resources stmt......." + ex);
        }
    }

}

最佳答案

我会继续使用重载的releaseResources方法。如果连接是从外部传入的,则dao不拥有它,也不应该关闭它。而是应由创建连接的同一类分别关闭该连接。因此,应将getStateById更改为仅关闭resultSet和语句,并在其他位置关闭该连接。

您可以添加releaseResources的额外重载以采用resultSet和语句,或者如果您使用的是Java 7,则可以创建一个方法:releaseResouces(Closeable... closeables)。我将使此方法成为单独类的公共静态方法,以便任何类都可以使用它。

关于java - DAO设计模式与DBUnit代码,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/29954583/

10-13 05:44