Insert on foreign key constraint - java

I am trying to insert the [ORDERID] (foreign key), [PHONENUMBER] (foreign key), [ORDERTIME],and [TOTALPRICE] into my Orders database. [ORDERID] and [PHONENUMBER] are also the primary keys of my two other collections, Customers and OrderedItems. So, I have made sure to update those tables first before I update the orders table. However, I am still getting a foreign key error in my Orders database.
try
{
// create a PreparedStatement to insert a new address book entry
PreparedStatement addCustomer
= connection.prepareStatement("INSERT INTO customers "
+ "(Phonenumber, firstname, lastname, email) \n"
+ " ( SELECT ?, ?, ?, ? \n"
+ "From customers \n"
+ " WHERE phonenumber = ?"
+ " HAVING count(*)=0 )"
);
// specify the PreparedStatement's arguments
addCustomer.setString(1, getFirstName());
addCustomer.setString(2, getLastName());
addCustomer.setString(3, getPhone());
addCustomer.setString(4, getEmail());
addCustomer.setString(5, getPhone());
addCustomer.executeUpdate(); // insert the entry
// create a PreparedStatement to insert a new address book entry
PreparedStatement addOrderedItems =
connection.prepareStatement("INSERT INTO ORDEREDITEMS " +
"(ORDERID, PIZZAID, PIZZAQN, SIDESID, SIDESQN, DRINKID, DRINKQN)" +
" VALUES (?, ?, ?, ?, ?, ?, ?)");
// specify the PreparedStatement's arguments
addOrderedItems.setInt(1, getID());
addOrderedItems.setInt(2, getPizza());
addOrderedItems.setInt(3, getPizzaQuantity());
addOrderedItems.setInt(4, getSides());
addOrderedItems.setInt(5, getSidesQuantity());
addOrderedItems.setInt(6, getDrinks());
addOrderedItems.setInt(7, getDrinksQuantity());
addOrderedItems.executeUpdate(); // insert the entry
// create a PreparedStatement to insert a new address book entry
PreparedStatement addEntry =
connection.prepareStatement("INSERT INTO ORDERS " +
"(ORDERID, PHONENUMBER, ORDERTIME, TOTALPRICE)" +
" VALUES (?, ?, ?, ?)");
// specify the PreparedStatement's arguments
addEntry.setInt(1, getID());
addEntry.setString(2, getPhone());
addEntry.setString(3, getTime());
addEntry.setDouble(4, getPrice());
addEntry.executeUpdate(); // insert the entry
return "index"; // go back to index.xhtml page

Related

Integrity constraint violation: unique constraint or index violation HSQLDB

For example if I add new Department(new BigInteger("50"), "ODD", "SPB"), all work, it values are insert into database. But if I want again insert for example new Department(new BigInteger("50"), "ODDMOD", "SPBMOD"), appear java.sql.SQLIntegrityConstraintViolationException: integrity constraint violation: unique constraint or index violation; SYS_PK_10092 table: DEPARTMENT. I know that can not insert values with the same primary key, but how can update values if primary key exists or other solutions?
public Department save(Department department) throws SQLException {
Connection connection = ConnectionSource.instance().createConnection();
String sql = "insert into department values (?, ?, ?)";
PreparedStatement statement = connection.prepareStatement(sql);
statement.setLong(1, Long.parseLong(String.valueOf(department.getId())));
statement.setString(2, department.getName());
statement.setString(3, department.getLocation());
statement.executeUpdate();
PreparedStatement st = connection.prepareStatement("select * from department where id = ? ");
st.setLong(1, Long.parseLong(String.valueOf(department.getId())));
ResultSet resultSet = st.executeQuery();
resultSet.next();
Department demper = new Department(
new BigInteger(String.valueOf(resultSet.getInt("id"))),
resultSet.getString("name"),
resultSet.getString("location")
);
return demper;
}
You want an upsert here:
public Department save(Department department) throws SQLException {
Connection connection = ConnectionSource.instance().createConnection();
String sql = "MERGE INTO department d1 " +
"USING (VALUES ?, ?, ?) d2 (id, name, location) " +
" ON (d1.id = d2.id) " +
" WHEN MATCHED THEN UPDATE SET " +
" d1.name = d2.name, d1.location = d2.location " +
" WHEN NOT MATCHED THEN INSERT (id, name, location) VALUES (d2.id, d2.name, d2.location)";
PreparedStatement statement = connection.prepareStatement(sql);
// execute merge here as before
statement.setLong(1, Long.parseLong(String.valueOf(department.getId())));
statement.setString(2, department.getName());
statement.setString(3, department.getLocation());
statement.executeUpdate();
// ...
}
A MERGE behaves by doing an insert if the department id does not already exist in the table. Otherwise it will do an update. Note that if you shift to JPA/Hibernate from pure JDBC, the JPA save() method can upsert automatically for you under the hood.

Oracle primary key generator in Java

My app allows users to create an account (stored in database) and place orders.
When a client registers himself, I want to generate a primary key named CLIENT_CODE to identify him, starting from x value and increment it with y value. (I'm using oracle 11g atm)
I've tried this so far:
private void jButton6ActionPerformed(java.awt.event.ActionEvent evt) {
String fname = jTextField9.getText();
String lname = jTextField10.getText();
String city = jTextField11.getText();
String street = jTextField13.getText();
String number = jTextField14.getText();
String userClient = jTextField15.getText();
String pass1 = String.valueOf(jPasswordField5.getPassword());
String pass2 = String.valueOf(jPasswordField6.getPassword());
if(verifyFields()){
if(!checkUsername(userClient)){
OraclePreparedStatement ps;
OracleResultSet rs;
String registerClient = "insert into CLIENT (FNAME_CL, LNAME, CITY, STREET, NUMBER, MONEY, CLIENT_CODE, USER_CLIENT, PASS) values (?, ?, ?, ?, ?, ?, ?, ?, ?)";
try {
ps = (OraclePreparedStatement) JavaConnectDb.ConnectDb().prepareStatement(registerClient);
ps.setString(1, fname);
ps.setString(2, lname);
ps.setString(3, city);
ps.setString(4, street);
ps.setString(5, number);
ps.setDouble(6, 0.0);
ps.setInt(7, ???); <--- here should be the generated primary key
ps.setString(8, userClient);
ps.setString(9, pass1);
if(ps.executeUpdate() != 0){
JOptionPane.showMessageDialog(null, "Account created!");
} else{
JOptionPane.showMessageDialog(null, "Error: Check your info");
}
} catch (SQLException ex) {
Logger.getLogger(App.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
}
Don't do it in Java; handle the primary key value creation in the database using a sequence:
CREATE SEQUENCE CLIENT__CLIENT_CODE__SEQ
START WITH 1
INCREMENT BY 1
Then just use your sequence in the INSERT statement and use the RETURNING clause to get the generated value as an OUT parameter of your prepared statement.
insert into CLIENT (
FNAME_CL,
LNAME,
CITY,
STREET,
NUMBER,
MONEY,
CLIENT_CODE,
USER_CLIENT,
PASS
) values (
?,
?,
?,
?,
?,
?,
CLIENT__CLIENT_CODE__SEQ.NEXTVAL,
?,
?
) RETURNING CLIENT_CODE INTO ?
If you were using Oracle 12c then you could use GENERATED AS IDENTITY in the table's CREATE DDL statement to generate the values without creating a separate sequence.

Get RETURNING value from Postgresql via Java

From Java, I'm calling a prepared statement in Postgresql with an insert that has a RETURNING clause for my identity column. In PG admin it comes right back, but not sure how to get it from my prepared statement:
String insertStatement = "INSERT INTO person(\n" +
" name, address, phone, customer_type, \n" +
" start_dtm)\n" +
" VALUES (?, ?, ?, ?, \n" +
" ?)\n" +
" RETURNING person_id;";
PreparedStatement stmt = connection.prepareStatement(insertStatement);
stmt.setObject(1, perToSave.getName(null));
stmt.setObject(2, editToSave.getAddress());
stmt.setObject(3, editToSave.getPhone());
stmt.setObject(4, editToSave.getCustType());
long epochTime = java.lang.System.currentTimeMillis();
stmt.setObject(5, new java.sql.Date(epochTime));
stmt.executeUpdate();
I do not have enough reputation to Comment and my Edit got rejected, so sorry for re-posting the already accepted answer from hd1.
executeUpdate expects no returns; use execute.
Check if there is some results before trying to retrieve the value.
String insertStatement = "INSERT INTO person(\n" +
" name, address, phone, customer_type, \n" +
" start_dtm)\n" +
" VALUES (?, ?, ?, ?, \n" +
" ?)\n" +
" RETURNING person_id;";
PreparedStatement stmt = connection.prepareStatement(insertStatement);
stmt.setObject(1, perToSave.getName(null));
stmt.setObject(2, editToSave.getAddress());
stmt.setObject(3, editToSave.getPhone());
stmt.setObject(4, editToSave.getCustType());
long epochTime = java.lang.System.currentTimeMillis();
stmt.setObject(5, new java.sql.Date(epochTime));
stmt.execute();
ResultSet last_updated_person = stmt.getResultSet();
if(last_updated_person.next()) {
int last_updated_person_id = last_updated_person.getInt(1);
}
According to the javadoc, PreparedStatement inherits from Statement and the latter contains a getResultSet() method. In other words, try this:
String insertStatement = "INSERT INTO person(\n" +
" name, address, phone, customer_type, \n" +
" start_dtm)\n" +
" VALUES (?, ?, ?, ?, \n" +
" ?)\n" +
" RETURNING person_id;";
PreparedStatement stmt = connection.prepareStatement(insertStatement);
stmt.setObject(1, perToSave.getName(null));
stmt.setObject(2, editToSave.getAddress());
stmt.setObject(3, editToSave.getPhone());
stmt.setObject(4, editToSave.getCustType());
long epochTime = java.lang.System.currentTimeMillis();
stmt.setObject(5, new java.sql.Date(epochTime));
stmt.execute();
ResultSet last_updated_person = stmt.getResultSet();
last_updated_person.next();
int last_updated_person_id = last_updated_person.getInt(1);
Leave a comment if you have further issues.
Calling executeUpdate() expects no result from statement. Call stmt.execute() and then stmt.getResultSet()
JDBC has built-in support for returning primary key values for insert statements. Remove the "returning" clause from your SQL and specify PreparedStatement.RETURN_GENERATED_KEYS as a second parameter to your prepareStatment(...) call. Then you can get the generated primary key by calling stmt.getGeneratedKeys() on your PreparedStatement object after calling executeUpdate().
String insertStatement = "INSERT INTO person(\n" +
" name, address, phone, customer_type, \n" +
" start_dtm)\n" +
" VALUES (?, ?, ?, ?, \n" +
" ?)";
PreparedStatement stmt = connection.prepareStatement(insertStatement,
PreparedStatement.RETURN_GENERATED_KEYS);
stmt.setObject(1, perToSave.getName(null));
stmt.setObject(2, editToSave.getAddress());
stmt.setObject(3, editToSave.getPhone());
stmt.setObject(4, editToSave.getCustType());
long epochTime = java.lang.System.currentTimeMillis();
stmt.setObject(5, new java.sql.Date(epochTime));
stmt.executeUpdate();
ResultSet resultSet = stmt.getGeneratedKeys();
resultSet.next();
int lastInsertedPersonID = resultSet.getInt(1);

How to optimize this update SQL query

I have this Java method which I will use to insert data from JSF form into Oracle:
public int saveData(int result) throws SQLException, java.text.ParseException, NoSuchAlgorithmException {
String SqlStatement = null;
if (ds == null) {
throw new SQLException();
}
Connection conn = ds.getConnection();
if (conn == null) {
throw new SQLException();
}
PreparedStatement ps = null;
/*
CREATE TABLE USERS(
USERID INTEGER NOT NULL,
GROUPID INTEGER,
SPECIALNUMBER VARCHAR2(60 ),
USERNAME VARCHAR2(50 ),
PASSWD VARCHAR2(50 ),
DATETOCHANGEPASSWD DATE,
ADDRESS VARCHAR2(60 ),
STATEREGION VARCHAR2(50 ),
COUNTRY VARCHAR2(50 ),
USERSTATUS VARCHAR2(30 ),
TELEPHONE VARCHAR2(50 ),
DATEUSERADDED DATE,
USEREXPIREDATE DATE,
DATEUSERLOCKED CHAR(20 ),
CITY VARCHAR2(50 ),
EMAIL VARCHAR2(50 ),
DESCRIPTION CLOB
)
/
*/
try {
conn.setAutoCommit(false);
boolean committed = false;
try { /* insert into Oracle the default system(Linux) time */
InsertSqlStatement = "INSERT INTO USERS"
+ " (USERID, GROUPID, SPECIALNUMBER, USERNAME, PASSWD, DATETOCHANGEPASSWD,"
+ " ADDRESS, STATEREGION, COUNTRY, USERSTATUS, TELEPHONE, DATEUSERADDED,"
+ " USEREXPIREDATE, DATEUSERLOCKED, CITY, EMAIL, DESCRIPTION)"
+ " VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)";
UpdateSqlStatement = "UPDATE USERS "
+ "SET "
+ "USERID = ?, "
+ "GROUPID = ?, "
+ "SPECIALNUMBER = ?, "
+ "USERNAME = ?, "
+ "PASSWD = ?, "
+ "DATETOCHANGEPASSWD = ?, "
+ "ADDRESS = ?, "
+ "STATEREGION = ?, "
+ "COUNTRY = ?, "
+ "USERSTATUS = ?, "
+ "TELEPHONE = ?, "
+ "DATEUSERADDED = ?, "
+ "USEREXPIREDATE = ?, "
+ "DATEUSERLOCKED = ?, "
+ "CITY = ?, "
+ "EMAIL = ?, "
+ "DESCRIPTION = ? "
+ "WHERE USERID = " + id;
ps = conn.prepareStatement(SqlStatement);
ps.setString(1, settingsMap.get("USERID"));
ps.setString(2, settingsMap.get("GROUPID"));
ps.setString(3, settingsMap.get("SPECIALNUMBER"));
ps.setString(4, settingsMap.get("USERNAME"));
ps.setString(5, passwdConvert(settingsMap.get("PASSWD")));
ps.setDate(6, toDate(settingsMap.get("DATETOCHANGEPASSWD")));
ps.setString(7, settingsMap.get("ADDRESS"));
ps.setString(8, settingsMap.get("STATEREGION"));
ps.setString(9, settingsMap.get("COUNTRY"));
ps.setString(10, settingsMap.get("USERSTATUS"));
ps.setString(11, settingsMap.get("TELEPHONE"));
ps.setDate(12, toDate(settingsMap.get("DATEUSERADDED")));
ps.setDate(13, toDate(settingsMap.get("USEREXPIREDATE")));
ps.setDate(14, toDate(settingsMap.get("DATEUSERLOCKED")));
ps.setString(15, settingsMap.get("CITY"));
ps.setString(16, settingsMap.get("EMAIL"));
ps.setString(17, settingsMap.get("DESCRIPTION"));
ps.executeUpdate();
conn.commit();
committed = true;
}
finally
{
if (!committed) {
conn.rollback();
}
}
} finally {
/* Release the resources */
ps.close();
conn.close();
}
return result;
}
Right now I cannot test the SQL query. Can you tell me is it valid and how I can optimize the SQL query for performance?
Right now I cannot test the SQL query. Can you tell me is it valid ...
Not with any certainty. (Why don't you wait until you CAN test it??)
... and how I can optimize the SQL query for performance?
It is not entirely clear what you are trying to do. However, here are some suggestions on performance:
You are creating and releasing a database connection for each SQL statement executed. That has to be bad for performance.
There is no need to do an insert followed by an update of the same record ... if that is what you are proposing to do.
You will get performance by doing a bulk or batch insert or update rather than inserting records one at a time.
If you are inserting lots of data into an empty table with lots of indexes, then you may get better performance if you do the insertions first and create the indexes afterwards.
At the level of a single query (i.e. the "UPDATE"), you probably cannot make the query significantly faster.
The only improvement you can make is put the id as '?' also:
UPDATE USERS "
+ "SET "
+ "USERID = ?, "
+ "GROUPID = ?, "
+ "SPECIALNUMBER = ?, "
+ "USERNAME = ?, "
+ "PASSWD = ?, "
+ "DATETOCHANGEPASSWD = ?, "
+ "ADDRESS = ?, "
+ "STATEREGION = ?, "
+ "COUNTRY = ?, "
+ "USERSTATUS = ?, "
+ "TELEPHONE = ?, "
+ "DATEUSERADDED = ?, "
+ "USEREXPIREDATE = ?, "
+ "DATEUSERLOCKED = ?, "
+ "CITY = ?, "
+ "EMAIL = ?, "
+ "DESCRIPTION = ? "
+ "WHERE USERID = ?";
And of course add a set decleration:
ps.setInt(18, id);
I think there is nothing to optimize because you are inserting to only one table. Same for update. There are no joins or grouping so there is really anything you can do about it. Maybe just one note - you could use StringBuilder for code formatting :-)
If you are going to insert several rows, then you could increase performance by reusing the database connection, as well as the prepared statement. The latter requires treating the user id as a row as well, the way ftom2 suggested. Apart from that, there is little room for performance optimizations.

Unable to insert a row in Oracle with Java (JDBC) --> error ORA-00917: missing comma

I have a problem during an insert in Oracle using Java and JDBC. The error obtained is:
java.sql.SQLException: ORA-00917: missing comma
The data for the insert is taken from a form like a string and is parsed to the appropiated data type and then is saved in an object called edicio. That's all OK. Then, my intention is make an insert in the DB using the data of this object.
Here is the code of the DAO, where I'm making the insert:
public Edicio insertarCurs(Connection con, Edicio ed) throws SQLException {
PreparedStatement stm = null;
ResultSet rst = null;
// Insert
StringBuffer sql = new StringBuffer();
sql.append("INSERT INTO curs (id, nom, idarea, area, programa, datainici)");
sql.append(" VALUES (?, ?, ?, ?, ?, ?");
logger.info("Building insert works fine.");
try {
stm = con.prepareStatement(sql.toString());
// params
stm.setLong(1, ed.getIdEdicio());
stm.setString(2, ed.getNomEdicio());
stm.setLong(3, ed.getIdArea());
stm.setString(4, ed.getArea());
stm.setString(5, ed.getPrograma());
// Conversion from Java Date to SQL Date
java.sql.Date sqlDate = new java.sql.Date(ed.getDataInici().getTime());
logger.info("sqlDate before the insert is: "+ sqlDate); //0011-12-02
stm.setDate(6, sqlDate);
// Data and results commented
logger.info("Id edicio: "+ ed.getIdEdicio()); //6
logger.info("Nom edicio: "+ ed.getNomEdicio()); //test
logger.info("Id area: "+ ed.getIdArea()); //0
logger.info("Nom area: "+ ed.getArea()); //test
logger.info("Programa: "+ ed.getPrograma()); //test
logger.info("Data inici: "+ sqlDate); //2011-06-06
// We are going to execute the insert
int numRows = stm.executeUpdate();
// The program never reaches this point, fails doing the executeUpdate()
logger.info("Rows created: "+ numFiles);
...
The variable types are:
idEdicio = long
nomEdicio = String
idArea = long
area = String
programa = String
dataInici = Date
Can someone help me? Thank you in advance :)
Missing )
sql.append(" VALUES (?, ?, ?, ?, ?, ?");
should be
sql.append(" VALUES (?, ?, ?, ?, ?, ?)");
sql.append(" VALUES (?, ?, ?, ?, ?, ?)");
^--- missing parenthesis

Categories

Resources