I am using hibernate in my automation testing project, to execute a database 'clean-up routine' that is:
disabling constraints for all tables in the database
removing records by ID's that I stored when creating records used for my automation testing
enabling constraints for all tables in the database
Here is my pseudo code:
private SessionFactory sessionFactory;
private void initialize()
{
try
{
Configuration config = createHibernateConfiguration();
addAnnotatedClassesForClientDB(config);
StandardServiceRegistryBuilder serviceRegistryBuilder = new StandardServiceRegistryBuilder();
serviceRegistryBuilder.applySettings(config.getProperties());
serviceRegistry = serviceRegistryBuilder.build();
sessionFactory = config.buildSessionFactory(serviceRegistry);
}
catch (HibernateException e)
{
logger.error("Problem creating session factory!");
e.printStackTrace();
}
}
public Session openSession()
{
Session session = sessionFactory.openSession();
session.beginTransaction();
return session;
}
public void cleanClientDatabase()
{
Session session = openSession();
try
{
logger.info("Client DB cleaning started...");
String combinedQuery = // her comes my SQL query
Query query = session.createNativeQuery(combinedQuery);
query.executeUpdate();
closeSession(session);
}
catch (Exception e)
{
logger.error("Failed cleaning Client DB! " + e.getClass().getSimpleName());
e.printStackTrace();
session.getTransaction().rollback();
session.close();
}
}
Now from time to time, it sticks at query.executeUpdate(); in cleanClientDatabase() method and will hang there forever, until I manually kill transaction in Microsoft SQL Management studio by PID.
For some reason an exception is never thrown so I can't tell what is the error, I suspect some sort of lock, what can I do to avoid this issue and fix my code?
Thank you.
Related
I have 5 tables data those needs to be saved at a same time into database.My code snippet is as below.
public boolean addStudentDetail(RegisterLoginDetail registerLoginDetail,
StudentRegisterBasicDetail studentRegisterBasicDetail, StudentBoardDetail studentBoardDetail,
StudentSchoolDetail studentSchoolDetail, StudentAdditionalDetail studentAdditionalDetail,
StepCompletionMatrix stepCompletionMatrix) {
boolean isSuceess = true;
Session session = sessionFactory.openSession();
Transaction transaction = null;
try {
transaction = session.beginTransaction();
session.saveOrUpdate(registerLoginDetail);
session.saveOrUpdate(studentRegisterBasicDetail);
session.saveOrUpdate(studentBoardDetail);
session.saveOrUpdate(studentSchoolDetail);
session.saveOrUpdate(studentAdditionalDetail);
session.saveOrUpdate(stepCompletionMatrix);
transaction.commit();
} catch (HibernateException e) {
e.printStackTrace();
session.getTransaction().rollback();
isSuceess = false;
} finally {
if (session != null && session.isOpen()) {
session.close();
}
}
return isSuceess;
}
But for my two transaction data entry for insert operation not found in StudentRegisterBasicDetail table and all other table contains entry for one common id shared between each table.My webapplication is in pilot testing mode and concurrent users are making entry through form.So I am not able to figure out for which reason my entry being skipped in that table.There is no exception log for that table entry and if exception occurs then rollback for all table should be happen or not?
Please help me...
I'm new to Hibernate. I've created the SessionFactory and obtaining the Session like below. And I'm using c3p0 connection provider
public static SessionFactory getSessionFactory() {
try {
if (sessionFactory == null) {
Configuration configuration = loadDBConfiguration();
if (configuration != null) {
sessionFactory = configuration.buildSessionFactory();
} else {
log.info("---- Configuration failed ----");
}
}
} catch (Exception ex) {
log.info("---- Initial SessionFactory creation failed ----");
}
return sessionFactory;
}
public static EntityManagerFactory getEntityManagerFactory() {
try {
Session session = getSessionFactory().openSession();
entityManagerFactory = session.getEntityManagerFactory();
} catch (Exception e) {
log.error(e);
}
return entityManagerFactory;
}
public static EntityManager getEntityManager() {
try {
EntityManagerFactory entityManagerFactory = getEntityManagerFactory();
return entityManagerFactory.createEntityManager();
} catch (Exception e) {
log.error(e);
}
return null;
}
And i'm confused with below things.
Should i close the connection after commit(), or c3p0 connection provider will close after commit().
Shall i call getEntityManager() on each request or should i use like singleton
If i'm used as singleton, then does it affect any parallel transaction.begin() or transaction.commit() if server receives multiple request at same time.
Also in singleton the entity still persist in session until it gets closed or clear manually. So what i need to do in this case.
Currently the getEntityManager() gets called in all my EntityManager Classes like UserManager, AccountsManager. After some period of time in RDS it shows like 20connections, even my application not handling any user requests.
You should close your connections. Since your connections are wrapped by the database connection pool, they will not get physically closed, but they will return to the pool. This needs to be done otherwise the connection pool will think the connections are being used and when you hit the pool limit, no new connections will be open.
Keep the session factory as a singleton. You should open a new session for each thread.
I am working in java hibernate and mysql. I want to use transaction settimeout for a payment functionality of application. I just test the code as below for settimeout to work.
Transaction tx = (Transaction) threadTransaction.get();
try {
if (tx == null) {
Session session = (Session) threadSession.get();
session.getTransaction().setTimeout(5);
tx=session.beginTransaction();
try {
Thread.sleep(6000);
} catch (InterruptedException e) {
e.printStackTrace();
}
if(session.getTransaction().isActive()) {
System.out.println("session active");
}
else {
System.out.println("session inactive");
}
threadTransaction.set(tx);
}
}
catch (HibernateException e) {
throw new HibernateException("", e);
}
But it print session active, means the timeout doesnt work. What is the reason? please help !
Hibernate is pretty good at doing nothing as long as nothing needs to be done (efficiency and such). I think that is what your test shows, not that the the timeout is not working for what it was intended to do:
"... ensuring that database level deadlocks and queries with huge result sets are limited by a defined timeout."
Also note that "setTimeout() cannot be called in a CMT bean ..."
Test the transaction timeout with some code that does what the transaction timeout was intended for and I think you'll find it working properly.
My web application used hibernate mysql. I can add records to database without having any issue. But if i going to update latest adding record It will not updating. But if I re-start the server(tomcat) and then try to update It's working.
To update the record following condition should be satisfied.
//Check record aready exist
public boolean idExists(String id) {
Session session = (Session) HibernateUtil.getSessionFactory().getCurrentSession();
session.beginTransaction();
List<Officer> list = (List<Officer>) session.createQuery("from Officer as p where p.idno =" + "\'" + id.trim() + "\'").list();
return (list.size() > 0) ;
}
Immediate(return 1) adding records It will returns 0. But one restart the server and update the record It will work. I also verify after adding record it's successfully commit to DB.
public class HibernateUtil {
private static final SessionFactory sessionFactory;
static{
try{
sessionFactory = new AnnotationConfiguration().configure().buildSessionFactory();
}catch(Throwable ex){
System.err.println("Initial SessionFactory creation failed." + ex);
throw new ExceptionInInitializerError(ex);
}
}
public static SessionFactory getSessionFactory() {
return sessionFactory;
}
}
Let me know if something wrong in my code?
Hibernate does not interact with database immediately after transaction or it does at the time of flushing session, it manages and updates its record to increase system performance in its own way, If you want immediate reflection use :
session.flush();
After updating records.
You could try to flush the session. Entities are not immediately persisted into the database.
session.flush();
I think better you use Transactions here.
You put session.biginTranasaction();
Instead do something like,
public boolean idExists(String id) {
Session session = (Session) HibernateUtil.getSessionFactory().getCurrentSession();
Transaction tx = session.beginTransaction();
List<Officer> list = (List<Officer>) session.createQuery("from Officer as p where p.idno =" + "\'" + id.trim() + "\'").list();
tx.commit();
if(session != null){
session.close();
}
return (list.size() > 0) ;
}
On other end you should generate new session and do other stuffs.
In Hibernate when i save() an object in a transaction, and then i rollback it, the saved object still remains in the DB. It's strange because this issue doesn't happen with the update() or delete() method, just with save().
Here is the code i'm using:
DbEntity dbEntity = getDbEntity();
HibernateUtil.beginTransaction();
Session session = HibernateUtil.getCurrentSession();
session.save(dbEntity);
HibernateUtil.rollbackTransaction();
And here is the HibernateUtil class (just the involved functions, i guarantee the getSessionFactory() method works well - there is an Interceptor handler, but it doesn't matter now):
private static final ThreadLocal<Session> threadSession = new ThreadLocal<Session>();
private static final ThreadLocal<Transaction> threadTransaction = new ThreadLocal<Transaction>();
/**
* Retrieves the current Session local to the thread.
* <p/>
* If no Session is open, opens a new Session for the running thread.
*
* #return Session
*/
public static Session getCurrentSession()
throws HibernateException {
Session s = (Session) threadSession.get();
try {
if (s == null) {
log.debug("Opening new Session for this thread.");
if (getInterceptor() != null) {
log.debug("Using interceptor: " + getInterceptor().getClass());
s = getSessionFactory().openSession(getInterceptor());
} else {
s = getSessionFactory().openSession();
}
threadSession.set(s);
}
} catch (HibernateException ex) {
throw new HibernateException(ex);
}
return s;
}
/**
* Start a new database transaction.
*/
public static void beginTransaction()
throws HibernateException {
Transaction tx = (Transaction) threadTransaction.get();
try {
if (tx == null) {
log.debug("Starting new database transaction in this thread.");
tx = getCurrentSession().beginTransaction();
threadTransaction.set(tx);
}
} catch (HibernateException ex) {
throw new HibernateException(ex);
}
}
/**
* Rollback the database transaction.
*/
public static void rollbackTransaction()
throws HibernateException {
Transaction tx = (Transaction) threadTransaction.get();
try {
threadTransaction.set(null);
if ( tx != null && !tx.wasCommitted() && !tx.wasRolledBack() ) {
log.debug("Tyring to rollback database transaction of this thread.");
tx.rollback();
}
} catch (HibernateException ex) {
throw new HibernateException(ex);
} finally {
closeSession();
}
}
Thanks
Check if your database supports a roll back i.e. if you're using InnoDB tables and not MyISAM (you can mix transactional and non-transactional tables but in most cases, you want all your tables to be InnoDB).
MySQL by default uses the MyIsam storage engine. As the MyISAM does not support transactions, insert, update and delete statements are directly written to the database. The commit and rollback statements are ignored.
In order to use transaction you need to change the storage engine of you tables. Use this command:
ALTER TABLE table_name ENGINE = InnoDB;
(note how ever, that the two storage engines are different and you need to test you're application if it still behaves as expected)