Java Hibernate : Update most recent entry in MySql database - java

This is my requirement. I have a bunch of rows with similar data. I want to update some columns on the LATEST entry. So I have written a hibernate query which goes like this
String hql = "UPDATE Studenttable T set T.timestamp=:time,T.Action=:action where T.StudentId=:studentId and T.teacherId=:TeacherId order by T.teacher_student_mapping_id DESC";
Query query = session.createQuery(hql);
query.setParameter("time",time);
query.setParameter("studentId", studentId);
query.setParameter("TeacherId", teacherId);
query.setParameter("action", action);
query.setMaxResults(1);
query.executeUpdate();
What this does is it updates all the rows which satisfies the condition and then returns the latest row. Instead I want it to fetch the latest row satisfying the conditions, and then update it. How can I do it? Any help is deeply appreciated.
P.S. the teacher_student_mapping_id is an auto-generated value, which is also a primary key.
Time is the current time.
Please don't try to make sense of the table, I have changed the names of the columns for confidentiality.

try
String hql = "UPDATE Studenttable T set T.timestamp=:time,T.Action=:action where T.StudentId=:studentId and T.teacherId=:TeacherId order by T.timestamp DESC LIMIT 1";

Since tagged hql you can try something like below. Updating only the latest one based on pk.
UPDATE Studenttable T set T.timestamp=:time,T.Action=:action where T.StudentId=:studentId and T.teacherId=:TeacherId
and T.pk = (select max(tb.pk) from Studenttable tb where tb.StudentId=:studentId and tb.teacherId=:TeacherId )

Related

How to force Hibernate use AND in update query?

I am trying to update a raw by composite primary key by using hibernate.
Hibernate uses the next style for such updates:
update mytable set mycolumn=321 where (left_pk, right_pk) = (123, 456);
Is it possible to force hibernate to use the next style?:
update mytable set mycolumn=321 where left_pk = 123 and right_pk = 456;
Both queries work but with a huge difference (at least in MariaDB).
If we use repeatable read transaction then the first query locks the whole table for updates and the second query locks only the single row for updates.
I would prefer to lock only a single row, so I need to use the second query.
You can go for NamedQueries approach in Hibernate,
For example:
//Create Query
#NamedQueries({ #NamedQuery(name = " YOUR QUERY NAME",
query = "from DeptEmployee where department = :department and emp = :emp") })
// set multiple parameters
query.setParameter("department",department)
.setParameter("emp", emp)
Try giving this a shot.

Need column names and column values from update sql before executing

I need to know the list of the column and values from the update sql using java. Code is to read a update query and take backup of the actual column values before executing the update sql. For this is need to know the column names. Please advise!
sql = update testenv.employee set gender = '2',StudentInd = '112233' where empID in (987987);
String criteriaQuery = resultset.getString("query"); // this is the update statement which is not constant and varies everytime.
String schema = StringUtils.substringBetween(criteriaQuery.toUpperCase(), "UPDATE ", ".").trim();
String table = StringUtils.substringBetween(criteriaQuery.toUpperCase(), ".", "SET").trim();
String columnName = StringUtils.substringBetween(criteriaQuery.toUpperCase(), "SET", "=").trim();
But columnName will not get the correct columns. Need to optimise the code such that i can get the entire column names from the update query.
If you're using JDBC, you can use the following:
ResultSetMetaData md = rs.getMetaData();
after getting the result set of your select statement.
http://www.roseindia.net/jdbc/jdbc-mysql/DiscriptionTable.shtml
Provides a clear example, the same applies for SQLServer databases and Oracle.

Update single column field in table using Hibernate query

I am trying to update the single value in table (without updating any others) by using Hibernate.
Here is my code:
#Override
public void updateUser(User userDetails){
Query query = session.createQuery("UPDATE User u set u.balance = :balanceValue where u.userId = :userIdValue AND c.userType = :userTypeValue");
query.setParameter("balanceValue", userDetails.getBalance());
query.setParameter("userIdValue", userDetails.getUserId());
query.setParameter("userTypeValue", userDetails.getUserType());
query.executeUpdate();
}
Please note that all parameters I am inserting are String. Columns u.userType and u.userId are composite keys.
Caused by: java.sql.SQLException. Incorrect syntax near the keyword
"IN".
I have spent hours on understanding what is wrong with this query. I am using "User" entity for save, update criteria (writing all fields) and delete row without any problems. Thank you in advance for any help.

How to delete multiple rows from multiple tables using Where clause?

