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");
}
}
Related
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");
}
}
Well, I'm trying to use SQLite in my Libgdx game, but don't know how.
public class Main {
public static void main(String[] args){
LwjglApplicationConfiguration config = new LwjglApplicationConfiguration();
config.title = Game.TITLE;
config.width = Game.V_WIDTH * Game.SCALE;
config.height = Game.V_HEIGHT * Game.SCALE;
new LwjglApplication(new Game(), config);
}}
What I need to do in my main? lol
I've been looking for this but, all I can find is related to Android application.
I already have the driver in my ref libraries, and connection class..
What I usually do when using a database with an application, is make a ConnectionFactory, that returns a new connection to the database.
public class ConnectionFactory {
public static Connection getConnection() {
Connection con = null;
Class.forName("org.sqlite.JDBC");
con = DriverManager.getConnection("jdbc:sqlite:test.db"); //change to whatever db you want
return con;
}
}
now we have a ConnectionFactory that can pump out connections to our database. Now when we want to interact with the database, you can get the connection appropriately. inside your main, it might look something like this:
public static void main(String[] args) {
Connection con = null;
String firstName = null, lastName = null;
try {
con = ConnectionFactory.getConnection();
PreparedStatement pstmt = con.prepareStatement("SELECT * FROM myTable where myId = ?");
pstmt.setInt(1, /*some id here, ill put this as example:*/ 1234567);
//execute the query and put into result set so we can get the values.
ResultSet rs = pstmt.executeQuery();
//the resultset iterates through rows, by calling next
if( rs.next() ) //could be while(rs.next()) if expecting multiple rows
{
firstName = rs.getString("firstName"); //column name you want to grab here
lastName = rs.getString("lastName");
}
} catch(SQLException sqle) {
sqle.printStackTrace();
}
finally {
try {
con.close(); //dont forget to close your connection to database!
} catch(SQLException sqle) {
sqle.printStackTrace();
}
}
}
You will need to create tables within the SQLite database and insert records before you can do any interactions though, so keep that in mind.
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")
}
Here is my code:
public void actionPerformed(ActionEvent e)
{
JButton source = (JButton)e.getSource();
if(source == buttonShop)
{
try
{
Connection myConn = DriverManager.getConnection("jdbc:mysql://localhost:3306/database?autoReconnect=true&useSSL=false", "xxx", "xxx");
Statement myStmt = myConn.createStatement();
ResultSet myRs1 = myStmt.executeQuery("select * from shop");
while(myRs1.next())
{
shop += myRs1.getString("ID_SHOP")+" "+myRs1.getString("NAME")+" "+myRs1.getString("ADRESS")+" "+myRs1.getString("PHONE")+"\n";
}
}catch(Exception exc){
exc.printStackTrace();
};
notifyObserver1();
shop = "";
}
else if(source == buttonEmployee)
{
try
{
Connection myConn = DriverManager.getConnection("jdbc:mysql://localhost:3306/database?autoReconnect=true&useSSL=false", "xxx", "xxx");
Statement myStmt = myConn.createStatement();
ResultSet myRs2 = myStmt.executeQuery("select * from employee");
while(myRs2.next())
{
employee += myRs2.getString("ID_EMPLOYEE")+" "+myRs2.getString("ID_SHOP")+" "+myRs2.getString("NAME")+" "+myRs2.getString("SURNAME")+"\n";
}
}catch(Exception exc){
exc.printStackTrace();
};
notifyObserver2();
employee = "";
}
}
This is a database app. I don't want to copy-paste every Connection myConn =... and Statement myStmt =... fragment to all button sources. How to make it 'global' to be visible out of actionPerformed method?
First You should have a Db Utility say 'DBUtil' class with at least a getConnection method.
This getConnection should create a connection or return it from pool depending upon your implementation.
DBUtil Class:
static Connection getConnection()
After that create two helper methods to handle both of the scenarios, something like:
getEmployeeDetails(){}
getShopDetails(){}
Inside these methods you should ideally use:
try(Connection conn = DBUtil.getConnection();
PreparedStatement st = conn.prepareStatement("Your Qry");
ResultSet rs = st.executeQuery()){
// Do Something
}
Some good points:
Use PreparedStatements
Use Try with Resource to prevent resource leaks or handle it manually
As a good practice, create, initialize and close the resource within a single method. You should not pass the resources to other methods for processing, this type of design can lead to major leak issues.
You can also make one generalized method, pass the query string to that, do some conditional processing and then return the final result to caller. This generalized method will handle db communication.
What is the problem in this code? where it is update the all column values with the same last one .
public class dbconnection {
java.sql.Connection con;
java.sql.Statement st;
ResultSet rs;
public EncBean getConnection()throws SQLException{
EncBean encBean1 = new EncBean();
String v_url= "jdbc:oracle:thin:#192.168.2.138:1522:orcl2";
String v_username= "scott";
String v_password = "tiger";
try
{
DriverManager.registerDriver(new oracle.jdbc.OracleDriver());
con = DriverManager.getConnection(v_url,v_username,v_password);
System.out.println ("Connection to Oracle database was Established");
}
catch ( SQLException e)
{
e.printStackTrace();
}
return encBean1;
}
public EncBean selectRows()
{
EncBean encBean2 = new EncBean();
try
{
String SQLselect="select JOB_NAME from job";
st=con.createStatement();
rs=st.executeQuery(SQLselect);
while (rs.next()) {
encBean2.setName(rs.getString("JOB_NAME"));
}
}
catch ( Exception ex )
{
ex.printStackTrace();
}
return encBean2;
}
public void updateRows(String updatedname){
try
{
Statement stmt = con.createStatement(ResultSet.TYPE_FORWARD_ONLY,ResultSet.CONCUR_UPDATABLE);
ResultSet srs = stmt.executeQuery("select job_name from job " );
while (srs.next()) {
srs.updateString("job_name", updatedname);
srs.updateRow();
con.commit();}
System.out.println("An existing user was updated successfully!");}
catch(SQLException err){
System.out.println(err.getMessage());
}}}
This is the main
public class mainenc {
public static void main(String[] args) throws Exception{
dbconnection dbcon = new dbconnection();
EncBean encbeancon= dbcon.getConnection();
EncBean encBean5 = dbcon.selectRows();
enc concatinputs = new enc();
EncBean encBeanconcat = concatinputs.funconcat(encBean5.getName());
EncBean encBean4 = concatinputs.inputencryption(encBeanconcat.getConcatenatedData());
String vReserverbin= encBean4.getReversedBinary();
String ascistring= concatinputs.convertBinaryStringToString(vReserverbin);
dbcon.updateRows(ascistring);
}}
What is the problem in this code? where it is update the all column values with the same last one .
After updated method you should write list method again.
Try to take this example:
UPDATE tableB
SET tableB.value , tableA.value, tableB.value)
WHERE tableA.name = 'Joe'
It is kind of obvious: dbcon.updateRows(...) calls for the update method and that method does the job.
But as Erhan said, you don't get to see the result because you don't actually make use of updated records, e.g. show them etc. At least, you can check it out at the DB level if op is completed.
But I really disliked your comment:
plz can you do it for me?
You should do your own task and ask help when you need a hand. But never expect someone else to do your job mate.