I have this code:
try {
Integer user = InformationService.authenticate(username, password, connection);
Statement st = connection.createStatement();
ResultSet rs = st.executeQuery("SELECT * FROM tasks WHERE uid = " + user + " ORDER BY title ASC");
System.out.println("SELECT * FROM tasks WHERE uid = " + user + " ORDER BY title ASC");
while (rs.next()) {
Task p = new Task(rs.getString("title"), rs.getInt("id"), rs.getString("descriere"),
rs.getString("data"), rs.getInt("uid"), rs.getString("data_creare"), rs.getString("ora"),
rs.getInt("status"), rs.getString("priority"), rs.getInt("sters"), rs.getInt("id_parinte"),
rs.getInt("notify"), rs.getString("assigner"), rs.getInt("durata"), rs.getInt("project_id"));
System.out.println(p);
tasks.add(p);
}
The problem is that it returns only the first row, and if I run the query manually I get more results (16 total). Here's the output:
SELECT * FROM tasks WHERE uid = 4 ORDER BY title ASC
models.Task#164b9b8f
Any idea why this is happening?
May be you can improve the code a bit like below which will help you to quickly identify the issue.
int rowCount = 0;
try {
Integer user = InformationService.authenticate(username, password, connection);
Statement st = connection.createStatement();
String query = "SELECT * FROM tasks WHERE uid = " + user + " ORDER BY title ASC";
System.out.println(query);
ResultSet rs = st.executeQuery(query);
while (rs.next()) {
Task p = new Task(rs.getString("title"), rs.getInt("id"), rs.getString("descriere"),
rs.getString("data"), rs.getInt("uid"), rs.getString("data_creare"), rs.getString("ora"),
rs.getInt("status"), rs.getString("priority"), rs.getInt("sters"), rs.getInt("id_parinte"),
rs.getInt("notify"), rs.getString("assigner"), rs.getInt("durata"), rs.getInt("project_id"));
rowCount++;
System.out.println(rowCount + "." + p);
tasks.add(p);
}
} finally {
System.out.println("Number of records = " + rowCount);
}
In this approach you can clearly identify how many rows were iterated.
Related
I updated my database from SQLite db to MySQL and I suddenly I get this error:
java.sql.SQLException: No operations allowed after statement closed.
public boolean isEnough(int quantity, String item) throws SQLException {
boolean enough = false;
PreparedStatement pst = null;
ResultSet rs = null;
String sql = "SELECT * FROM Stock WHERE Item_name='" + item + "'";
pst = conn.prepareStatement(sql);
rs = pst.executeQuery();
if (rs.next()) {
int temp = rs.getInt(3);
if (quantity > temp) {
stmt.close();
enough = false;
} else if (quantity <= temp) {
enough = true;
int updatedStock = temp - quantity;
String sql_1 = "UPDATE Stock SET Item_quantity ='" + updatedStock + "' WHERE Item_name ='" + item + "'";
stmt.executeUpdate(sql_1); //error here
String sql_2 = "SELECT * FROM Stock WHERE Item_name='" + item + "'";
pst = conn.prepareStatement(sql);
rs = pst.executeQuery();
System.out.println(rs);
if (rs.next()) {
int isZero = rs.getInt(3);
if (isZero == 0) {
String sql_3 = "DELETE FROM Stock WHERE Item_name = '" + item + "'";
stmt.executeUpdate(sql_3);
JOptionPane.showMessageDialog(this, "Order Added\nItem is now out of Stock and removed from Stock database automatically.");
}
}
}
}
stmt.close();
return enough;
}
I'm closing connection and statement after every update, but I have no idea how to fix this error. If I go back to SQLite db this error disappears. I'm new to MySQL, so pardon me if I'm doing something wrong.
I have loaded millions of rows of data from 5 tables in database. I want to display the loaded data into a tableview. It takes a long time to load all the records(sometimes all of them don't fit into memory). I want to make it so that I can load a resultSet, display it, load a second one, and so on. Is this possible? My code as of now:
#FXML
private TableView<Vysledok_hladania> table;
#FXML
private TableColumn<Vysledok_hladania, String> Nazov_hotela, Adresa, Krajina, Mesto, Hviezdicky, Cena, Typ_izby, Pocet_izieb;
#FXML
void vyhladajInfo(ActionEvent event){
table.getItems().clear();
try {
Connection con = Runner.getConnection();
con.setAutoCommit(false);
String query = "SELECT h.\"Nazov hotela\", k.\"Nazov krajiny\", m.\"Nazov mesta\", h.\"Adresa hotela\", h.\"Hviezdicky\", p.\"Cena pobytu\", i.\"Typ izby\", h.\"Pocet izieb\" FROM hotel h " +
"inner JOIN izba i ON i.\"ID hotela\" = h.\"ID hotela\" " +
"inner JOIN krajina k ON k.\"ID krajiny\" = h.\"ID krajiny\" " +
"inner JOIN mesto m ON m.\"ID mesta\" = h.\"ID mesta\" " +
"inner JOIN pobyt p ON p.\"ID hotela\" = h.\"ID hotela\" " +
"WHERE h.\"Nazov hotela\" = ? " +
"AND k.\"Nazov krajiny\" = ? " +
"AND h.\"Hviezdicky\" = ? " +
"AND i.\"Pocet posteli\" >= ? " +
"AND p.\"Cena pobytu\" <= ? ";
//"AND p.\"Datum od\" = ? " +
//"AND p.\"Datum do\" <= ?";
int i = 1;
PreparedStatement pst = con.prepareStatement(query, ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY);
pst.setFetchSize(50);
pst.setString(1,Text_nazov.getText());
pst.setString(2,(String)krajina.getValue());
int pocet_hviezdiciek = Integer.parseInt((String)hviezdicky.getValue());
pst.setInt(3,pocet_hviezdiciek);
int pocet_osob = Integer.parseInt((String)osoby.getValue());
pst.setInt(4, pocet_osob);
double cena_pobytu = Double.parseDouble(Text_cena.getText());
pst.setDouble(5, cena_pobytu);
// Date datum_OD = Date.valueOf(date_od.getValue());
// pst.setDate(6, datum_OD);
// Date datum_DO = Date.valueOf(date_do.getValue());
// pst.setDate(7, datum_DO);
ResultSet rs = pst.executeQuery();
System.out.println(pst);
Nazov_hotela.setCellValueFactory(new PropertyValueFactory<>("Meno_hotela"));
Krajina.setCellValueFactory(new PropertyValueFactory<>("Krajina"));
Mesto.setCellValueFactory(new PropertyValueFactory<>("Mesto"));
Adresa.setCellValueFactory(new PropertyValueFactory<>("Adresa"));
Hviezdicky.setCellValueFactory(new PropertyValueFactory<>("Hviezdicky"));
Cena.setCellValueFactory(new PropertyValueFactory<>("Cena"));
Typ_izby.setCellValueFactory(new PropertyValueFactory<>("Typ_izby"));
Pocet_izieb.setCellValueFactory(new PropertyValueFactory<>("Pocet_izieb"));
while(rs.next()){
oblist.add(new Vysledok_hladania(rs.getString("Nazov hotela"),
rs.getString("Nazov krajiny"),
rs.getString("Nazov mesta"),
rs.getString("Adresa hotela"),
rs.getInt("Hviezdicky"),
rs.getDouble("Cena pobytu"),
rs.getString("Typ izby"),
rs.getInt("Pocet izieb")));
System.out.println(i++);
}
rs.close();
pst.close();
con.close();
} catch(SQLException ex){
Logger.getLogger(Result_Controller.class.getName()).log(Level.SEVERE, null, ex);
}
table.setItems(oblist);
}
I am currently writing a simple Java app that reads information from an XLS file and then enters it in the database. Since that XLS does have duplicated records, I do a simple check if the entry in the XLS file already exists in the database. Here is my code:
public static void addResult(ArrayList<ArrayList<String>> listResults)
{
try
{
openDatabase();
stmt = c.createStatement();
for (int i = 0; i < listResults.size(); i++)
{
PreparedStatement stm = c.prepareStatement("SELECT player_name FROM results WHERE player_name=?;");
stm.setString(1, listResults.get(i).get(ReadResultsFile.NAME));
System.out.println(stm);
ResultSet rs = stm.executeQuery();
if (rs.getRow() <= 0)
{
String typeOfPlay = new String();
if (listResults.get(i).get(ReadResultsFile.TYPE).equals("Simple"))
{
typeOfPlay = "single";
}
else if (listResults.get(i).get(ReadResultsFile.TYPE).equals("Double"))
{
typeOfPlay = "double";
}
stm = c.prepareStatement("INSERT INTO results (player_name, school_id, " + typeOfPlay + ", tournament_id) "
+ "VALUES(?,?,?,?);");
stm.setString(1, listResults.get(i).get(ReadResultsFile.NAME));
stm.setString(2, listResults.get(i).get(ReadResultsFile.SCHOOL_ID));
stm.setInt(3, Integer.parseInt(listResults.get(i).get(ReadResultsFile.SCORE)));
stm.setString(4, "1");
stm.executeUpdate();
}
else
{
String typeOfPlay = new String();
if (listResults.get(i).get(ReadResultsFile.TYPE).equals("Simple"))
{
typeOfPlay = "single";
}
else if (listResults.get(i).get(ReadResultsFile.TYPE).equals("Double"))
{
typeOfPlay = "double";
}
stm = c.prepareStatement("UPDATE results SET " + typeOfPlay + "=? WHERE player_name=?;");
stm.setString(1, typeOfPlay);
stm.setString(2, listResults.get(i).get(ReadResultsFile.SCORE));
stm.setString(1, listResults.get(i).get(ReadResultsFile.NAME));
System.out.println(stm);
stm.executeUpdate();
}
}
closeDatabase();
}
catch (Exception e)
{
System.err.println(e.getClass().getName() + ": " + e.getMessage());
System.exit(0);
}
}
The problem that arises is that the rs.getRow() function always returns -1. I tried running the SELECT query directly in the database tool and the query returns the player_name column if there is already a similar entry existing. It unfortunately do the same in Java.
I am unsure what to do at this point.
Thank you for any hint!
getRow will not work as per the javadocs
Retrieves the current row number. The first row is number 1, the second number 2, and so on.
and
A ResultSet cursor is initially positioned before the first row; the
first call to the method next makes the first row the current row
Usually use
while (rs.next ()) {....
try {
DataBase DB = new DataBase();
Connection con = DB.Connect();
String sql;
sql = "select Id,Name,FatherName, City, Address, Department,RStatus, DatePlacement\n"
+ "from ECL where "
+ "id like ? and "
+ "name like ? and FatherName like ? and "
+ "City like ? and Address like ?";
PreparedStatement pst = con.prepareStatement(sql);
pst.setString(1, "%" + SearchId.getText() + "%");
pst.setString(2, "%" + SearchName.getText() + "%");
pst.setString(3, "%" + SearchFatherName.getText() + "%");
pst.setString(4, "%" + SearchCity.getText() + "%");
pst.setString(5, "%" + SearchAddress.getText() + "%");
ResultSet rs = pst.executeQuery();
ResultSetMetaData rsmd = rs.getMetaData();
int MetaColum = rsmd.getColumnCount(); //adding colums in Jtable
Vector col = new Vector();
for (int i = 1; i <= MetaColum; i++) {
col.addElement(rsmd.getColumnName(i));
}
ReTable.setColumnIdentifiers(col);
while (rs.next()) {
Vector rows = new Vector(); // to add rows in Jtable
for (int j = 1; j <= MetaColum; j++) {
rows.addElement(rs.getString(j));
}
ReTable.addRow(rows);
ResultTable.setModel(ReTable);
}
} catch (Exception ex) {
System.out.println(ex);
}
ReTable.fireTableDataChanged(); // Method to refresh the Jtable
}
how to refresh jtable with new data. it loads new data but it also contain the old data every time i search for new name it give me the correct result but the previous search data also remains in jtable. my question is how to refresh jtable every time i make a new search. Thanks In Advance.
You are not removing the previous rows inserted in your model ReTable. In each call you are adding more and more rows in this line:
ReTable.addRow(rows);
Remove all rows from the model before launching the query or create a new model fresh with no rows for each query.
I'm trying to code a system for a large IRC channel (Twitch Channel)
One of the things I'm trying to do is log every user and give them points for being in the chat. For all intents and purposes the chat is just a large IRC channel. I'm retrieving the users in a big list from the twitch API, I put all the usernames in a large Array and running the following timer with a while loop:
timer = new Timer(900000, new ActionListener() {
public void actionPerformed(ActionEvent evt) {
updating = true;
try {
Arraynumber = 0;
TwitchBot.getDate();
arrayused = false;
System.out.println("trying to save users if theres enough stuff");
while(Arraynumber < TwitchBot.words.length){
TwitchBot.CheckUpdateUserSQL(TwitchBot.words[Arraynumber]);
Arraynumber++;
System.out.println("updating database");
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
As you can see it's a simple timer that picks the name from a String[] and runs every name through the script individually.
The updateuser looks like such:
public static void CheckUpdateUserSQL(String sqluser) throws ClassNotFoundException{
selectSQL(sqluser);
if (id == "thisuserdoesntexistforsure"){
InsertSQL(sqluser);
}
else{
int progress = CurrentTime - lastlogin;
int totalprogress = progress + totaltime;
if(progress < 60 && progress > 0){
c15 = null;
Statement stmt = null;
if(isonline == 1) {
coins = progress / 4;
}
else{
coins = progress / 5;
}
int coinsincrease = (int) Math.ceil(coins);
int coinstotal = coinsamount + coinsincrease;
Class.forName("org.sqlite.JDBC");
try {
c15 = DriverManager.getConnection("jdbc:sqlite:users.db");
c15.setAutoCommit(false);
stmt = c15.createStatement();
String sql = "UPDATE USERS set TOTALTIME = " + totalprogress + " where NAME='" + sqluser + "';";
stmt.executeUpdate(sql);
c15.commit();
String sql2 = "UPDATE USERS set LASTLOGIN = " + CurrentTime + " where NAME='" + sqluser + "';";
stmt.executeUpdate(sql2);
c15.commit();
String sql3 = "UPDATE USERS set TOTALCOIN = " + coinstotal + " where NAME='" + sqluser + "';";
stmt.executeUpdate(sql3);
c15.commit();
String sql4 = "UPDATE USERS set ISONLINE = 0 where NAME='" + sqluser + "';";
stmt.executeUpdate(sql4);
c15.commit();
stmt.close();
c15.close();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
else {
Connection c = null;
Statement stmt = null;
try {
c = DriverManager.getConnection("jdbc:sqlite:users.db");
c.setAutoCommit(false);
stmt = c.createStatement();
String sql2 = "UPDATE USERS set LASTLOGIN = " + CurrentTime + " where NAME='" + sqluser + "';";
stmt.executeUpdate(sql2);
c.commit();
stmt.close();
c15.close();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
This code checks whether an user exists. (using the select method, which is as concise as I can get it, it only search for an username and returns the id, which will be 'thisuderdoesntexistforsure' if nothing returns)
If the user exists it will run the code to calculate their online time and the increase in online time and points since the last time they visited. Then updates the code. If they were not online or if the time somehow returns a negative value (or one that's too high) it will instead only update the timestamp and skip the rest of the updates. This makes sure that users who leave for a day don't just get 1.400 minutes of online time when they log on five minutes the next day.
Anyway. My question is; How can I trim it down? I'm running into an issue where it will take 6 minutes to update the entire userlist. having 2000 users online is not rare and it would take 2,000 loops through that while loop to update them all. The program is updating more often then not. I've tried cutting down the code to be as condensed as possible, but I have no idea where to start to speed things up.
Sorry if I'm coming over as moronic, I'm relatively new to SQL and this is my biggest project yet in JAVA.
You can use batching to perform your updates, but in your given code a simpler optimization would be to update the values with one update call (instead of 4). Also, you could use PreparedStatement and try-with-resources close. Something like,
public static void CheckUpdateUserSQL(String sqluser) throws ClassNotFoundException {
selectSQL(sqluser);
if (id.equals("thisuserdoesntexistforsure")) {
InsertSQL(sqluser);
} else {
String sql = "UPDATE USERS set TOTALTIME = ?, LASTLOGIN = ?, "
+ "TOTALCOIN = ?, ISONLINE = 0 where NAME = ?";
String sql2 = "UPDATE USERS set LASTLOGIN = ? where NAME=?";
int progress = CurrentTime - lastlogin;
int totalprogress = progress + totaltime;
if (progress < 60 && progress > 0) {
if (isonline == 1) {
coins = progress / 4;
} else {
coins = progress / 5;
}
int coinsincrease = (int) Math.ceil(coins);
int coinstotal = coinsamount + coinsincrease;
Class.forName("org.sqlite.JDBC");
try (Connection conn = DriverManager.getConnection("jdbc:sqlite:users.db");
PreparedStatement ps = conn.prepareStatement(sql)) {
ps.setInt(1, totalprogress);
ps.setInt(2, CurrentTime);
ps.setInt(3, coinstotal);
ps.setString(4, sqluser);
ps.executeUpdate();
} catch (SQLException e) {
e.printStackTrace();
}
} else {
Class.forName("org.sqlite.JDBC");
try (Connection conn = DriverManager.getConnection("jdbc:sqlite:users.db");
PreparedStatement ps = conn.prepareStatement(sql2)) {
ps.setInt(1, CurrentTime);
ps.setString(2, sqluser);
ps.executeUpdate();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
What you need is batchupdate. Some good tutorial can be found on the internet.
An example can be the following:
stm = db.prepareStatement("INSERT INTO ITEM (ID, TYPE, TITEL, UITGELEEND) VALUES (?, ?, ?, ?)");
db.setAutoCommit(false);
for (int n = 0; n < ItemLijst.getItems().size(); n++) {
Item huidigItem = ItemLijst.getItemObvIdx(n);
stm.setString(1, huidigItem.getID().toString());
stm.setString(2, huidigItem.getType().toString());
stm.setString(3, huidigItem.getTitel());
stm.setString(4,String.valueOf(huidigItem.isUitgeleend()));
stm.addBatch();
}
String SQL = "UPDATE Employees SET age = 35 " +
"WHERE id = 100";
// Add above SQL statement in the batch.
stm.addBatch(SQL);
stm.executeBatch();
db.commit();
Also try avoiding joining strings, instead use '?', otherwise it will be subjected to sql injection attacks.
http://tutorials.jenkov.com/jdbc/batchupdate.html
http://www.tutorialspoint.com/jdbc/jdbc-batch-processing.htm