In an database application, while testing an update button statements for some application jtable which represents a database table contents, i gained a resulting behavior with either creating a new row/record or throwing an duplicate primary key exception such being the same row/record key, with a clear update statement and syntax, actually i asked here before and i was guided to provide a "Minimal, Complete, and Verifiable example" , so i grabbed those updating lines in a new java runnable class - which worked very well and i didn't notice the difference - and it was such this counterpart parameters code example :
import java.sql.*;
import java.util.logging.Level;
import java.util.logging.Logger;
public class QueryTesting
{
public static void main(String[] args)
{
try
{
// create a java mysql database connection
Class.forName("com.mysql.jdbc.Driver");
try (Connection conn = DriverManager.getConnection("jdbc:mysql://localhost/?verifyServerCertificate=false&useSSL=true", "username", "password")) {
Statement s = null ;
try {
s = conn.createStatement();
} catch (SQLException ex) {
Logger.getLogger(QueryTestingForWMC.class.getName()).log(Level.SEVERE, null, ex);
}
int Result ;
try {
Result = s.executeUpdate("USE myDatabase");
} catch (SQLException ex) {
Logger.getLogger(QueryTestingForWMC.class.getName()).log(Level.SEVERE, null, ex);
}
PreparedStatement preparedStmt= null;
// create the java mysql update preparedstatement
String query = "update relativesTable set idRelativeMembers = ? , Name = ? , Picture = ? , RelationDegree = ? , persons_idPersons = ? where idRelativeMembers = ?";
// create the mysql update preparedstatement
preparedStmt = conn.prepareStatement(query);
preparedStmt.setString(1,"00002/10");
preparedStmt.setString(2,"عبد الحفيظ أحمد عبد الفتاح الدؤري");
preparedStmt.setBinaryStream(3, null);
preparedStmt.setString(4, "إبن عم");
preparedStmt.setString(5, "00002");
preparedStmt.setString(6, "00002/10");
// execute the java preparedstatement
preparedStmt.executeUpdate();
preparedStmt.close();
s.close();
}
catch (Exception e)
{
System.err.println("Got an exception! ");
System.err.println(e.getMessage());
}
}catch (ClassNotFoundException e)
{
System.err.println("Got an exception! ");
System.err.println(e.getMessage());
}
}
}
the update code block - in the original application - mentioned with a System.out.println() hint statement to assure that is the updating statement conditional block :
// the mysql update statement
String selectedMemberPrimaryKey = getMembersWithoutPhotos().get(jTable5.convertRowIndexToView(jTable5.getSelectedRow())).getId() ;
System.out.println("This is an update query");
String updateStatement = "update relativesTable set idRelativeMembers = ? , Name = ? , Picture = ? , RelationDegree = ? , persons_idPersons = ? where idRelativeMembers = ?";
// create the mysql update preparedstatement
preparedStmt = conn.prepareStatement(updateStatement);
preparedStmt.setString(1, jTextField2.getText());
while insert condition is hinted also with an insertion hint :
// the mysql insert statement
System.out.println("This is an insert query");
String insertStatement = "insert into relativesTable (idRelativeMembers, Name, Picture, RelationDegree, persons_idPersons) values ( ?, ?, ?, ?, ?)";
// create the mysql insert preparedstatement
preparedStmt = conn.prepareStatement(insertStatement);
preparedStmt.setString(1, jTextField2.getText());
The database table is related with another table through persons_idPersons foreign key, till now, i cannot figure out how the behavior would came from, however, is there is a condition(s) that may leads to the insertion behavior for the jdbc sql update statement ?
NEW NOTION :
I have tried to prepare the update query by other prepare statement way such :
System.out.println("This is an update query");
String updateStatement = "update relativesTable set idRelativeMembers = '00002/20' , Name =' أحمد عبد البارئ الثبنيتي ', Picture = null , RelationDegree =' عم ', persons_idPersons = '00002' where idRelativeMembers = '00002/10'";
// create the mysql update preparedstatement
preparedStmt = conn.prepareStatement(updateStatement);
and it has worked very well !
The whole UPDATE statement block in the jbutton for saving data to the database is - while i have commented the whole INSERT statement block in the jbutton, and still UPDATE works in such INSERT behavior! - :
try
{
// the mysql update statement
String selectedRelateivesMemberPrimaryKey = getMembersWithoutPhotos().get(jTable5.convertRowIndexToView(jTable5.getSelectedRow())).getId() ;
System.out.println("This is an update query");
String updateStatement = "update relativesTable set idRelativeMembers = ? , Name = ? , Picture = ? , RelationDegree = ? , persons_idPersons = ? where idRelativeMembers = ?";
// create the mysql update preparedstatement
preparedStmt = conn.prepareStatement(updateStatement);
preparedStmt.setString(1, jTextField2.getText());
selectedRelativeMemberForUpdateId = jTextField2.getText();
preparedStmt.setString(2, jTextField4.getText());
if(null == jLabel17.getIcon())
{
preparedStmt.setBinaryStream(3, null);
}else
{
Icon icon = jLabel17.getIcon();
ImageIcon img = (ImageIcon) icon ;
BufferedImage bI = new BufferedImage(img.getIconWidth(), img.getIconHeight(), BufferedImage.TYPE_INT_RGB);
Graphics g = bI.createGraphics();
icon.paintIcon(null, g, 0,0);
g.dispose();
ImageIO.write(bI, "jpg", new File("personRelativeMemTempImage.jpg"));
personRelativeMemImageFileForDatabase = new File("personRelativeMemTempImage.jpg");
personRelativeMemImageFileInputStream = new FileInputStream(personRelativeMemImageFileForDatabase);
preparedStmt.setBinaryStream(3,(InputStream) personRelativeMemImageFileInputStream,(int) personRelativeMemImageFileForDatabase.length());
}
preparedStmt.setString(4, jTextField15.getText());
preparedStmt.setString(5, selectedPersonForRelativeMembersId);
preparedStmt.setString(6, selectedRelateivesMemberPrimaryKey);
// execute the preparedstatement
preparedStmt.execute();
try {
preparedStmt.close();
} catch (SQLException ex) {
Logger.getLogger(GUI.class.getName()).log(Level.SEVERE, null, ex);
}
}
catch (FileNotFoundException | SQLException e)
{
System.err.println("Got an exception!");
System.err.println(e.getMessage());
String exceptionMessage = e.getMessage();
if(exceptionMessage.contains(exceptionStringPartOne) && exceptionMessage.contains(exceptionStringPartTwo))
{
JOptionPane.showMessageDialog(null, "Duplicate Keys","error",JOptionPane.ERROR_MESSAGE);
duplicatePrimaryKeyFlag = true ;
}else
{
JOptionPane.showMessageDialog(null, "A Related Database Error","error",JOptionPane.ERROR_MESSAGE);
return;
}
} catch (IOException ex) {
Logger.getLogger(GUI.class.getName()).log(Level.SEVERE, null, ex);
}
No, you need an INSERT statement to insert a new row, an UPDATE will only act on an existing record.
There is a possibility that there is an before/after UPDATE trigger defined on the table that does the INSERT but it would still be an INSERT that creates the new record, however it is called.
You could check for a trigger with
select * from `information_schema`.`triggers`
where event_object_schema = 'myDatabase'
and event_object_table = 'relativesTable'\G
However, a more likely explanation is an error in your application logic that runs the insert path rather than the update path, or both.
Preamble :
The application form was providing a selection to a person from person's jtable and then other selection to his/her relatives members from relatives jtable, and the other selection which is to a relative member brings members's row data to jtextfields to be modified and saved by a save button, and what was happening is throwing duplicate primary key exception in case of updating a member data with the same key, and in case of entering new id for key, a new member appears in the member's jtable.
Behind the Behavior :
Regardless of the state of affairs of writting this application, the problem was in superfluous using of methods at this line :
String selectedMemberPrimaryKey = getMembersWithoutPhotos().get(jTable5.convertRowIndexToView(jTable5.getSelectedRow())).getId() ;
it was enough to retrieve the key of the relatives members jtable to update the corresponding keyed record in the relatives members database table through the id column with just :
String selectedMemberPrimaryKey = jTable5.getValueAt(jTable5.convertRowIndexToView(jTable5.getSelectedRow()), 0).toString();
, and this mismatch led to retrieve another key and specify another record to be updated with the relative member's updating data. Thus, updating the wrong record (key column, and other columns) with the desired record data leads to duplicate primary key exception, and in case of updating the wrong record with a new data of a new relative member for a person, the new record appears in the the desired person's members jtable, which was the update of a member from another - wrong - person's members.
So, in an java/mysql application, an sql UPDATE cannot behave directly as an sql INSERT, but it may leave an INSERT effects as in this case if this wrong updated record was auto-renewable or auto-recreatable, so it would leave some INSERT behavior.
Thank you all For caring, viewing and trying to answer.
Related
I'm using JFreeChart to create a chart in Java and MySQL.
When I try to insert my values in another table the query seems to be executed twice since I end up with the same timestamps multiple times...
Here's a part of my code :
private JDBCXYDataset createDataset() {
try {
Connection conn = DriverManager.getConnection(
"jdbc:mysql://localhost:bd?serverTimezone=UTC","MySQL", "MySQL");
conn.setAutoCommit(false);
SQLException savedException = null;
Statement st = conn.createStatement();
st.execute("DROP TABLE IF EXISTS test ");
st.execute("create table test(Table timestamp, Table float,Table float)");
String Date_Debut = "2020-06-25 00:00:00";
String Date_Fin = "2020-06-26 00:00:00";
String sql1 = "INSERT INTO test (Table ,Table ,Table ) "
+ "SELECT Table ,Table ,Table "
+ "FROM Table "
+ "WHERE Table BETWEEN ? AND ? ";
try ( PreparedStatement ps = conn.prepareStatement(sql1)){
ps.setString(1,Date_Debut);
ps.setString(2, Date_Fin);
ps.executeUpdate();
ps.close();
JDBCXYDataset jds = new JDBCXYDataset(conn);
st.close();
jds.executeQuery("SELECT Table ,Table ,Table FROM test");
conn.commit();
return jds;
} catch (SQLException ex) {
savedException = ex;
conn.rollback();
} finally {
conn.setAutoCommit(true);
if(savedException != null) {
throw savedException;
}
}
} catch (SQLException ex1) {
}
return null;
}
EDIT : Actually it seems like the errors where comming directly from the database, the moderators can delete this post if they want. However I keep Trashgod's response validated as it was more than helpful.
For everyone that might come here with a similar issue, inspect in detail your database first to see if it isn't comming from there instead of your code.
Chasing down anomalies in data is arduous, but JFreeChart can at least make the result easier to visualize. Some heuristics for testing:
To verify that the the presumed duplicates in your tabular listing are indeed duplicates, format the timestamps to include milliseconds, e.g. add an S to a SimpleDateFormat or A to a DateTimeFormatter.
For study, temporarily pass the query directly to JDBCXYDataset, and add an ORDER BY clause (untested):
jds.executeQuery(
"SELECT Date_Heure, PV, SV FROM cmd3 "
+ "WHERE Date_Heure BETWEEN "
+ "2020-06-25 00:00:00 AND 2020-06-26 00:00:00 "
+ "ORDER BY Date_Heure");
Enable tooltips in your ChartFactory, as you did here, to see data values in situ. This may suggest additional conditions for your WHERE clause, e.g. PV BETWEEN 5.1 AND 5.9.
Use the interactive JFreeChart pan/zoom controls, discussed here to examine the data; add suitable buttons, shown here, if it will make it easier for colleagues to see your findings.
By design, JDBCXYDataset executes a query defined by a String. If your design needs to display data from a query defined by a PreparedStatement, you can use the existing implementation as a guide.
public class PreparedDataset extends AbstractXYDataset
implements XYDataset, TableXYDataset, RangeInfo {
private final PreparedStatement ps;
public PreparedDataset(PreparedStatement ps) {
this.ps = ps;
}
…
}
Here's my code for the addStudent:
#FXML
private void addStudent(ActionEvent event) {
// sql query to insert data into students at ID, first name, last name, email and DOB
String sqlInsert = "INSERT INTO students(id,fname,lname,email,DOB) VALUES (?,?,?,?,?)";
try {
Connection conn = dbConnection.getConnection();
PreparedStatement stmt = conn.prepareStatement(sqlInsert);
// add the data in the right column
stmt.setString(1, this.id.getText());
stmt.setString(2, this.firstname.getText());
stmt.setString(3, this.lastname.getText());
stmt.setString(4, this.email.getText());
stmt.setString(5, this.dob.getEditor().getText());
stmt.execute();
conn.close();
} catch(SQLException ex) {
ex.printStackTrace();
}
}
And here's my code for removeStudent:
#FXML
private void removeStudent(ActionEvent event) {
try {
// sql query to delete data from the database
String sqlRemove = "DELETE FROM students WHERE id = ?";
// open a connection to the database and use PreparedStatement to
// initialize the query.
Connection conn = dbConnection.getConnection();
PreparedStatement delete = conn.prepareStatement(sqlRemove);
// information needed to delete the row
delete.setString(1, selectStudent());
// execute and delete
delete.executeUpdate();
// close the connection
conn.close();
} catch (SQLException ex) {
ex.printStackTrace();
}
// update table after deleting
loadStudentData(event);
}
The picture above is the view of my table. I hit LoadData and my table values show up. I want to be able to click on a row(student) and hit Delete Student to remove it.
Helper method for removeStudent:
private String selectStudent() {
String result = "";
try {
String sqlSelect = "SELECT id FROM students";
Connection conn = dbConnection.getConnection();
ResultSet rs = conn.createStatement().executeQuery(sqlSelect);
result = rs.getString(1);
conn.close();
} catch (SQLException ex) {
ex.printStackTrace();
}
return result;
}
I'm pretty sure it has to do with when I "click" on a row, the id value for that isn't being held anywhere so when I hit "Delete" nothing is being given for it to Delete.
I don't know. Any advice would be awesome. :D
First edit: nothing is assigned to delete.setString(1, this.id.getText()). When I click on the row and hit delete, nothing is happening because there's nothing being assigned to id when I click on the row. The query string DOES work however when I physically give it an ID to delete. Also verified that the button does work; it prints out a lovely message for me with a good ol' System.out.println("expletive");
Second edit: Ok, so I updated the removeStudent code and now all I get is the string "null" returned. Nothing deletes. Nothing updates. Nothing is happening except I get "null" in the console.
Third edit: Getting closer! With the realization that the removeStudent isn't being given an ID to delete, I decided to create a private helper method that will do a SELECT query. Now, when I hit delete, it'll delete....but from the top, and not at where I want it selected. The code is above.
Fourth edit: Getting even closer! So, I figured out how to capture the row I click on within the table and I can delete......however, because of my sqlRemove command, I'm deleting by id so if I click on a row with index 3, then ONLY the row within the table that has an id of 3 will be deleted, nothing else. I gotta re-write how the sqlRemove command is worded.
I fixed it:
private String selectStudent() {
// initial value for result to return
String result = "";
// grab the index of the row selected on the table
int initial = studenttable.getSelectionModel().getSelectedIndex();
try {
// SELECT query to execute
String sqlSelect = "SELECT id FROM students";
Connection conn = dbConnection.getConnection();
ResultSet rs = conn.createStatement().executeQuery(sqlSelect);
// while there's a next row
while(rs.next()) {
// set temp to equal the id rs.next() is currently on
String temp = rs.getString("id");
// get the row id - 1 since we start at 0
int temp1 = rs.getRow() - 1;
// if temp1 is equal to the index we selected
if(temp1 == initial) {
// make it equal to result
result = temp;
}
}
// close the connection
conn.close();
} catch (SQLException ex) {
ex.printStackTrace();
}
// return the row to delete
return result;
}
What's going on is in the comments. I finally figured out how to pass the value from a selected row and compare it to a row. Once I get the correct row to pass, I give it to the delete function to remove.
After a day in a half.............but I love it, so. Yeah.
Hi I have a problem with my syntax in my java code. I have a tableview which gets its data from a SQL database. I have created 3 tables in the database book, customer, order. When I click a button I want to take the selected books and add them to the order table.
Here is the code from the main program (calling the method from db):
if(table.getSelectionModel().getSelectedItems().iterator().hasNext()) {
db.insertOrder(new Bestellung(customerid,table.getSelectionModel().getSelectedItems().iterator().next()));
The table book is fixed. Just the two other tables customer,order are dynamic.
The problem:
I create the values in the order table like this
String ct = "CREATE TABLE Order (" + "Order_Id integer generated always as identity, " + "CUSTOMER_ID BIGINT" + "ISBN, CHAR(13) " + "PRIMARY KEY(Order_Id))";
and so on...
I insert into order table like this. (Here is the syntax problem in the String i That's the position where the compiler says it doesn't work..)
String i = "INSERT INTO ORDER(CUSTOMER_ID,ISBN), VALUES(?,?)";
Connection conn = null;
PreparedStatement stmt = null;
try {
conn = DriverManager.getConnection(connString);
stmt = conn.prepareStatement(i);
conn.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE,ResultSet.CONCUR_UPDATABLE);
stmt.setLong(1, order.getCustomerId());
stmt.setString(2, order.getBuch().getISBN());
stmt.executeUpdate();
} catch (SQLException e) {
System.out.println(e.getMessage());
e.printStackTrace();
}
finally {
try {
if (stmt != null)
stmt.close();
if (conn != null)
conn.close();
} catch (SQLException e) {
System.out.println(e.getMessage());
e.printStackTrace();
}
}
and here is the syntax error which I got
Syntax error: Encountered "ORDER" at line 1, column 13.
So how do I have to correct my syntax in the string i? Does anyone have any ideas?
INSERT INTO ORDER(CUSTOMER_ID,ISBN), VALUES(?,?)
^
The comma is superfluous. Also, in your CREATE TABLE
... + "ISBN, CHAR(13) " + ...
^
This comma is also extraneous.
If you want to use reserved words/keywords as Table name, you should:
MySQL: use ' , like : select * from 'Order'
Oracle, PostgreSQL: use " , like : select * from "Order"
But it is bad practice, try to change your table name.
You have another Error that answered by #Jim Garrison.
I want to insert 700 million rows to a table which is defined in a following way.
CREATE TABLE KeywordIndex (id INT PRIMARY KEY AUTO_INCREMENT,
keyValue VARCHAR(45) NOT NULL, postings LONGTEXT NOT NULL);
To insert data in the table I first check if the keyValue exists I update the value of postings by concatenating new value to old value. Otherwise, insert data as a new row of the table. Also, if the size of postings is bigger than its definition I consider a new row to write extension of postings of the keyValue. In my implementation, inserting 70,294 entry took 12 hours!!!!
( I am not a database expert, so the code I've written could be based on wrong foundations. Please help me to understand my mistakes :) )
I read this page but I could not find a solution for my problem.
I add code that I wrote to do this process.
public void writeTermIndex(
HashMap<String, ArrayList<TermPosting>> finalInvertedLists) {
try {
for (String key : finalInvertedLists.keySet()) {
int exist=ExistTerm("KeywordIndex",key);
ArrayList<TermPosting> currentTermPostings=finalInvertedLists.get(key);
if (exist>0)
{
String postings=null;
String query = "select postings from KeywordIndex where keyValue=?";
PreparedStatement preparedStmt = conn.prepareStatement(query);
preparedStmt.setString (1, key);
ResultSet rs=preparedStmt.executeQuery();
if(rs.next())
postings=rs.getString("postings");
postings=postings+convertTermPostingsToString(currentTermPostings);
if(getByteSize(postings)>65530)
insertUpdatePostingList("KeywordIndex",key,postings);
else{
updatePosting("KeywordIndex",key,postings);
rs.close();
preparedStmt.close();
}
}
else
{
String postings=convertTermPostingsToString(currentTermPostings);
if(getByteSize(postings)>65530)
insertPostingList("KeywordIndex",key,postings);
else
insetToHashmap("KeywordIndex",key,postings);
}
}
}
catch(Exception e){
e.printStackTrace();
}
}
You should think about using executeBatch() for insert (I'm not talking about the load part of your request). Depending on your database, performances can change a lot (see benchmark at the end of this page)(I once tested it with oracle database)
Something like :
PreparedStatement statement = null;
try {
statement = getConnection().prepareStatement(insertQuerry);
for (/*...*/) {
statement.clearParameters();
statement.setString(1, "Hi");
statement.addBatch();
}
statement.executeBatch();
} catch (SQLException se) {
//Handle exception
} finally {
//Close everything
}
No error is showing when i click the button but the table on the database doesn't update.
String heh = jLabel17.getText();
try {
stmt.executeUpdate("UPDATE books SET availability='"+"Unavailable"+"' where Book_title='"+heh+"'");
}catch (SQLException err) {
System.out.println(err.getMessage() );
}
You have messed up the query totally,
stmt.executeUpdate("UPDATE books SET availability='"+"Unavailable"+"' where Book_title='"+heh+"'");
should be,
stmt.executeUpdate("UPDATE books SET availability='Unavailable' where Book_title='"+heh+"' ");
It is advisable to print query before you execute , as that avoids common mistakes. Also try to use Prepared Statements as yours is vulnerable to sql injection
Read this Prepared Statements and JDBC Drivers
AFTER HOURS OF RESEARCH, I FOUND THE SOLUTION, I REPLACED THIS
String heh = jLabel17.getText();
try{
stmt.executeUpdate("UPDATE books SET availability='"+"Unavailable"+"' where Book_title='"+heh+"'");
}catch(SQLException err){
System.out.println(err);
}
WITH THIS CODE
String heh = jLabel17.getText();
try{
con = DriverManager.getConnection("jdbc:derby://localhost:1527/Dafuq7","Dafuq7","Dafuq7");
// Creating Statement for query execution
stmt = con.createStatement();
// creating Query String
String query = "UPDATE books SET availability='NOT AVAILABLE' WHERE book_title='"+heh+"'";
// Updating Table
int rows = stmt.executeUpdate(query);
System.out.println(rows + " Rows Updated Successfully....");
} catch (Exception e) {
System.out.println(e.toString());
}