so I am a beginer in JDBC - SQL Programming. I need a little advice which is most probably about SYNTAX.
So, Problem = I'm trying to search a record which has name(string provided in function argument) in the record. Following is my code. Now I've designed this code in such a way that there can be more than 1 records with the same name, so all of that records' data will be printed (by ShowData() Function).
protected static void SearchbyName (String toCompareName)
{
Statement stmt = null;
ResultSet rs = null;
Connection conn = null;
boolean flag = false; //to confirm if record has found atleast once
try
{
Class.forName("com.mysql.jdbc.Driver").newInstance();
conn = DriverManager.getConnection(url, username, password);
stmt = conn.createStatement();
rs = stmt.executeQuery("SELECT idEmployee FROM employee WHERE name = ' "+toCompareName+" ' ");
if( !(rs.next()) ) //if ResultSet is not empty
{
while(rs.next()) //reading all records with the same name, extracted by Query
{
int foundID = rs.getInt("idEmployee"); //extracting ID of found record
ShowRecord(foundID); //prints record of foundID fromDB
flag = true; //set flag
}
}
if(flag==false) //if no record found
{
JOptionPane.showMessageDialog(null, "ERROR:: No Records Found..", "Not Found", JOptionPane.ERROR_MESSAGE);
}
//close connection
if(rs!=null)
{ rs.close(); }
if(stmt!=null)
{ stmt.close(); }
if(conn!=null)
{ conn.close(); }
}
catch(SQLException e)
{ System.err.println(e); }
catch(Exception e)
{ System.err.println(e); }
}
So here it is. As far as my understanding goes, there is some problem with either RESULTSET rs or the Query I'm executing.
Kindly help. & if you can suggest a better approach for search, sure do please. I'm going to write 4 more functions SearchbyAge, SearchbyQualification, SearchbySpecialization on the same pattern.
Just this is enough
while(rs.next()) //reading all records with the same name, extracted by Query
{
int foundID = rs.getInt("idEmployee"); //extracting ID of found record
ShowRecord(foundID); //prints record of foundID fromDB
flag = true; //set flag
}
You don't have to check the data in resultset this way with a if case
if( !(rs.next()) )
This will move to the next record in the resultset
SOVLED
My error was in query. I was putting spaces in string's syntax which I was comparing.
WRONG = `"(.. WHERE name = " ' +toCompareName+ '" ");
RIGHT = `"(.. WHERE name = "'+toCompareName+'" ");
So thats it. Hope it helps to anyone else. :)
Related
I am working on a program which will when finished allow the end user to keep track of there sound packs in a database through SQLite. The newest problem I am running into is that I can not get the Select statement to take a JTextField input. The reason that I want to do this is that I already have the text fields linked through the insert method. I have tried switching the variable types in the readAllData method and I am not entirely sure what other way to fix it.
The fields are as follows
PackId
PackName
VendorName
PackValue
what I want to happen is when I hit the Update button I want the data in the database to print out to the console (for now) and I am also going to be adding a select specified records method as well.
Here is the code I do apologize in advance this is a very long project:
public void readAllData() throws SQLException {
Connection conn = DriverManager.getConnection("jdbc:sqlite:packsver3.db");
PreparedStatement ps = null;
ResultSet rs = null;
try {
String sql = "SELECT * FROM packs";
ps = conn.prepareStatement(sql);
rs = ps.executeQuery();
while(rs.next()) {
String PackId = PackId.getText();
String PackName = PackName.getText();
String VendorName = VendorName.getTextField();
String PackValue = rs.getTextField;
System.out.println("All Packs\n");
System.out.println("PackId: " +PackId);
System.out.println("PackName: " +PackName);
System.out.println("VendorName: " +VendorName);
System.out.println("PackValue: " +PackValue+"\n\n");
}
} catch (SQLException e) {
System.out.println(e.toString());
}finally {
try {
assert rs != null;
rs.close();
ps.close();
conn.close();
} catch (SQLException e) {
System.out.println(e.toString());
}
Console Output
I need to check the box no if exist in the database under the remittance id that I enter if the box no exists then i need to show the message that the box no already exists but if it doesn't the it should insert new box i have written some code but its showing error
private void txtboxnoFocusLost(java.awt.event.FocusEvent evt) {
DBUtil util = new DBUtil();
try {
Connection con = util.getConnection();
PreparedStatement stmt = con.prepareStatement(
"select box_no from dbo.soil_det where rm_id = ? and box_no = ?");
stmt.setLong(1, Long.parseLong(tf_rm_id.getText()));
stmt.setString(1, (txtboxno.getText()));
ResultSet rs=stmt.executeQuery();
while(rs.next()){
rs.equals().txtboxno.getText());
}
JOptionPane.showMessageDialog(rootPane, "hello!S");
} catch (Exception ex) {
Logger.getLogger(DATAENTRY.class.getName()).log(Level.SEVERE, null, ex);
}
Try this code
private void txtboxnoFocusLost(java.awt.event.FocusEvent evt) {
DBUtil util = new DBUtil();
try {
Connection con = util.getConnection();
PreparedStatement stmt = con.prepareStatement(
"select box_no from dbo.soil_det where rm_id = ? and box_no = ?");
stmt.setLong(1, Long.parseLong(tf_rm_id.getText()));
stmt.setString(2, (txtboxno.getText()));
ResultSet rs=stmt.executeQuery();
bool recordAdded = false;
while(!rs.next()){
/// Do your insertion of new records
recordAdded = true;
}
if( recordAdded ){
JOptionPane.showMessageDialog(rootPane, "Record added");
}else{
JOptionPane.showMessageDialog(rootPane, "Record already exists");
}
} catch (Exception ex) {
Logger.getLogger(DATAENTRY.class.getName()).log(Level.SEVERE, null, ex);
}
or you could use a count:
String query = "select count(*)
from dbo.soil_det where rm_id = ? and box_no = ?";
then after executing the query you get the count with
rs.getInt(1)
using that you can decide which info to show to the user
very First You have to get count using sql if count is greater than zero then do not insert records and show message like already exists and in else part insert record. see following example
private boolean findCount(int rm_id,String box_no)
{
int count=0;
//write query here
count = assign query result;
//check count
if(count>0)
{
return false;//records exists
}else{
return true;//records do not exists
}
}
public void insertData()
{
if(findCount(1,"1")){//pass values
//Write down your insert logic
}else{
JOptionPane.showMessageDialog(rootPane, "Records Already Exists");
}
}
Note: Friend in Your Example you have not written the insert logic. only select was there
First you could add -- on the db table -- a unique constrain on the columns (rm_id, box_no), this is anyway a good thing to do.
Then you could simply try to insert the box and catch the exception and check if it is a violation of the unique constraint.
Another option (still keeping the unique constraint) would be to make a more complicated SQL insert statement that inserts only if not existing, you may google "sql insert if not exist" to find some examples...
You need to get the appropriate record from the ResultSet e.g.
boolean found = rs.getString(1).equals().txtboxno.getText());
At the moment you're simply comparing the ResultSet object itself to a string, and that won't work. The above pulls the first record from the ResultSet and performs the comparison on that (note: your datatype may be different and you may need rs.getInt(1) etc.)
Perhaps its sufficient in your case just to check if you have a ResultSet result (via rs.next())
simplified version
private void txtboxnoFocusLost(java.awt.event.FocusEvent evt) {
DBUtil util = new DBUtil();
try {
Connection con = util.getConnection();
PreparedStatement stmt = con.prepareStatement(
"select box_no from dbo.soil_det where rm_id = ? and box_no = ?");
stmt.setLong(1, Long.parseLong(tf_rm_id.getText()));
stmt.setString(2, (txtboxno.getText()));
ResultSet rs=stmt.executeQuery();
if(!rs.next()){
JOptionPane.showMessageDialog(rootPane, "Record added");
}else{
JOptionPane.showMessageDialog(rootPane, "Record already exists");
}
} catch (Exception ex) {
Logger.getLogger(DATAENTRY.class.getName()).log(Level.SEVERE, null, ex);
}
rs.next() followed by if condition returns true if the record exists in a table. if not, return false.
I've connected to a MySQL database, which contains four fields (the first of which being an ID, the latter ones each containing varchar strings).
I am trying to get the last row of the database and retrieve the contents of the fields so that I can set them to variables (an int and three strings) and use them later.
So far, I have the bare minimum to make the connection, where do I go from here? As you can see I have tried to write a SQL statement to get the last row but it's all gone wrong from there and I don't know how to split it into the separate fields.
Class.forName("com.mysql.jdbc.Driver").newInstance();
Connection con = DriverManager.getConnection("jdbc:mysql://localhost/t", "", "");
Statement st = con.createStatement();
String sql = ("SELECT * FROM posts ORDER BY id DESC LIMIT 1;");
st.getResultSet().getRow();
con.close();
Here you go :
Class.forName("com.mysql.jdbc.Driver").newInstance();
Connection con = DriverManager.getConnection("jdbc:mysql://localhost/t", "", "");
Statement st = con.createStatement();
String sql = ("SELECT * FROM posts ORDER BY id DESC LIMIT 1;");
ResultSet rs = st.executeQuery(sql);
if(rs.next()) {
int id = rs.getInt("first_column_name");
String str1 = rs.getString("second_column_name");
}
con.close();
In rs.getInt or rs.getString you can pass column_id starting from 1, but i prefer to pass column_name as its more informative as you don't have to look at database table for which index is what column.
UPDATE : rs.next
boolean next()
throws SQLException
Moves the cursor froward one row from its current position. A
ResultSet cursor is initially positioned before the first row; the
first call to the method next makes the first row the current row; the
second call makes the second row the current row, and so on.
When a call to the next method returns false, the cursor is positioned
after the last row. Any invocation of a ResultSet method which
requires a current row will result in a SQLException being thrown. If
the result set type is TYPE_FORWARD_ONLY, it is vendor specified
whether their JDBC driver implementation will return false or throw an
SQLException on a subsequent call to next.
If an input stream is open for the current row, a call to the method
next will implicitly close it. A ResultSet object's warning chain is
cleared when a new row is read.
Returns:
true if the new current row is valid; false if there are no more rows Throws:
SQLException - if a database access error occurs or this method is called on a closed result set
reference
Something like this would do:
public static void main(String[] args) {
Connection con = null;
Statement st = null;
ResultSet rs = null;
String url = "jdbc:mysql://localhost/t";
String user = "";
String password = "";
try {
Class.forName("com.mysql.jdbc.Driver");
con = DriverManager.getConnection(url, user, password);
st = con.createStatement();
rs = st.executeQuery("SELECT * FROM posts ORDER BY id DESC LIMIT 1;");
if (rs.next()) {//get first result
System.out.println(rs.getString(1));//coloumn 1
}
} catch (SQLException ex) {
Logger lgr = Logger.getLogger(Version.class.getName());
lgr.log(Level.SEVERE, ex.getMessage(), ex);
} finally {
try {
if (rs != null) {
rs.close();
}
if (st != null) {
st.close();
}
if (con != null) {
con.close();
}
} catch (SQLException ex) {
Logger lgr = Logger.getLogger(Version.class.getName());
lgr.log(Level.WARNING, ex.getMessage(), ex);
}
}
}
you can iterate over the results with a while like this:
while(rs.next())
{
System.out.println(rs.getString("Colomn_Name"));//or getString(1) for coloumn 1 etc
}
There are many other great tutorial out there like these to list a few:
http://www.vogella.com/articles/MySQLJava/article.html
http://www.java-samples.com/showtutorial.php?tutorialid=9
As for your use of Class.forName("com.mysql.jdbc.Driver").newInstance(); see JDBC connection- Class.forName vs Class.forName().newInstance? which shows how you can just use Class.forName("com.mysql.jdbc.Driver") as its not necessary to initiate it yourself
References:
http://zetcode.com/databases/mysqljavatutorial/
This should work, I think...
ResultSet results = st.executeQuery(sql);
if(results.next()) { //there is a row
int id = results.getInt(1); //ID if its 1st column
String str1 = results.getString(2);
...
}
Easy Java method to get data from MySQL table:
/*
* CREDIT : WWW.CODENIRVANA.IN
*/
String Data(String query){
String get=null;
try{
Class.forName("com.mysql.jdbc.Driver").newInstance();
Connection con = (Connection)DriverManager.getConnection
("jdbc:mysql://localhost:3306/mysql","root","password");
Statement stmt = (Statement) con.createStatement();
ResultSet rs=stmt.executeQuery(query);
if (rs.next())
{
get = rs.getString("");
}
}
catch(Exception e){
JOptionPane.showMessageDialog (this, e.getMessage());
}
return get;
}
Here is what I just did right now:
import java.sql.*;
import java.util.logging.Level;
import java.util.logging.Logger;
import com.sun.javafx.runtime.VersionInfo;
public class ConnectToMySql {
public static ConnectBean dataBean = new ConnectBean();
public static void main(String args[]) {
getData();
}
public static void getData () {
try {
Class.forName("com.mysql.jdbc.Driver");
Connection con = DriverManager.getConnection("jdbc:mysql://localhost:3306/mynewpage",
"root", "root");
// here mynewpage is database name, root is username and password
Statement stmt = con.createStatement();
System.out.println("stmt " + stmt);
ResultSet rs = stmt.executeQuery("select * from carsData");
System.out.println("rs " + rs);
int count = 1;
while (rs.next()) {
String vehicleType = rs.getString("VHCL_TYPE");
System.out.println(count +": " + vehicleType);
count++;
}
con.close();
} catch (Exception e) {
Logger lgr = Logger.getLogger(VersionInfo.class.getName());
lgr.log(Level.SEVERE, e.getMessage(), e);
System.out.println(e.getMessage());
}
}
}
The Above code will get you the first column of the table you have.
This is the table which you might need to create in your MySQL database
CREATE TABLE
carsData
(
VHCL_TYPE CHARACTER(10) NOT NULL,
);
First, Download MySQL connector jar file, This is the latest jar file as of today [mysql-connector-java-8.0.21].
Add the Jar file to your workspace [build path].
Then Create a new Connection object from the DriverManager class, so you could use this Connection object to execute queries.
Define the database name, userName, and Password for your connection.
Use the resultSet to get the data based one the column name from your database table.
Sample code is here:
public class JdbcMySQLExample{
public static void main(String[] args) {
String url = "jdbc:mysql://localhost:3306/YOUR_DB_NAME?useSSL=false";
String user = "root";
String password = "root";
String query = "SELECT * from YOUR_TABLE_NAME";
try (Connection con = DriverManager.getConnection(url, user, password);
Statement st = con.createStatement();
ResultSet rs = st.executeQuery(query)) {
if (rs.next()) {
System.out.println(rs.getString(1));
}
} catch (SQLException ex) {
System.out.println(ex);
}
}
I have table VIDEO (VideoID int Primary Key, Address Varchar(100)) and I want to search table to see if there is video with given address. But I am not sure if this code works good, and if this could be better done.
Here is my code:
public boolean checkIfVideoExist(String address) throws SQLException {
int count = 0;
Statement stmt = connection.createStatement();
ResultSet rset = stmt
.executeQuery("SELECT Count(VideoID) from VIDEO WHERE Address='"
+ address + "'");
if (rset.next())
count = rset.getInt(1);
if (count == 0)
return false;
else
return true;
}
Be sure you have an index set on column ADDRESS. Then your query should run fast.
It is better to use a prepared statement to pass the address value to the query. And you should close the result set and the statement.
And
if (count == 0)
return false;
else
return true;
looks a bit strange.
public boolean checkIfVideoExist(String address) throws SQLException {
int count = 0;
PreparedStatement stmt = null;
ResultSet rset = null;
try {
stmt = connection.prepareStatement(
"SELECT Count(VideoID) from VIDEO WHERE Address=?");
stmt.setString(1, address);
rset = stmt.executeQuery();
if (rset.next())
count = rset.getInt(1);
return count > 0;
} finally {
if(rset != null) {
try {
rset.close();
} catch(SQLException e) {
e.printStackTrace();
}
}
if(stmt != null) {
try {
stmt.close();
} catch(SQLException e) {
e.printStackTrace();
}
}
}
}
The code is fine, except for the way you're embedding strings in your query. If address contains a quote character, the query will become invalid. And this is only a small part of the problem. Doing it like this opens the door to SQL injection attacks, where malicious users could enter an address which completely changes the meaning of the query.
Always use prepared statements to bind parameters:
PreparedStatement stmt = connection.prepareStatement("SELECT Count(VideoID) from VIDEO WHERE Address=?");
stmt.setString(1, address); // proper escaping is done for you by the JDBC driver
ResultSet rset = stmt.executeQuery();
Also, you should use finally blocks to close your result sets and statements.
Your code is vulnerable to SQL Injection, it should use a prepared statement instead of building the SQL query via string concatenation.
Apart from that, it looks OK.
ResultSet rset = stmt.executeQuery("SELECT * from VIDEO WHERE Address='" + address + "'");
return rset.next();
then there is at least one matching record and you are done. No need for aggregate function count() ....
I'm trying to write a function that updates 2 tables in my database. I'm getting an error which i think is caused by calling next() on a resultset that has no more rows in the set.
I was thinking an if condition on hasNext() would fix this but it's not available to the result set...
The error i'm getting is 'No operations allowed after statement closed.'
private void updateDatabase() throws Exception {
Connection conn = getConnection();
PreparedStatement updateMovieStmt = conn.prepareStatement("INSERT INTO movies VALUES(null,?,null,null,null)", Statement.RETURN_GENERATED_KEYS);
PreparedStatement updateVideoStmt = conn.prepareStatement("INSERT INTO video_files VALUES(null,null,null,?,?)", Statement.RETURN_GENERATED_KEYS);
try {
for (Movie localMovie : getLocalMovies()) {
// fetch a local movie{
boolean newMovie = true;
for (Movie dbMovie : getDatabaseMovies(conn)) {
newMovie = true;
Pattern p = Pattern.compile(localMovie.getTitlePattern(), Pattern.CASE_INSENSITIVE);
Matcher m = p.matcher(dbMovie.getTitle());
// if it's already in the database not new movie... but is
// is it a new video rip????????????;
if (m.find()) {
System.out.println("DB movie: " + dbMovie.getTitle() + " matches localpattern of: " + localMovie.getTitlePattern());
newMovie = false;
break;
}
}
if (newMovie == true && localMovie.getTitle() != null) {
updateMovieStmt.setString(1, localMovie.getTitle());
updateMovieStmt.executeUpdate();
// get new movie id and put into new video row
ResultSet rs = updateMovieStmt.getGeneratedKeys();
if (rs.next()) {
updateVideoStmt.setBytes(1, localMovie.getHash());
updateVideoStmt.setInt(2, rs.getInt(1));
updateVideoStmt.executeUpdate();
}
}
}
} catch (SQLException e) {
e.printStackTrace();
} finally {
updateMovieStmt.close();
updateVideoStmt.close();
conn.close();
}
}
If you're not using batches (addBatch()/executeBatch()), nor clearing the parameters (clearParameters()), then you should be creating the statements inside the loop, not outside the loop.
Move the both conn.prepareStatement() lines into the if (newMovie == true && localMovie.getTitle() != null) block, preferably refactored in separate methods. Your current method is doing way too much.
you can have only one open Statement per connection. Once you create a new Statement on the same connection, the previously created one will be closed
This holds true for resultSet that we can have only one resultSet open per statement. With a connection we can have multiple statements open.