JDBC ResultSet::RefreshRow not working with Cascading update - java

I'm trying to throw together a quick JDBC app using Postgres as the DB and am running into an interesting issue.
I currently have 2 tables, table1 and table2.
CREATE TABLE table1
(
a character varying NOT NULL,
b integer NOT NULL,
CONSTRAINT table1_pkey PRIMARY KEY (b)
)
CREATE TABLE table2
(
c character varying NOT NULL,
d integer,
CONSTRAINT table2_pkey PRIMARY KEY (c),
CONSTRAINT table2_d_fkey FOREIGN KEY (d),
REFERENCES table1(b) MATCH SIMPLE
ON UPDATE CSCADE ON DELETE CASCADE
)
As the backend of my program I'm SELECTing * and holding on to the ResultSet from my query. Each table has 1 row of simple values in it, doesn't seem to matter what they are.
My statement is created with the flags ResultSet.TYPE_SCROLL_INSENSITIVE and ResultSet.CONCUR_UPDATE. Although I have tried SCROLL_SENSITIVE as well.
If I try the following (assumgin ResultSet rs/rs2 are valid and point to table1/table2 respectively:
rs.first(); // move to the first row (only row)
rs.updateInt(2, 50); // update our primary key, which is also the cascading fk
// 50 could be any number
print(rs); // Will show the old value
rs.updateRow();
print(rs); // Will show the new value
rs2.refreshRow(); // make sure we get the latest data from table2
print(rs2); // will show the old data?
I was hoping to see the new values due to the cascade. If I quit and re-run the app, not changing any input, then it will print the correct table2 values. I'm guessing this is due to re-running the SELECT statement. If I look at the table by running psql or pgadmin3, the values seem like they're changing. So it seems like refreshRow() isn't bringing down the latest stuff. Would anyone have any idea why?
I'm using:
java 1.6_29
postgresql-9.1-901.jdbc4.jar
Any help would be appreciated.

I hope you got it sorted out since it's an old question but just for the record I post here a snippet that I tried and which is working for me:
Statement stmt = conn.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_UPDATABLE);
ResultSet rs = stmt.executeQuery("SELECT * FROM table1");
Statement stmt2 = conn.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_UPDATABLE);
ResultSet rs2 = stmt2.executeQuery("SELECT * FROM table2");
rs.first(); // move to the first row (only row)
rs.updateInt(2, 50); // update our primary key, which is also the
// cascading fk 50 could be any number
System.out.println(rs.getString(2)); // Prints the old value 12
rs.updateRow();
System.out.println(rs.getString(2)); // Prints the new value 50
rs2.first();
rs2.refreshRow(); // make sure we get the latest data from table2
System.out.println(rs2.getString(2)); // Prints the new value 50

Related

Get a specific column of the updated rows

I need to know how to execute an update in JDBC with Oracle database backend and retrieve values for a specific column of the records that have been updated. The column that I am interested in is part of a composite primary key, e.g. COL_NAME in the example below.
I have tried the following:
String query = "UPDATE T1 SET COL_ABC = 'A'"; // Simplified
statement = conn.prepareStatement(query.toString(), new String[] { "COL_NAME" });
ResultSet rs = statement.getResultSet();
while (rs.next()) {
rs.getLong("COL_NAME");
}
But statement comes back as null.
I am not sure how to utilize RETURNING INTO in this case unless converting this whole thing into an anonymous PL/SQL block, if it is indeed a possible solution.
Please note that I need a list of the values from this column from all the records that have been updated.

PostgreSQL unique string field

My database is PostgreSQL. The language is Java.
Table name is phrase with column name name.
At any time many users are inserting many rows to this table.
And we need to make sure that a certain field is unique.
And if such a field was found during loading, I want to return the row ID.
I could for example make a field the unique primary key, and when a row id inserted, catch the exception and look up the existing row.
But I think that is a bad idea.
I could just look for that row first and then insert.
But how can we avoid that the concurrent transactions get in each other's way?
And when downloading, is it better to do a batch download, and how do I do that in PostgreSQL? I do not even know.
You could create a UNIQUE constraint and INSERT ... ON CONFLICT:
CREATE TABLE mytable (
id integer PRIMARY KEY,
name text NOT NULL
CONSTRAINT name_unique UNIQUE
);
INSERT INTO mytable (id, name)
VALUES (1, 'me');
Now to run a batch INSERT that returns the id of each affecte row, run
INSERT INTO mytable (id, name)
VALUES (2, 'me'),
(3, 'new')
ON CONFLICT (name)
DO UPDATE SET name = EXCLUDED.name
RETURNING id;
The strange UPDATE that does not actually change the row is necessary if you want the id back.
Instead of catching the exception, you can use the INSERT ... ON CONFLICT DO NOTHING clause available in PostgreSQL. By checking the number of affected rows (returncode of PreparedStatement.executeUpdate), you can detect if there was a conflict.
E.g.
PreparedStatement pstmt = conn.prepareStatement("insert into x values (?,?) on conflict do nothing");
pstmt.setInt(1, myId);
pstmt.setInt(2, myValue);
int rc = pstmt.executeUpdate();
if (rc == 0) {
// fetch the existing row...
}

Retrieving Primary Key Generated By Trigger (Java)

