Java with Hibernate Database - java

I have code which updates a column in a database which looks like this:
logger.info("Entering Update Method");
Query query =session.createQuery("update CardMaster cm set cm.otpAmount = :otpAmount" + " where cm.cardNumber = :cardnumber");
double otpAmount= cardMaster.getOtpAmount();
String cardNumber=cardMaster.getCardNumber();
query.setParameter("otpAmount",otpAmount);
query.setParameter("cardnumber",cardNumber);
query.executeUpdate();
logger.info("cardMasterUpdated successfully");
In this I am getting otpamount ,cardnumber and it is giving result of executeupdate as 1 but it is not reflecting in Database .. I am opening the session and committing correctly outside.
Instead of using this, if I use update() of hibernate it is happening correctly.
Can you help me out of this?

You have to commit the transaction.
Since you do not commit, nothing is visible for other processes, like the tool you are using to view your DB.
You can acquire your transaction with session.getTransaction(). However, normally you start your transaction manually like this:
Transaction tx = session.beginTransaction();
// Do your stuff
session.flush();
tx.commit()

Related

Alter Oracle session variables outside of a Hibernate transaction

We've been using a pattern like this for a while to ensure a specific operation is executed with BATCH NOWAIT, for performance reasons.
try {
session.createSQLQuery("ALTER SESSION SET COMMIT_LOGGING='BATCH' COMMIT_WAIT='NOWAIT'").executeUpdate();
// Do the operation (which also calls transaction.commit())
return callback.apply(session);
} finally {
session.createSQLQuery("ALTER SESSION SET COMMIT_LOGGING='IMMEDIATE' COMMIT_WAIT='WAIT'").executeUpdate();
}
This has worked fine in Hibernate 4. As of Hibernate 5, the last statement fails because it's not inside a transaction (as it's just been committed).
javax.persistence.TransactionRequiredException: Executing an update/delete query
It isn't an update or a delete, but executeUpdate() is the only method you can call to execute this statement without returning any rows. It shouldn't need to be in a transaction since session variables apply to the entirety of the connection, and it does need to be executed to restore the session variables because a connection pool is in use.
I've tried using one of the query methods instead, but this statement has -1 rows, and it won't let me stack SELECT 1 FROM DUAL on the end.
Is there any way to execute a native query from Hibernate that's neither update/delete or results-returning, outside of a transaction?
Using the underlying Connection directly bypasses Hibernate's checks and allows me to execute such a statement in peace.
try {
session.doWork(conn ->
conn.createStatement().execute("ALTER SESSION SET COMMIT_LOGGING='BATCH' COMMIT_WAIT='NOWAIT'")
);
return callback.apply(session);
} finally {
session.doWork(conn ->
conn.createStatement().execute("ALTER SESSION SET COMMIT_LOGGING='IMMEDIATE' COMMIT_WAIT='WAIT'")
);
}

Hibernate transaction does not commit changes to database (SQL Server)

We have a function in our application that cleans up the database and resets the data, we call a method cleanup() which at first deletes all the data from the database and then calls a sql script file to insert all the necessary default data of our application. Our application supports Oracle - MySQL and MSSQL, the function works fine on both Oracle and MySQL but doesn't work as it supposed to on MSSQL.
The problem is that it is clearing all the data from the database but not inserting the default data, the first section of the method works fine but the second section doesn't get committed to the database. Here is the function:
public boolean cleanup(...){
Session session = sessionFactory.openSession();
Transaction tx = session.beginTransaction();
// delete and drop sql queries here...
tx.commit();
session.close();
// end of first section
session = sessionFactory.openSession();
tx = session.beginTransaction();
// insert default data sql queries here...
tx.commit();
session.close();
// end of second section
}
The database gets cleared successfully, but the default data is not being inserted to the database. Please let me know what am I doing wrong here. I tried doing both delete and insert sections in one transaction with no luck.

JPA : insert and delete object in same transaction

I want to insert an object into database in a transaction and after that object is saved in the database, I'd like to delete that it once a specific operation is done. Can I restart the transaction again and perform deletion and then commit? Is this a correct way of doing it?
Example :
Employee employee = new Employee();
String name = "Ronnie";
entityManager.getTransaction.begin();
employee.setName(name);
entityManager.persist(employee);
entityManager.getTransaction.commit();
//After few steps
entityManager.getTransaction.begin();
entityManager.remove(employee);
entityManager.getTransaction.commit();
SHORT ANSWER: Yes, you can do that whithout problems.
LONG ANSWER: Yes, you can.
Every transaction is independent of any other transaction. So, if you do some operations, commit them (remember, committing a transaction execs the operations in the DB, and closes it), and then reopen it lately, it is independent of the last transaction.
You can even be in the same transaction, whithout closing it, by flushing changes to the DB:
Employee employee = new Employee();
String name = "Ronnie";
entityManager.getTransaction.begin();
employee.setName(name);
entityManager.persist(employee);
entityManager.flush();
//After few steps, the transaction is still the same
entityManager.remove(employee);
entityManager.getTransaction.commit();
The transaction isolate database state from other transactions. So you can insert and delete in the same transaction. no need to commit it.

