diff --git a/src/library/assistant/database/DatabaseHandler.java b/src/library/assistant/database/DatabaseHandler.java index e9c4f53..da6d966 100644 --- a/src/library/assistant/database/DatabaseHandler.java +++ b/src/library/assistant/database/DatabaseHandler.java @@ -35,7 +35,6 @@ public final class DatabaseHandler { private static final String DB_URL = "jdbc:derby:database;create=true"; private static Connection conn = null; - private static Statement stmt = null; static { createConnection(); @@ -109,39 +108,42 @@ private static void readDBTable(Set set, DatabaseMetaData dbmeta, String } public ResultSet execQuery(String query) { - ResultSet result; + Statement stmt = null; + ResultSet result = null; try { stmt = conn.createStatement(); result = stmt.executeQuery(query); + stmt.closeOnCompletion(); } catch (SQLException ex) { - System.out.println("Exception at execQuery:dataHandler" + ex.getLocalizedMessage()); + LOGGER.log(Level.ERROR, "Exception at execQuery:dataHandler {}", ex.getLocalizedMessage()); + if (stmt != null) { + try { + stmt.close(); + } catch (SQLException e) { + LOGGER.log(Level.ERROR, "{}", e); + } + } return null; } - finally { - } return result; } public boolean execAction(String qu) { - try { - stmt = conn.createStatement(); + try (Statement stmt = conn.createStatement()) { stmt.execute(qu); return true; } catch (SQLException ex) { JOptionPane.showMessageDialog(null, "Error:" + ex.getMessage(), "Error Occured", JOptionPane.ERROR_MESSAGE); - System.out.println("Exception at execQuery:dataHandler" + ex.getLocalizedMessage()); + LOGGER.log(Level.ERROR, "Exception at execAction:dataHandler {}", ex.getLocalizedMessage()); return false; } - finally { - } } public boolean deleteBook(Book book) { - try { - String deleteStatement = "DELETE FROM BOOK WHERE ID = ?"; - PreparedStatement stmt = conn.prepareStatement(deleteStatement); + String deleteStatement = "DELETE FROM BOOK WHERE ID = ?"; + try (PreparedStatement stmt = conn.prepareStatement(deleteStatement)) { stmt.setString(1, book.getId()); int res = stmt.executeUpdate(); if (res == 1) { @@ -155,9 +157,8 @@ public boolean deleteBook(Book book) { } public boolean isBookAlreadyIssued(Book book) { - try { - String checkstmt = "SELECT COUNT(*) FROM ISSUE WHERE bookid=?"; - PreparedStatement stmt = conn.prepareStatement(checkstmt); + String checkstmt = "SELECT COUNT(*) FROM ISSUE WHERE bookid=?"; + try (PreparedStatement stmt = conn.prepareStatement(checkstmt)) { stmt.setString(1, book.getId()); ResultSet rs = stmt.executeQuery(); if (rs.next()) { @@ -173,9 +174,8 @@ public boolean isBookAlreadyIssued(Book book) { } public boolean deleteMember(MemberListController.Member member) { - try { - String deleteStatement = "DELETE FROM MEMBER WHERE id = ?"; - PreparedStatement stmt = conn.prepareStatement(deleteStatement); + String deleteStatement = "DELETE FROM MEMBER WHERE id = ?"; + try (PreparedStatement stmt = conn.prepareStatement(deleteStatement)) { stmt.setString(1, member.getId()); int res = stmt.executeUpdate(); if (res == 1) { @@ -189,9 +189,8 @@ public boolean deleteMember(MemberListController.Member member) { } public boolean isMemberHasAnyBooks(MemberListController.Member member) { - try { - String checkstmt = "SELECT COUNT(*) FROM ISSUE WHERE memberID=?"; - PreparedStatement stmt = conn.prepareStatement(checkstmt); + String checkstmt = "SELECT COUNT(*) FROM ISSUE WHERE memberID=?"; + try (PreparedStatement stmt = conn.prepareStatement(checkstmt)) { stmt.setString(1, member.getId()); ResultSet rs = stmt.executeQuery(); if (rs.next()) { @@ -207,9 +206,8 @@ public boolean isMemberHasAnyBooks(MemberListController.Member member) { } public boolean updateBook(Book book) { - try { - String update = "UPDATE BOOK SET TITLE=?, AUTHOR=?, PUBLISHER=? WHERE ID=?"; - PreparedStatement stmt = conn.prepareStatement(update); + String update = "UPDATE BOOK SET TITLE=?, AUTHOR=?, PUBLISHER=? WHERE ID=?"; + try (PreparedStatement stmt = conn.prepareStatement(update)) { stmt.setString(1, book.getTitle()); stmt.setString(2, book.getAuthor()); stmt.setString(3, book.getPublisher()); @@ -224,9 +222,8 @@ public boolean updateBook(Book book) { } public boolean updateMember(MemberListController.Member member) { - try { - String update = "UPDATE MEMBER SET NAME=?, EMAIL=?, MOBILE=? WHERE ID=?"; - PreparedStatement stmt = conn.prepareStatement(update); + String update = "UPDATE MEMBER SET NAME=?, EMAIL=?, MOBILE=? WHERE ID=?"; + try (PreparedStatement stmt = conn.prepareStatement(update)) { stmt.setString(1, member.getName()); stmt.setString(2, member.getEmail()); stmt.setString(3, member.getMobile()); @@ -289,13 +286,13 @@ public ObservableList getMemberGraphStatistics() { } private static void createTables(List tableData) throws SQLException { - Statement statement = conn.createStatement(); - statement.closeOnCompletion(); - for (String command : tableData) { - System.out.println(command); - statement.addBatch(command); + try (Statement statement = conn.createStatement()) { + for (String command : tableData) { + System.out.println(command); + statement.addBatch(command); + } + statement.executeBatch(); } - statement.executeBatch(); } public Connection getConnection() { diff --git a/test/library/assistant/database/DatabaseHandlerTest.java b/test/library/assistant/database/DatabaseHandlerTest.java new file mode 100644 index 0000000..b7c78f5 --- /dev/null +++ b/test/library/assistant/database/DatabaseHandlerTest.java @@ -0,0 +1,78 @@ +package library.assistant.database; + +import java.lang.reflect.Field; +import java.sql.Connection; +import java.sql.ResultSet; +import java.sql.Statement; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.junit.MockitoJUnitRunner; + +import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +@RunWith(MockitoJUnitRunner.class) +public class DatabaseHandlerTest { + + @Mock + private Connection mockConnection; + + @Mock + private Statement mockStatement; + + @Mock + private ResultSet mockResultSet; + + @Test + public void testExecQueryClosesStatementOnCompletion() throws Exception { + // Setup mock behavior + when(mockConnection.createStatement()).thenReturn(mockStatement); + when(mockStatement.executeQuery(anyString())).thenReturn(mockResultSet); + + // Get instance (it's a singleton) + // This will trigger static initialization. Ensure libs are in classpath. + DatabaseHandler handler = DatabaseHandler.getInstance(); + + // Inject mock connection via reflection + Field connField = DatabaseHandler.class.getDeclaredField("conn"); + connField.setAccessible(true); + connField.set(null, mockConnection); // static field + + // Execute query + ResultSet rs = handler.execQuery("SELECT * FROM TEST"); + + // Verify statement creation and execution + verify(mockConnection).createStatement(); + verify(mockStatement).executeQuery("SELECT * FROM TEST"); + + // Verify closeOnCompletion is called + verify(mockStatement).closeOnCompletion(); + } + + @Test + public void testExecActionClosesStatement() throws Exception { + // Setup mock behavior + when(mockConnection.createStatement()).thenReturn(mockStatement); + when(mockStatement.execute(anyString())).thenReturn(true); + + // Get instance + DatabaseHandler handler = DatabaseHandler.getInstance(); + + // Inject mock connection via reflection + Field connField = DatabaseHandler.class.getDeclaredField("conn"); + connField.setAccessible(true); + connField.set(null, mockConnection); + + // Execute action + handler.execAction("UPDATE TEST SET A=1"); + + // Verify statement creation and execution + verify(mockConnection).createStatement(); + verify(mockStatement).execute("UPDATE TEST SET A=1"); + + // Verify close is called + verify(mockStatement).close(); + } +}