I wrote code to run multiple statement in single connection. The first statement will retrieve IDs to be looped and used by the second statement then get the desired output. As example:
String sql1 = "SELECT ID FROM __TestParent WHERE Status = 'S'";
try (
Connection conn = DbConnector.getConnection();
Statement s = conn.createStatement();
Statement s2 = conn.createStatement();
ResultSet rs = s.executeQuery(sql1)
) {
while(rs.next()) {
String id = String.valueOf(rs.getInt("ID"));
String sql2 = "SELECT Description FROM __TestChild WHERE FK = " + id;
try (
ResultSet rs2 = s2.executeQuery(sql2)
) {
while(rs2.next())
Util.printLog("INFO",rs2.getString("Description"));
}catch(SQLTimeoutException sqltoex){
Util.printLog("SEVERE",sqltoex);
}catch(SQLException sqlex){
Util.printLog("SEVERE",sqlex);
}
}
}catch(SQLTimeoutException sqltoex){
Util.printLog("SEVERE",sqltoex);
}catch(SQLException sqlex){
Util.printLog("SEVERE",sqlex);
}
Util.printLog method is to print the message in the desired format
The code run perfectly fine and the output was as expected. What I want to know is:
Is this the right way to do it, or is/are there better way to write the code.
Is there anything that I need to be aware of? Because I seems cannot find anything about this use case other than this link Multiple-statements-single-connection from CodeRanch which is 16-year-old thread and I'm not quite clear other than driver support.
Thanks.
You can actually do what you want using a single query and result set:
SELECT c.Description
FROM __TestChild c
INNER JOIN __TestParent p
ON c.FK = p.ID
WHERE p.Status = 'S';
Code:
String sql = "SELECT c.Description FROM __TestChild c ";
sql += " INNER JOIN __TestParent p ON c.FK = p.ID ";
sql += "WHERE p.Status = 'S'";
try (
Connection conn = DbConnector.getConnection();
Statement s = conn.createStatement();
ResultSet rs = s.executeQuery(sql)
) {
while(rs.next()) {
Util.printLog("INFO", rs.getString("Description"));
}
} catch(SQLTimeoutException sqltoex) {
Util.printLog("SEVERE",sqltoex);
} catch(SQLException sqlex) {
Util.printLog("SEVERE",sqlex);
}
Related
The user must choose a Resort ID from the table that is displayed and the make a booking. I can't seem to find my problem, I want to print the name of the Resort that they are making a booking at.
String x = jTextFieldID.getText();
Integer Resort = Integer.valueOf(x);
int resort = Integer.parseInt(x);
String sql = "SELECT RESORT_NAME FROM LouwDataBase.Resorts WHERE ID = "+Resort;
try (PreparedStatement pstmt = conn.prepareStatement(sql)) {
pstmt.setInt(1, resort);
try (ResultSet rs = pstmt.executeQuery()) {
if (rs.next()) {
String resortName = rs.getString("RESORT_NAME");
JOptionPane.showMessageDialog(null,
"You want to book at " + resortName);
}
You have to use rs.next() :
ResultSet rs = pstmt.executeQuery(sql);
String resortName = "";
if(rs.next()){//<<-----------------------------
resortName = rs.getString("RESORT_NAME");
}
JOptionPane.showMessageDialog(null, "You want to book at "+resortName);
If you want to get many results you can use while(rs.next){...} instead.
Note? for a good practice, don't use upper letter in beginning for the name of your variables ResortName use this instead resortName
You need to test over the ResultSet result before trying to read from it:
if(rs.next()) {
String ResortName = rs.getString(1);
JOptionPane.showMessageDialog(null, "You want to book at "+ResortName);
}
And you can use getString(1) to get the RESORT_NAME, check ResultSet .getString(int index) method for further details.
The error is that sql is passed to Statement.executeQuery(String) too, instead of the PreparedStatement.executeQuery().
int resort = Integer.parseInt(x);
//String sql = "SELECT RESORT_NAME FROM LouwDataBase.Resorts WHERE ID = ?";
String sql = "SELECT RESORT_NAME FROM LouwDataBase.Resorts WHERE ID = " + resort;
try (PreparedStatement pstmt = conn.prepareStatement(sql)) {
//pstmt.setInt(1, resort);
try (ResultSet rs = pstmt.executeQuery()) {
if (rs.next()) {
String resortName = rs.getString("RESORT_NAME");
JOptionPane.showMessageDialog(null,
"You want to book at " + resortName);
}
}
} catch (SQLException ex) {
Logger.getLogger(Booking.class.getName()).log(Level.SEVERE, null, ex);
}
Commented is the alternative usage of a prepared statement (as normally used).
Also you should close statement and result set, which can be done automatically with try-with-resources as above.
Oh, oversaw almost, that rs.next() must be called. (The others already mentioned.)
I know many questions were asked before for this issue but for this situations I can't find an answer.
This is my code:
private Collection<Coupon> getCouponsMain(Company company, String filters) throws DAOException
{
String sql = null;
if (filters != null)
{
sql = "SELECT couponsystem.coupon.* FROM couponsystem.company_coupon LEFT JOIN couponsystem.coupon ON "
+ "couponsystem.company_coupon.COUPON_ID = couponsystem.coupon.ID WHERE couponsystem.company_coupon.COMP_ID = ? AND ?";
}
else
{
sql = "SELECT couponsystem.coupon.* FROM couponsystem.company_coupon LEFT JOIN couponsystem.coupon ON "
+ "couponsystem.company_coupon.COUPON_ID = couponsystem.coupon.ID WHERE couponsystem.company_coupon.COMP_ID = ?";
}
try (Connection con = pool.OpenConnection(); PreparedStatement preparedStatement = con.prepareStatement(sql);)
{
// query command
preparedStatement.setLong(1, company.getId());
if (filters != null)
{
preparedStatement.setString(2, filters);
}
ResultSet rs = preparedStatement.executeQuery();
if (rs.next())
{
CouponDBDAO couponDao = new CouponDBDAO();
rs.previous();
return couponDao.BuildCoupons(rs);
}
else
{
return null;
}
}
catch (SQLException | NullPointerException e)
{
throw new DAOException("Failed to retrieve data for all coupons" + e.getMessage());
}
}
I think the query itself is not the important issue here but, once I use next() for the ResultSet, I get the error:
java.sql.SQLException: Operation not allowed after ResultSet closed"
This usually happened when using two rs for same statement, this is not the case this time.
Due to many issues with previous method and BuildCoupons(rs) issue, also this part does not work properly for the same reason:
#Override
public Company getCompany(long id) throws DAOException
{
String sql = "SELECT * FROM couponsystem.company WHERE ID = ?";
try (Connection con = pool.OpenConnection(); PreparedStatement preparedStatement = con.prepareStatement(sql);)
{
// query command
preparedStatement.setLong(1, id);
// query execution
ResultSet rs = preparedStatement.executeQuery();
Company comp = new Company();
if (rs.next())
{
//Fill customer object from Customer table
comp.setId(rs.getLong("ID"));
comp.setCompName(rs.getString("COMP_NAME"));
comp.setPassword(rs.getString("PASSWORD"));
comp.setEmail(rs.getString("EMAIL"));
comp.setCoupons(comp.getCoupons());
}
else
{
comp = null;
}
return comp;
}
catch (SQLException e)
{
throw new DAOException("Failed to retrieve data for customer id: " + id);
}
}
BTW - working with MySQL and insert, update and delete queries are working properly so there not issue with the connection to the db
Another update -
Once i replace it to regular statement, it's working but of course i'm losing all the advantages of prepared statement
Like i said i create new code in order to isolate the big program
This is the code:
public class testState
{
public static void main(String[] args) throws SQLException
{
DBDAO pool = DBDAO.getInstance();
String sql = "SELECT ID FROM couponsystem.company WHERE COMP_NAME = ? AND PASSWORD = ?";
String compName = "t";
String password = "t";
pool.CreatePool();
Connection con = pool.OpenConnection();
PreparedStatement preparedStatement = con.prepareStatement(sql);
preparedStatement.setString(1, compName);
preparedStatement.setString(2, password);
preparedStatement.executeQuery();
ResultSet rs = preparedStatement.executeQuery();
System.out.println("rs status: " + rs.isClosed());
if (rs.next())
{
System.out.println("log-in was successfuly performed");
System.out.println(rs.getLong(1));
System.out.println("hjhjh");
}
else
{
System.out.println("-1");
}
rs.close();
preparedStatement.close();
con.close();
pool.CloseConnection();
}
}
Problem was solved,
this is the problem:
sql = "SELECT couponsystem.coupon.* FROM couponsystem.company_coupon LEFT JOIN couponsystem.coupon ON "
+ "couponsystem.company_coupon.COUPON_ID = couponsystem.coupon.ID WHERE couponsystem.company_coupon.COMP_ID = ? AND ?";
the second ? is illegal, but the exception is ResultSet closed and not query issue
the problem is you are trying to go back to the previous record in the result set which is not possible.
learn about scrollable resultset and make it insensitive, once you use this you can go back to the previous record by using rs.previous()
ResultSet.TYPE_SCROLL_INSENSITIVE
I have this piece of code where I prompt the user to enter the depID to edit a department and then through the IF statement I have done it displays either saved or department doesn't exists. Now my problem is that it's going directly to the else statement. When I used debugging I noticed that the RS (ResultSet) is only comaring the users input to the first row of the table which is AOL.
try{
String value1 = txt_depID.getText();
String value2 = txt_depName.getText();
String sql = "Update tblDepartment set depID = '"+value1+"' , depName = '"+value2+"' where depID = '"+value1+"'";
String sql1 = "Select depID, depName from tblDepartment";
Class.forName(driver);
conn = DriverManager.getConnection(url);
ps = conn.prepareStatement(sql1);
rs = ps.executeQuery();
ps = conn.prepareStatement(sql);
ps.execute();
if(rs.next()){
String depi = rs.getString("depID"); //Issue: only reading first row
if(depi.equals(value1)){
JOptionPane.showMessageDialog(null, "Entry Saved");
}
else{
JOptionPane.showMessageDialog(null, "Department doesn't exist");
}
}
} catch (Exception e){
JOptionPane.showMessageDialog(null, e);
}
You can do this in one cycle. You should be using executeUpdate.
String sql = "Delete from tblEmployee where staffNo=?";
String sql1 = "Select * from tblEmployee";
Class.forName(driver);
conn = DriverManager.getConnection(url);
ps = conn.prepareStatement(sql1);
int result = ps.executeUpdate();
if (result > 0) {
// success
}
Here's what executeUpdate results:
Returns: either (1) the row count for SQL Data Manipulation Language
(DML) statements or (2) 0 for SQL statements that return nothing
I am using following method for calculating payroll by using jdbc but "ORA-01008: not all variables bound" error is not removing.
Any idea please?
I am using following code
public double getPayroll(){
ResultSet rs = null;
ResultSet rs1 = null;
ResultSet rs2 = null;
Connection conn = null;
PreparedStatement pstmt = null;
try {
conn = getDBConnection();
double dailyPay=0,basicPay=0,payroll2=0;
int houseRent=0,convAllow=0,noOfPresents=0,empId=0;
String q = "select e_id from employee";
pstmt = conn.prepareStatement(q);
rs = pstmt.executeQuery();
while (rs.next()) {
empId=rs.getInt(1);
String q1 = "select count(att_status) from attendance where att_status='p'";
pstmt = conn.prepareStatement(q1);
rs1 = pstmt.executeQuery(q1);
while(rs1.next()){
noOfPresents=rs1.getInt(1);
String q2 = "select e_salary,e_house_rent,e_conv_allow from employee where e_id=?";
pstmt = conn.prepareStatement(q2);
pstmt.setInt(1,empId);
rs2 = pstmt.executeQuery(q2);
while(rs2.next()){
dailyPay=rs2.getInt(1)/22;
houseRent=rs2.getInt(2);
convAllow=rs2.getInt(3);
basicPay=dailyPay*noOfPresents;
payroll2+=basicPay+houseRent+convAllow;
}
}
}
return payroll2;
}catch (Exception e) {
e.printStackTrace();
return 0.0;
} finally {
try {
rs.close();
pstmt.close();
conn.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
Your problem is here:
rs2 = pstmt.executeQuery(q2);
You're telling the PreparedStatement to execute the SQL q2, rather than executing the SQL previously prepared. This should just be:
rs2 = pstmt.executeQuery();
This is a fairly common mistake, caused mainly by the bad class design of java.sql.Statement and its subtypes.
As #RMT points out, you make the same mistake here:
rs1 = pstmt.executeQuery(q1);
This doesn't matter so much, since there are no placeholders in q1, so the SQL executes as-is. It's still wrong, though.
Lastly, you should consider calling close() on the first PreparedStatement, before re-assigning the pstmt variable to another one. You risk a leak if you don't do that.
pstmt = conn.prepareStatement(q2);
pstmt.setInt(1,empId);
rs2 = pstmt.executeQuery(q2);
You have already created the prepared statement with the query q2 and bound the variable empId to it. if you now invoke pstmt.executeQuery(q2), the variable binding is lost. The JDBC driver probably parses the unbound sql q2 when you execute pstmt.executeQuery(q2).
One reason might be that you cannot re-use the instance of pstmt like that. You have to use a separate PreparedStatement instance in each level of the loop.
Are you aware that this can be done with just a single statement as well?
Edit:
Assuming there is a relation between employee and attendance, something like this would return the sum in a single request:
select sum( (e_salary / 22) * att_count + e_house_rent + e_conv_allow )
from (
select emp.e_salary
emp.e_house_rent,
emp.e_conv_allow,
(select count(att.att_status) from attendance att where att.e_id = mp.e_id) s att_count
from employee emp
) t
If indeed attendance is not linked to employee, just leave out the where clause in the nested select.
UPDATE TESTCP SET CP_KEY2 =?, CP_DESC =?, CP_MAKER =?, CP_MAKER_DT =SYSDATE, CP_STATUS ='M' WHERE CP_LANGUAGE = ? AND CP_ENG_CODE = ? AND CP_KEY1 =? AND CP_LANGUAGE =?
In the above query we have 7 in parameter but if in your java code PreparedStatement you have set only 6 parameter values .
That time also this error will occur.
how can i replace hardcoded number with variable in this java statement which is accessing the mysql datatabase using jdbc. the query is executed using executeQuery(query)
here is the java statement
String query = "select * from TableA where num = '1233' ";
i need to replace this 1233 with a variable in this statement.
any help appreciated
Regards,
If you can use prepared statement, you'll be safer (no risk of SQL injection):
Connection con = getMyConnection();
try {
PreparedStatement ps = con.prepareStatement("select * from TableA where num = ?");
try {
ps.setLong(1, number);
ResultSet rs = ps.executeQuery();
while(rs.next()) {
//TODO
}
} finally {
ps.close();
}
} finally {
con.close();
}
Are you using Hibernate? If yes this is how you should go supose str is the string/integer you want to replace then get the str by requestobject and continue by using the following code.
try {
SessionFactory sessionfactory = new Configuration().configure().buildSessionFactory();
session = sessionfactory.openSession();<br>
String query = "from Contact c where name='"+str+"'";
Query query1 = session.createQuery(query);<br>
list = query1.list();
System.out.println("Number of users in the system :- "+list.size());
for (Contact contact : list) {
System.out.println(contact.getId()+" : "+contact.getName()+" : "+ contact.getRole()+ " : "+ contact.isEnable());
}