Hibernate not executing an UPDATE query

I'm trying to setup hibernate in a project, and as part of it, I'm trying to do a simple update query just to make sure that its able to work. Here's my code:
Session sess = factory.openSession();
sess.beginTransaction();
sess.createSQLQuery("UPDATE fooTable SET bar='baz' ");
sess.getTransaction().commit();
sess.close();
When I run the code, everything executes without any error messages, and I see debug messages about getting a JDBC driver (using the config info I've provided), but the update query doesn't seem to be executed, as the table still shows the old info.
What am I doing wrong?
You created the query, but didn't execute it.
...
Query qry = sess.createSQLQuery("UPDATE fooTable SET bar='baz' ");
int updatedRows = qry.executeUpdate();
...

using Hibernate to loading 20K products, modifying the entity and updating to db

I am using hibernate to update 20K products in my database.
As of now I am pulling in the 20K products, looping through them and modifying some properties and then updating the database.
so:
load products
foreach products
session begintransaction
productDao.MakePersistant(p);
session commit();
As of now things are pretty slow compared to your standard jdbc, what can I do to speed things up?
I am sure I am doing something wrong here.
The right place to look at in the documentation for this kind of treatment is the whole Chapter 13. Batch processing.
Here, there are several obvious mistakes in your current approach:
you should not start/commit the transaction for each update.
you should enable JDBC batching and set it to a reasonable number (10-50):
hibernate.jdbc.batch_size 20
you should flush() and then clear() the session at regular intervals (every n records where n is equal to the hibernate.jdbc.batch_size parameter) or it will keep growing and may explode (with an OutOfMemoryException) at some point.
Below, the example given in the section 13.2. Batch updates illustrating this:
Session session = sessionFactory.openSession();
Transaction tx = session.beginTransaction();
ScrollableResults customers = session.getNamedQuery("GetCustomers")
.setCacheMode(CacheMode.IGNORE)
.scroll(ScrollMode.FORWARD_ONLY);
int count=0;
while ( customers.next() ) {
Customer customer = (Customer) customers.get(0);
customer.updateStuff(...);
if ( ++count % 20 == 0 ) {
//flush a batch of updates and release memory:
session.flush();
session.clear();
}
}
tx.commit();
session.close();
You may also consider using the StatelessSession.
Another option would be to use DML-style operations (in HQL!): UPDATE FROM? EntityName (WHERE where_conditions)?. This the HQL UPDATE example:
Session session = sessionFactory.openSession();
Transaction tx = session.beginTransaction();
String hqlUpdate = "update Customer c set c.name = :newName where c.name = :oldName";
// or String hqlUpdate = "update Customer set name = :newName where name = :oldName";
int updatedEntities = s.createQuery( hqlUpdate )
.setString( "newName", newName )
.setString( "oldName", oldName )
.executeUpdate();
tx.commit();
session.close();
Again, refer to the documentation for the details (especially how to deal with the version or timestamp property values using the VERSIONED keyword).
If this is pseudo-code, I'd recommend moving the transaction outside the loop, or at least have a double loop if having all 20K products in a single transaction is too much:
load products
foreach (batch)
{
try
{
session beginTransaction()
foreach (product in batch)
{
product.saveOrUpdate()
}
session commit()
}
catch (Exception e)
{
e.printStackTrace()
session.rollback()
}
}
Also, I'd recommend that you batch your UPDATEs instead of sending each one individually to the database. There's too much network traffic that way. Bundle each chunk into a single batch and send them all at once.
I agree with the answer above about looking at the chapter on batch processing.
I also wanted to add that you should make sure that you only load what is neccessary for the changes that you need to make for the product.
What I mean is, if the product eagerly loads a large number of other objects that are not important for this transaction, you should consider not loading the joined objects - it will speed up the loading of products and depending on their persistance strategy, may also save you time when making the product persistent again.
The fastest possible way to do a batch update would be to convert it to a single SQL statement and execute it as raw sql on the session. Something like
update TABLE set (x=y) where w=z;
Failing that you can try to make less transactions and do updates in batches:
start session
start transaction
products = session.getNamedQuery("GetProducs")
.setCacheMode(CacheMode.IGNORE)
.scroll(ScrollMode.FORWARD_ONLY);
count=0;
foreach product
update product
if ( ++count % 20 == 0 ) {
session.flush();
session.clear();
}
}
commit transaction
close session
For more information look at the Hibernate Community Docs

Categories

Resources