I have this unit test that started showing an error after I entered these two new parameters connection and notification.
I tried to make the mock but it is showing the error "Cannot open transaction cause it is null", can someone help me?
protected int getTotalRecords(Connection connection, Statement statement, final String sql, NotificationData notification) {
int rows = 0;
ResultSet rs = null;
try(ResultSet resultSet = statement.executeQuery(buildCountRecordsSQL(sql))) {
if (resultSet.next()) {
rows = resultSet.getInt("ROWS_COUNT");
}
} catch (SQLException e) {
try{
SEEntityManager.rollbackAndReOpenTransaction();
statement = connection.createStatement();
rs = statement.executeQuery(notification.getFieldSql());
return rows = BROKE_SQL;
}catch (final SQLException e1){
logger.error(e1.getMessage(), e1);
}
}
logger.debug("Total records: "+rows);
return rows;
}
Test Junit
#Test
public void verifyExceptionCountRecords() throws SQLException{
Mockito.when(resultSet.next()).thenThrow(new SQLException());
assertTrue(daoDefault.getTotalRecords(Mockito.mock(Connection.class), statement, "", notification)==0);
Mockito.verify(resultSet, Mockito.never()).getInt("ROWS_COUNT");
}
Tests in error:
Cannot open transaction cause it is null
Related
I am trying to mock a object in the junit test file. I am getting value in test file
public void TestMethod() throws SQLException{
String projectID = "Test";
Connection connectionMock = Mockito.mock(Connection.class);
PreparedStatement preparedStatementMock = Mockito.mock(PreparedStatement.class);
ResultSet resultSetMock = Mockito.mock(ResultSet.class);
mockStatic(Manager.class);
Worker workerMock = Mockito.mock(Worker.class);
mockingDetails(workerMock);
mock(PreparedStatement.class);
mock(ResultSet.class);
when(workerMock.getProjectId())
.thenReturn(projectID);
when(Manager.getDatabaseConnection())
.thenReturn(connectionMock);
when(connectionMock.prepareStatement(""))
.thenReturn(preparedStatementMock);
when(preparedStatementMock.executeQuery())
.thenReturn(resultSetMock);
//mockStatic(Manager.class);
System.out.println("workerMock--------->"+workerMock);
System.out.println("prepared stmt--------->"+preparedStatementMock);
assertNotNull(service.getProtocol());
}
If I print here I am getting value worker and prepared statement like this value
"Mock for Worker, hashCode: 853323835"
If I print same in my real method, I am getting null for both worker and prepared statement. I have used annotations
#RunWith(PowerMockRunner.class)
#PrepareForTest(Manager.class)
in the test class
public String Method() throws SQLException
{
Connection conn = Manager.getDatabaseConnection();
String protocol = null;
StringBuilder qryBuilder = new StringBuilder("MyQuery");
qryBuilder.append("condition = ?");
System.out.println("worker.getProjectId()------------->"+worker);
System.out.println("connection------------->"+conn);
PreparedStatement pst = conn.prepareStatement(qryBuilder.toString());
System.out.println("pst------------->"+pst);
pst.setString(1, worker.getProjectId());
try {
ResultSet rset = pst.executeQuery();
try {
while (rset.next()) {
protocol = rset.getString(1);
}
rset.close();
} finally {
pst.close();
}
} catch (SQLException e) {
throw e;
}
return protocol;
}
I'm trying to execute method which should create a new object with fields from database, and everytime i run this code im getting SQLException: ResultSet closed.
public DatabasedClient getDatabaseClient(int clientDatabaseid){
if(DatabaseClientUtil.isInDatabase(clientDatabaseid)){
return DatabaseClientUtil.getDBClient(clientDatabaseid);
}else{
try{
System.out.println("Trying to find user in db");
ResultSet rs = fbot.getStorage().query("select * from database_name where clientDBId = " + clientDatabaseid);
System.out.println("deb " + rs.getString("nick"));
while (rs.next()) {
DatabasedClient databasedClient = new DatabasedClient(clientDatabaseid);
databasedClient.setUid(rs.getString("uid"));
databasedClient.setNick(rs.getString("nick"));
databasedClient.setLastConnect(rs.getLong("lastConnected"));
databasedClient.setLastDisconnect(rs.getLong("lastDisconnect"));
databasedClient.setTimeSpent(rs.getLong("timeSpent"));
databasedClient.setLongestConnection(rs.getLong("longestConnection"));
return databasedClient;
}
} catch (SQLException e) {
e.printStackTrace();
}
}
return null;
}
}
Im using hikari, here are methods from AbstractStorage class
#Override
public void execute(String query) throws SQLException {
try (Connection connection = getConnection()){
connection.prepareStatement(query).executeUpdate();
}
}
#Override
public ResultSet query(String query) throws SQLException {
try (Connection connection = getConnection()) {
return connection.prepareStatement(query).executeQuery();
}
}
Screenshot from error
I hope someone will help me with this.
I think the exact error you are seeing is being caused by the following line of code:
System.out.println("deb " + rs.getString("nick"));
You are trying to access the result set before you advance the cursor to the first record. Also, your method getDatabaseClient is returning a single object which conceptually maps to a single expected record from the query. Hence, iterating once over the result set would seem to make sense. Taking all this into consideration, we can try the following:
try {
System.out.println("Trying to find user in db");
ResultSet rs = fbot.getStorage().query("select * from database_name where clientDBId = " + clientDatabaseid);
// do not access the result set here
if (rs.next()) {
DatabasedClient databasedClient = new DatabasedClient(clientDatabaseid);
databasedClient.setUid(rs.getString("uid"));
databasedClient.setNick(rs.getString("nick"));
databasedClient.setLastConnect(rs.getLong("lastConnected"));
databasedClient.setLastDisconnect(rs.getLong("lastDisconnect"));
databasedClient.setTimeSpent(rs.getLong("timeSpent"));
databasedClient.setLongestConnection(rs.getLong("longestConnection"));
return databasedClient;
}
} catch (SQLException e) {
e.printStackTrace();
}
I have a problem trying to execute more than one query into my Java Application code.
I have a procedure that is called in main and is in the class "Fant":
public void XXX(){
Connectivity con=new Connectivity(); // this class set up the data for the connection to db; if ( !con.connect() ) {
System.out.println("Error during connection.");
System.out.println( con.getError() );
System.exit(0);
}
ArrayList<User> blabla=new ArrayList<User>();
blabla=this.getAllUsers(con);
for (User u:blabla)
{
try {
Connectivity coni=new Connectivity();//start a new connection each time that i perform a query
Statement t;
t = coni.getDb().createStatement();
String query = "Select count(*) as rowcount from berebe.baraba";
ResultSet rs = t.executeQuery(query);
int numPrenotazioni=rs.getInt("rowcount");
rs.close(); //close resultset
t.close(); //close statement
coni.getDb().close(); //close connection
}
}
catch (SQLException e)
{
System.err.println("SQLState: " +
((SQLException)e).getSQLState());
System.err.println("Error Code: " +
((SQLException)e).getErrorCode());
}
}
}
The called function is defined as:
ArrayList<User> getAllUsers(Connectivity con) {
try{
ArrayList<User> userArrayList=new ArrayList<User>();
String query = "Select idUser,bubu,lala,sisi,gogo,gg from berebe.sasasa";
Statement t;
t = con.getDb().createStatement();
ResultSet rs = t.executeQuery(query);
while (rs.next())
{
User utente=new User(....); //user fields got from query
userArrayList.add(utente);
}
rs.close();
t.close();
con.disconnect(); //disconnect the connection
return userArrayList;
} catch (SQLException e) {
}
return null;
}
The main is:
public static void main(String[] argv) {
ArrayList<User> users=new ArrayList<User>();
System.out.println("-------- MySQL JDBC Connection Testing ------------");
Fant style = new Fant();
style.XXX();
}
The query performed into "getAllusers" is executed and into the arraylist "blabla" there are several users; the problem is that the second query that needs the count is never executed.
The MYSQlState given when running is= "S1000" and the SQLERROR is "0".
Probably i'm mistaking on connections issues but i'm not familiar with statements,connections,resultsets.
Thank you.
You might forget to call rs.next() before getting the result form it in XXX()methods as shown below:
ResultSet rs = t.executeQuery(query);
// call rs.next() first here
int numPrenotazioni=rs.getInt("rowcount");
can anyone please tell why the following update query which is working perfectly when executed directly from my SQLYog editor, but not executing from java. it is not giving any exception but not updating into the database.
this the update query
UPDATE hotel_tables SET hotel_tables.status='reserved' WHERE hotel_tables.section='pub' AND tableno='4' AND ('4' NOT IN (SELECT tableno FROM table_orders WHERE outlet='pub'))
Java code
public static void main(String[] args) throws Exception {
int update = new Dbhandler().update("UPDATE hotel_tables SET hotel_tables.status='reserved' WHERE hotel_tables.section='pub' AND tableno='4' AND ('4' NOT IN (SELECT tableno FROM table_orders WHERE outlet='pub'))");
}
public int update(String Query)throws Exception
{
try
{
cn=getconn();
stmt=(Statement) cn.createStatement();
n=stmt.executeUpdate(Query);
stmt.close();
}
catch(Exception e)
{
e.printStackTrace();
throw(e);
}
finally
{
cn.close();
}
return n;
}
public Connection getconn()
{
try
{
Class.forName(driver).newInstance();
String url="jdbc:mysql://localhost/kot?user=root&password=root";
cn=(Connection) DriverManager.getConnection(url);
}
catch(Exception e)
{
System.out.println("DBHandler ERROR:"+e);
}
return cn;
}
This is how I used to do it before I switched to Spring's JdbcTemplate framework. Maybe this will help. It looks very similar to yours.
public static int runUpdate(String query, DataSource ds, Object... params) throws SQLException {
int rowsAffected = 0;
Connection conn = null;
PreparedStatement stmt = null;
try {
conn = ds.getConnection();
stmt = conn.prepareStatement(query);
int paramCount = 1;
for (Object param : params) {
stmt.setObject(paramCount++, param);
}
rowsAffected = stmt.executeUpdate();
conn.commit();
} catch (SQLException sqle) {
throw sqle;
//log error
} finally {
closeConnections(conn, stmt, null);
}
return rowsAffected;
}
There are some subtle differences. I do a commit, though autoCommit is the default.
Try like this:
DriverManager.getConnection("jdbc:mysql://localhost:3306/kot","root","root");
In the following code, I execute a query on a SQLite JDBC connection via the executeRestitutionalQuery(String query) method:
public static ArrayList<Metadata> findMetadata(String name, String text, String after, String before, String repPath)
throws SQLException, ClassNotFoundException {
ArrayList<Metadata> data = new ArrayList<Metadata>();
boolean needADD = false;
String query = "SELECT * from " + TABLE_NAME_METADATA;
...
query += " ORDER BY timestamp DESC;";
ResultBundle bundle = executeRestitutionalQuery(query);
ResultSet result = bundle.getResultSet();
while(result.next()){
Metadata metadata = new Metadata(result.getLong("id"), result.getString("name"), Timestamp.valueOf(result.getString("timestamp")),
result.getInt("filesNo"), result.getLong("size"), result.getString("description"), -1);
data.add(metadata);
}
closeStatementAndResultSet(bundle.getStatement(), bundle.getResultSet());
return data;
}
private static ResultBundle executeRestitutionalQuery(String query) throws SQLException, ClassNotFoundException{
Connection connection = null;
Statement statement = null;
ResultSet result = null;
ResultBundle bundle = null;
try{
connection = getConnection();
statement = connection.createStatement();
statement.executeUpdate(query);
connection.commit();
result = statement.executeQuery(query);
bundle = new ResultBundle(statement, result);
}finally{
if(connection != null){
try{
connection.close();
}catch (Exception e){
/* ignored */
}
}
}
return bundle;
}
private static void closeStatementAndResultSet(Statement statement, ResultSet result){
if(result != null){
try{
result.close();
}catch (Exception e){
// ignored
}
}
if(statement != null){
try{
statement.close();
}catch (Exception e){
// ignored
}
}
}
The ResultBundle class is just used to summarize the resultset and the statement. It looks like this:
public class ResultBundle {
private final Statement statement;
private final ResultSet result;
public ResultBundle(Statement statement, ResultSet result){
this.result = result;
this.statement = statement;
}
public Statement getStatement(){
return statement;
}
public ResultSet getResultSet(){
return result;
}
}
The problem is, that every call to result.getLong(), result.getString() etc. returns null resp. 0. I can't understand why. The queries should all be okay, as the code was running fine before I had to do some refactoring. Could the problem arise from the ResultBundle-class? What am I not seeing here?
Statements and ResultSets are "live" objects, living only as long as their connection. The executeRestitutionalQuery returns a ResultBundle, whose result and statement members are implicitly closed on return when the connection is closed in the finally block.
try {
...
}finally{
if(connection != null){
try{
connection.close(); // <---- here's the problem
}catch (Exception e){
/* ignored */
}
}
}
By the time, the caller of executeRestitutionalQuery can lay its hand on the resource bundle, the connection has been closed, and the result set is "dead".
I would say this is a bad design.
A better one would keep the SQL objects in tight scope, map results into a collection or object and immediately close all those scarce resources. Not only will the data be available to clients, but you'll avoid nasty problems with connection and cursors exhausted. It'll scale better, too.