Using an Oracle DB, I need to select all the IDs from a table where a condition exists, then delete the rows from multiple tables where that ID exists. The pseudocode would be something like:
SELECT ID FROM TABLE1 WHERE AGE > ?
DELETE FROM TABLE1 WHERE ID = <all IDs received from SELECT>
DELETE FROM TABLE2 WHERE ID = <all IDs received from SELECT>
DELETE FROM TABLE3 WHERE ID = <all IDs received from SELECT>
What is the best and most efficient way to do this?
I was thinking something like the following, but wanted to know if there was a better way.
PreparedStatement selectStmt = conn.prepareStatment("SELECT ID FROM TABLE1 WHERE AGE > ?");
selectStmt.setInt(1, age);
ResultSet rs = selectStmt.executeQuery():
PreparedStatement delStmt1 = conn.prepareStatment("DELETE FROM TABLE1 WHERE ID = ?");
PreparedStatement delStmt2 = conn.prepareStatment("DELETE FROM TABLE2 WHERE ID = ?");
PreparedStatement delStmt3 = conn.prepareStatment("DELETE FROM TABLE3 WHERE ID = ?");
while(rs.next())
{
String id = rs.getString("ID");
delStmt1.setString(1, id);
delStmt1.addBatch();
delStmt2.setString(1, id);
delStmt2.addBatch();
delStmt3.setString(1, id);
delStmt3.addBatch();
}
delStmt1.executeBatch();
delStmt2.executeBatch();
delStmt3.executeBatch();
Is there a better/more efficient way?
You could do it with one DELETE statement if two of your 3 tables (for example "table2" and "table3") are child tables of the parent table (for example "table1") that have a "ON DELETE CASCADE" option.
This means that the two child tables have a column (example column "id" of "table2" and "table3") that has a foreign key constraint with "ON DELETE CASCADE" option that references the primary key column of the parent table (example column "id" of "table1"). This way only deleting from the parent table would automatically delete associated rows in the child tables.
Check out this in more detail : http://www.techonthenet.com/oracle/foreign_keys/foreign_delete.php
If you delete only few records of a large tables ensure that an index on the
column ID is defined.
To delete the records from the table TABLE2 and 3 the best strategy is to use the CASCADE DELETE as proposed by
#ivanzg - if this is not possible, see below.
To delete from TABLE1 a far superior option that a batch delete on a row basis, use signle delete using the age based predicate:
PreparedStatement stmt = con.prepareStatement("DELETE FROM TABLE1 WHERE age > ?")
stmt.setInt(1,60)
Integer rowCount = stmt.executeUpdate()
If you can't cascade delete, use for the table2 and 3 the same concept as above but with the following statment:
DELETE FROM TABLE2/*or 3*/ WHERE ID in (SELECT ID FROM TABLE1 WHERE age > ?)
General best practice - minimum logic in client, whole logic in the database server. The database should be able to do reasonable execution plan
- see the index note above.
DELETE statement operates a table per statement. However the main implementations support triggers or other mechanisms that perform subordinate modifications. For example Oracle's CREATE TRIGGER.
However developers might end up figuring out what is the database doing behind their backs. (When/Why to use Cascading in SQL Server?)
Alternatively, if you need to use an intermediate result in your delete statements. You might use a temporal table in your batch (as proposed here).
As a side note, I see not transaction control (setAutoCommit(false) ... commit() in your example code. I guess that might be for the sake of simplicity.
Also you are executing 3 different delete batches (one for each table) instead of one. That might negate the benefit of using PreparedStatement.

avoiding multiple selects when using kew word "new" in hql

I have the following code in java.
List<UserHelper> users=List<UserHelper>)session.getNamedQuery("PkUser.loadHelperUsers").list();,
I think it does not matter what the "UserHelper" class is that's why I do not write it, not to overload my question. This is my namedQuery mentioned above.
#NamedQuery(name = "PkUser.loadHelperUsers", query = "SELECT new ge.tec.pto.ext.helpers.UserHelper(u) from PkUser u order by u.pkUserId desc"),
The problem is that the hql selects too many rows, I think the same number of rows that is in database in pk_user table.If anyone knows how to fix this please inform me. It will be very nice if the solution will not require to alter my "NamedQuery", It will be graet if I will have to change only my Query creation, But any solutions will be helpful, Thank you
Multiple selects when using Key word “`new`” in `hql`
There is no problem with your code and with NEW keyword .
Your query will return all the Rows in the UserHelper related Table
You should use a WHERE clause to get the required rows .
EX :
query = "SELECT new ge.tec.pto.ext.helpers.UserHelper(u) from PkUser u where username=:passedparamer order by u.pkUserId desc"

Categories