Here's what I'm attempting to do. I have a Java program that decomms a telemetry stream into the individual raw fields. I am passing these raw fields values into a MySQL table where each column is one of the fields. In this database I also have a view that grabs all the telemetry data and calculates a few new derived columns based on raw data (e.g. raw counts to engineering units). In my Java program, after insertion I would like to grab the corresponding row from the VIEW (raw + derived) and pass that data along elsewhere.
Originally I thought I could simply insert the raw data into the VIEW and have the row returned to me in a ResultSet in the Java program. Unfortunately the data isn't returned in a ResultSet.
What I'm attempting to do now is insert the raw data into the table (this part works), get the primary key, then lookup the row from the VIEW. The part I'm struggling with is retrieving the primary key from the INSERT. I'm using a PreparedStatement generated from my Connection object and have supplied it with Statement.RETURN_GENERATED_KEYS. However, when I call getGeneratedKeys() on my statement after I call executeUpdate() my ResultSet is always empty. I can watch it insert the rows into the table while it's running...what am I doing wrong?
Can I not retrieve the generated primary key in this fashion if the primary key is generated via a trigger?
UPDATE: I've tried swapping out the Statement.RETURN_GENERATED_KEYS for a String array with the name of the primary key column, but that doesn't seem to work either.
I apologize for not including my code, but it would be difficult for me to do so. I've attempted to describe what I'm doing to the best of my abilities.
Ive seen this in another post. That claimed to work. Is this what yours looks like?
Statement stmt = db.prepareStatement(query, Statement.RETURN_GENERATED_KEYS);
numero = stmt.executeUpdate();
ResultSet rs = stmt.getGeneratedKeys();
if (rs.next()){
risultato=rs.getInt(1);
}
I have used SP's and here is an example of what I did. I used an in/out parm to get it back...
CREATE DEFINER=`scaha`#`localhost` PROCEDURE `updateprofile`(
IN in_idprofile INT(10),
IN in_usercode VARCHAR(50),
IN in_pwd VARCHAR(50),
IN in_nickname VARCHAR(50),
IN in_isactive tinyint,
IN in_updated timestamp,
OUT out_idprofile INT(10))
BEGIN
/* If the idprofile is < 1 then we insert a new record.. */
/* otherwise its an update */
if (in_idprofile < 1) then
insert into scaha.profile (usercode, pwd, nickname, isactive,updated) values (in_usercode,in_pwd,in_nickname,in_isactive,in_updated);
SET out_idprofile = LAST_INSERT_ID();
else
update scaha.profile set usercode = in_usercode, pwd = in_pwd, nickname = in_nickname, isactive = in_isactive, updated = in_updated
where idprofile = in_idprofile;
SET out_idprofile = in_idprofile;
end if;
END

Java: updating the MySQL table's id

This is my delete class that gets id as an input.
I succeeded to delete the row(for example row contained id '3' from my database) and now I want to update all the id-s.
for example: my rows were:
1 a5
2 f3
(3 t1 was deleted)
4 r2
so now the result should be updated:
1 a5
2 f3
3 r2
String delete = "DELETE from authors WHERE id = ?";
Class.forName("com.mysql.jdbc.Driver");
Connection con = DriverManager.getConnection(url, "root", "easttg");
PreparedStatement ps = con.prepareStatement(delete);
//updating the id
String sql = "Select id from authors";
PreparedStatement ps2 = con.prepareStatement(sql, Statement.RETURN_GENERATED_KEYS);
ps.setInt(1, id);
ps.executeUpdate();
con.close();
To update some row, you must use an update statement. Not a select statement:
update authors set id = ? where id = ?
That said: IDs are just technical identifiers for rows. They shouldn't be modified generally. And the reason why purely technical IDs are used is that they never need to be modified, which is a good thing because there might be dozens of other tables having foreign keys containing this same ID. The ID might also be part of some URL used to display the row in a web site, that many people could have bookmarked. The ID is... the identity of the row. You don't change an identity. If you do it, all kinds of problems occur, exactly as if you changed your own name.

How can I insert new values into two related tables?

I have a store program in java and a database made in access. I already have 2 tables in my database which are the customers table and the products table.
I want to add an orders table wherein it's primary key is an autonumber and an order_line table to complete this app. I want to have tables like this..
customer(cust_id, name, ....)
orders(order_no, cust_id, date_purchased,...)
order_line(order_no, product_id, ...)
products(product_id, product_name, price,....)
When the customer purchased the products, i could insert new values to the orders table. The thing that is not clear to me is how could i insert also in the order_line table, because the order_no I created in access is of type autonumber.
Would I make a select statement first to get the order_no value to put it to the order_no in order_line's table? Or I need to put this in one query only.
Anyone with experience to this? Any advice is appreciated.
The insertion into orders and order_line table should happen in a single transaction. While doing so, if you are using plain JDBC to insert record into orders table, you can register the order_no as an OUT parameter in your CallableStatement and get the value after the statement is executed and use to set the order_no attribute on the order_line records.
// begin transaction
connection.setAutoCommit(false);
CallableStatement cs = connection.prepareCall(INSERT_STMT_INTO_ORDERS_TABLE);
cs.registerOutParameter(1, Types.INT);
int updateCount = cs.execute();
// Check the update count.
long orderNo = cs.getInt(1);
// CallableStatement csLine for inserting into order_line table
// for (OrderLine line: orderLines) {
// Set the orderNo in line.
// set paramters on csLine.
// csLine.addBatch();
// }
// run the batch and verify update counts
connection.commit();
// connection.rollback() on error.
The JDBC-way (if you like database-independence), is to use the getGeneratedKeys() method of statement.
Use setAutoCommit(false), then execute the first query with the option Statement.RETURN_GENERATED_KEYS (eg for PreparedStatement).
Then use the getGeneratedKeys() method to retrieve the key (note: reference by column name, as the exact implementation and number of returned columns depends on the driver implementation.
And execute the second statement with that retrieved key.
Finally, commit().

Categories

Resources