I'm getting the following execption when executing sql statements
SQLServerException: The server failed to resume the transaction.
Desc:69d00000016.
I know that the following DAO implementation is not correct. I want to know what is the correct implementation for the following code and if the fact that my connFactory is declared as static can cause the above error.
private static DbConnectionFactory connFactory;
protected myDAO() {
myDAO.connFactory = DbConnectionFactoryHome.getHome().lookupFactory("facName");
}
public myReturn myAccessMethod(final int cod) throws BaseException {
Connection conn = null;
CallableStatement stmt = null;
ResultSet resSet = null;
myReturn ret= null;
try {
conn = myDAO.connFactory.getConnection();
stmt = conn.prepareCall("{call name (2)}");
stmt.setInt(1, cod);
resSet = stmt.executeQuery();
if (resSet.next()) {
ret = new myReturn(resSet.getInt("someValue"));
}
}
catch (SQLException sqle) {
throw new myException(sqle.getMessage(), (Throwable)sqle);
}
finally {
try {
if (resSet != null) {
resSet.close();
}
if (stmt != null) {
stmt.close();
}
if (conn != null) {
conn.close();
}
}
}
return ret;
}
Should I remove the static modifier from the connFactory or implement a singleton, so when the constructor is called again the factory is not recreated?
I would make your DBConnectionFactory a singleton. A good example of how to do this can be found here: Singleton DB Connectionfactory.
However, I am not sure that the your issue is with the db connection factory being static. It may actually be with the way you are extracting results with the result set. Make sure you process all your results. You should include a more complete stack trace. You may want to look into why you are getting: "The server failed to resume the transaction." There is an article about how what causes this error and how to fix it here: Failed to resume transaction
Try doing something like this:
CallableStatement stmt = connection.prepareCall("{call name (2)}");
stmt.setInt(1, cod);
stmt.execute();
ResultSet rs = (ResultSet)stmt.getObject(index);
//Loop results
while (rs.next()) {
ret = new myReturn(resSet.getInt("someValue")
}
Related
I am currently making a programme that communicates with an SQL database, after I make a query I obviously have to close the connections, I can close the connection fine, but I cannot close the actual statement itself. Is this necessary to close or does it close because it is a function of the connection itself? The code works perfectly fine I was just curious if this statement was needed. Here is the code, there error is highlighted towards the end of the returnEmployeeSalary function:
public class GroundControlToMajorTom {
public static void main(String[] args) throws ClassNotFoundException, SQLException {
System.out.println(returnEmployeeSalary("ivy"));
}
public static String returnEmployeeSalary(String name) throws ClassNotFoundException, SQLException {
HashMap<String, String> infoHR = connectionInfoHR();
String query = "SELECT salary FROM employees WHERE first_name = '" + name + "'";
Class.forName("com.mysql.cj.jdbc.Driver");
Connection con = DriverManager.getConnection(infoHR.get("url"), infoHR.get("uname"), infoHR.get("pass"));
Statement st = con.createStatement();
ResultSet rs = st.executeQuery(query);
rs.next();
String id = rs.getString("salary");
return id;
st.close(); /////////// ERROR IS HERE /////////////
con.close();
}
public static HashMap<String, String> connectionInfoHR() {
HashMap<String, String> infoHR = new HashMap();
infoHR.put("url", "jdbc:mysql://localhost:3306/sql_hr");
infoHR.put("uname", "root");
infoHR.put("pass", "");
return infoHR;
}
}
The problem is that you have statements after the return statement. Given return ends the normal flow of a method, the subsequent close methods aren't executed.
However, your code doesn't take into account abrupt exits of a method through an exception. In such situation, you won't properly close resources like statements and connections.
The appropriate solution is to use try-with-resources. Your code would then look like:
try (Connection con = DriverManager.getConnection(infoHR.get("url"), infoHR.get("uname"), infoHR.get("pass"));
Statement st = con.createStatement();
ResultSet rs = st.executeQuery(query);) {
rs.next();
return rs.getString("salary");
}
At the end of the try-with-resources block, the result set, statement and connection will be closed, in the right order, even if closing of one of these fails.
You need to close your resultSet ,statement then your database connection to release all resources from the database.
try this :
Connection connection = DriverManager.getConnection(infoHR.get("url"), infoHR.get("uname"), infoHR.get("pass"));
try {
Statement statement = connection.createStatement();
try {
ResultSet resultSet = statement.executeQuery(query);
try {
rs.next();
return rs.getString("salary");
} finally {
resultSet.close();
}
} finally {
statement.close();
}
} finally {
connection.close();
}
You could follow this article for more information :
How to Close JDBC Resources Properly – Every Time
Update :
Since Java 7 you could use this :
try (Connection connection = DriverManager.getConnection(infoHR.get("url"), infoHR.get("uname"), infoHR.get("pass"));
Statement statement = connection.createStatement()) {
try (ResultSet resultSet = statement.executeQuery(query)) {
rs.next();
return rs.getString("salary");
}
}
I am trying to launch a class only if a select query returned at least a row.
My call to thequery function noted below:
results=thequery("SELECT `username`,`numberpoints` FROM `highscores` WHERE `username` = '"+name+"'");//send query that checks if username exist
if(!results.next()) {
BallTrial trial = new BallTrial();
}
thequery function:
public ResultSet thequery(String query){
PreparedStatement statement = null;
ResultSet rs = null;
Connection con=null;
Statement st=null;
try {
con=DriverManager.getConnection("jdbc:mysql://localhost/scores","root","");
statement = con.prepareStatement(query);
rs= statement.executeQuery();
while(rs.next()){
System.out.println(rs.getString(1)+" "+rs.getString(2));
return rs;
}}
catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
System.out.println("you have not accessed the data base");
}
return null;
}
I am getting a null pointer exception at if(!results.next()) {, can anyone clarify what is my mistake here?
You should add the null check condition before calling next, the condition needs to be tweaked something around the lines: results != null && !results.next()
You need to make a couple of changes:
From thequery method, return ResultSet (i.e. rs) instead of returning null. Returning null will cause NPE. Also, remove while(...) as it needs to be done by the caller, e.g.
public ResultSet thequery(String query){
PreparedStatement statement = null;
ResultSet rs = null;
Connection con=null;
Statement st=null;
try {
con=DriverManager.getConnection("jdbc:mysql://localhost/scores","root","");
statement = con.prepareStatement(query);
rs= statement.executeQuery();
return rs;
catch (SQLException e) {
e.printStackTrace();
System.out.println("you have not accessed the data base");
throw e;
}
}
In the caller method, check whether ResultSet contains any records by calling rs.next(), e.g.:
results = thequery(..)
if(!results.next()){
BallTrial trial = new BallTrial();
}
while(true) {
if (!results.next()){
System.out.prinln("result has no data");
}else{
System.out.prinln("result has some data");
}
}
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;
}
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.
Can someone please show me how to fix the code below so that it does not throw an error?
The following line of code is giving me a null pointer exception:
return dataSource.getConnection();
Note that dataSource is an instance of javax.sql.DataSource which is specified in web.xml, and which works fine when called by other code.
Here is the actual method in DataAccessObject.java where the null pointer is occurring:
protected static Connection getConnection(){
try {
return dataSource.getConnection(); //
} catch (SQLException e) {
throw new RuntimeException(e);
}
}
The preceding method is being called by this line of code:
connection = getConnection();
Which is located in the following method in a class called CourseSummaryDAO as follows:
public List<CourseSummary> findAll(Long sid) {
LinkedList<CourseSummary> coursesummaries = new LinkedList<CourseSummary>();
ResultSet rs = null;
PreparedStatement statement = null;
Connection connection = null;
try {
connection = getConnection(); //
String sql = "select * from coursetotals where spid=?";
statement = connection.prepareStatement(sql);
statement.setLong(1, sid);
rs = statement.executeQuery();
//for every row, call read method to extract column
//values and place them in a coursesummary instance
while (rs.next()) {
CourseSummary coursesummary = read("findAll", rs);
coursesummaries.add(coursesummary);
}
return coursesummaries;
}catch (SQLException e) {
throw new RuntimeException(e);
}
finally {
close(rs, statement, connection);
}
}
To recreate this simply, I created the following TestCourseSummaries class:
public class TestCourseSummaries {
public static void main(String[] args) {
Long id = new Long(1002);
CourseSummaryDAO myCSDAO = new CourseSummaryDAO();
List<CourseSummary> coursesummaries = myCSDAO.findAll(id);
for(int i = 0;i<coursesummaries.size();i++){
System.out.println("type, numunits are: "+coursesummaries.get(i).getCourseType()+","+coursesummaries.get(i).getNumUnits());
}
}
}
EDIT:
To address JustDanyul's question, I am enclosing the code that calls in my application, and the underlying DataAccessObject code which is extended by the two DAO objects in the calling code:
Here is the code in my application which triggers the error. See there are two classes that each extended DataAccessObject. Perhaps they are conflicting with each other, causing the second one not to get the database connection?
protected void doGet(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
String idString = req.getParameter("id");
Long id = new Long(idString);
ThisObj thisobj = new ThisDAO().find(id);
req.setAttribute("thisobj", thisobj);
ThoseObjDAO myThoseDAO = new ThoseObjDAO();
List<ThoseObj> thoseobjects = myThoseObjDAO.findAll(id);
req.setAttribute("thoseobjects", thoseobjects);
jsp.forward(req, resp);
}
And here is the code for the DataAccessObject class which is extended by the two DAO classes in the calling code:
public class DataAccessObject {
private static DataSource dataSource;
private static Object idLock = new Object();
public static void setDataSource(DataSource dataSource) {
DataAccessObject.dataSource = dataSource;
}
protected static Connection getConnection() {
try {return dataSource.getConnection();}
catch (SQLException e) {throw new RuntimeException(e);}
}
protected static void close(Statement statement, Connection connection) {
close(null, statement, connection);
}
protected static void close(ResultSet rs, Statement statement, Connection connection) {
try {
if (rs != null) rs.close();
if (statement != null) statement.close();
if (connection != null) connection.close();
} catch (SQLException e) {throw new RuntimeException(e);}
}
protected static Long getUniqueId() {
ResultSet rs = null;
PreparedStatement statement = null;
Connection connection = null;
try {
connection = getConnection();
synchronized (idLock) {
statement = connection.prepareStatement("select next_value from sequence");
rs = statement.executeQuery();
rs.first();
long id = rs.getLong(1);
statement.close();
statement = connection.prepareStatement("update sequence set next_value = ?");
statement.setLong(1, id + 1);
statement.executeUpdate();
statement.close();
return new Long(id);
}
}
catch (SQLException e) {throw new RuntimeException(e);}
finally{close(rs, statement, connection);}
}
}
The data source is created in web.xml, as follows:
<resource-ref>
<description>dataSource</description>
<res-ref-name>datasource</res-ref-name>
<res-type>javax.sql.DataSource</res-type>
<res-auth>Container</res-auth>
</resource-ref>
I suspect that the code where it "runs fine" in, is code actually running in an application server. The example you are posting, which just runs a static void main() method, wont get any resources which has been defined in web.xml.
I am guessing that you use JDNI to setup the initial datasource. And then using something like
#Resource(name="jdbc/mydb")
private DataSource dataSource;
to set up your connection. Right?
EDIT:
After seeing your code, it seems like your data source is newer initialised at all. Just putting a element into your web.xml will not do it alone. You will also need to actually configure the dataSource, you know, specify the driver, username, password, uri etc etc etc.
I'm guessing the find() method of the DAO that works, isn't actually using the dataSource. What you have shown so far, doesn't insigunate that your have a initialised dataSource at all.
Just to give you an idea, I liked a tutorial on how you would do this with Tomcat and JDNI. (Or even better, use spring-jdbc).
http://www.mkyong.com/tomcat/how-to-configure-mysql-datasource-in-tomcat-6/
Use dataSource as <javax.sql.DataSource> instance, rather than an instance of <javax.activation.DataSource>.
In short, you should replace the statement <import javax.activation.DataSource;> by this other <import javax.sql.DataSource;>.
Use dataSource as javax.sql.DataSource instance, rather than an instance of javax.activation.DataSource. In short, you should replace the statement:
import javax.activation.DataSource;
by this other:
import javax.sql.DataSource;