I can't save all rows from my file Excel in database, because i get this error :
Exception in thread "main" org.hibernate.SessionException: Session is closed!
My code :
AnnotationConfiguration conf = new AnnotationConfiguration();
conf.addAnnotatedClass(Etudiant.class);
conf.configure("hibernate.cfg.xml");
new SchemaExport(conf).create(true, true);
SessionFactory factory = conf.buildSessionFactory();
Session session = factory.getCurrentSession();
for(int i=3;i<tab.length;i++){
session.beginTransaction();
etudiant.setNom(tab[i]);
i++;
etudiant.setPrenom(tab[i]);
i++;
etudiant.setAge(tab[i]);
session.save(etudiant);
session.getTransaction().commit();
}
Anyone have an idea plz ?
You are fulling up your first level cache. Clearing and flushing the cache periodically should be considered when your are doing a bulk insert. Also committing in each iteration slow down the insertion.
You have to do something like this..
13.1. Batch inserts
When making new objects persistent flush() and then clear() the sessionregularly in order to control the size of the first-level cache.
Session session = sessionFactory.openSession();
Transaction tx = session.beginTransaction();
for ( int i=0; i<100000; i++ ) {
Customer customer = new Customer(.....);
session.save(customer);
if ( i % 20 == 0 ) { //20, same as the JDBC batch size
//flush a batch of inserts and release memory:
session.flush();
session.clear();
}
}
tx.commit();
session.close();
You need to start a Session with factory.openSession() before you can use the current Session.
Related
I'm trying to save bulk data in to the table
while saving I'm facing the issue like
illegally attempted to associate a proxy with two open Sessions
Session session = sessionFactory.openSession();
Transaction transaction = session.beginTransaction();
for (Object obj : ObjectList) {
session.save(obj );
}
transaction.commit();
session.close();
}
I saw this issue while updating the records but now it is getting for save is there any solution.
Here you can flush a batch of inserts and release memory:
for more information you can refer hibernate doc on batch processing.
int count=0;
for (Object obj : ObjectList) {
session.save(obj );
//20, same as default the JDBC batch size
if ( ++count % 20 == 0 ) {
session.flush();
session.clear();
}
}
transaction.commit();
session.close();
I have a requirement where I am updating rows according to uuid's where one uuid may be associated to more than one rows.
Here's the scenario:
4a90558c-4a5b-4af7-8c68-60ff81f74ef3 is my uuid and it exists in 8 columns in my DB.
and my java code is as follows:
try{
session = sessionFactory.getCurrentSession();
tx = session.getTransaction();
criteria = session.createCriteria(Archive.class);
criteria.add(Restrictions.eq("bagUuid", "4a90558c-4a5b-4af7-8c68-60ff81f74ef3"));
ScrollableResults items = criteria.scroll();
while ( items.next() ) {
Archive archive = (Archive)items.get(0);
archive.setDecision(1);
archive.setOperatorAssigned("test");
session.saveOrUpdate(archive);
session.flush();
session.clear();
}
tx.commit();
LOGGER.info("Archive Record is updated: "+archive.getFilePath());
}catch(Exception e){
recordUpdated = false;
tx.rollback();
LOGGER.error("Archive Record failed to update due to exception in updateArchiveRecord method: "+e.getMessage());
}
Here sometimes all records associated to UUID is updating but sometimes failing.
I think it may be a issue with the Hibernate API.
Does anybody else has faced the same issue.
This line looks suspicious:
Archive archive = (Archive)items.get(0);
It means thart regardless of the number of items in the ScrollableResults, you will be updating only the first Archive object. If I understood what you are trying to do correctly, it should be a current record:
Archive archive = (Archive)items.get();
Also, I'd move out/delete session.flush() and session.clear(). The final code would look like this:
try{
session = sessionFactory.getCurrentSession();
tx = session.getTransaction();
criteria = session.createCriteria(Archive.class);
criteria.add(Restrictions.eq("bagUuid", "4a90558c-4a5b-4af7-8c68-60ff81f74ef3"));
ScrollableResults items = criteria.scroll();
while ( items.next() ) {
Archive archive = (Archive)items.get();
archive.setDecision(1);
archive.setOperatorAssigned("test");
session.saveOrUpdate(archive);
}
tx.commit();
session.close();
LOGGER.info("Archive Record is updated: "+archive.getFilePath());
}catch(Exception e){
recordUpdated = false;
tx.rollback();
LOGGER.error("Archive Record failed to update due to exception in updateArchiveRecord method: "+e.getMessage());
}
Slava Imeshev
Here is the code example from Hibernate about batch processing:
Session session = sessionFactory.openSession();
Transaction tx = session.beginTransaction();
for ( int i=0; i<100000; i++ ) {
Customer customer = new Customer(.....);
session.save(customer);
if ( i % 20 == 0 ) { //20, same as the JDBC batch size
//flush a batch of inserts and release memory:
session.flush();
session.clear();
}
}
tx.commit();
session.close();
At the beginning of codes, it uses openSession().However, when i wrote my code, i use getCurreentSession(). It seems like it will generate org.hibernate.TransactionException: nested transactions not supported error.
Could anybody explain why this happens?
SessionFactory.openSession() always opens a new session that you have to close once you are done with the operations. SessionFactory.getCurrentSession() returns a session bound to a context - you don't need to close this.
The error code like
org.hibernate.TransactionException: nested transactions not supported
at org.hibernate.engine.transaction.spi.AbstractTransactionImpl.begin(AbstractTransactionImpl.java:152)
at org.hibernate.internal.SessionImpl.beginTransaction(SessionImpl.java:1426)
at roseindia.PersonDetail.main(PersonDetail.java:16)
This is my code
Session session = HibernateUtil.getSessionFactory().openSession();
session.beginTransaction();
Person person = new Person();
System.out.println("Inserting Record");
session.beginTransaction();
person.setId(1);
person.setName("Jeff");
session.save(person);
session.getTransaction().commit();
System.out.println("Done");
session.close();
I didn't begin transaction before commit the old one.
What happened?
You are starting transaction twice (at second line and sixth one).
That's why you have this error. With your configuration you cannot create transaction in transaction.
Why is this giving me a lock timeout:
for(int i = 0; i < playersCount ; i++) {
StatUser stats = (StatUser) selectedUsers.get(i).getStatUsers().iterator().next();
int gc = stats.getGamesPlayed();
int gm = stats.getMakeCount();
Session session = HibernateUtil.getSessionFactory().getCurrentSession();
Transaction tx = session.beginTransaction();
if(i == winnerIndex) {
stats.setGamesPlayed(gc++);
stats.setMakeCount(gm++);
session.update(stats);
session.flush();
tx.commit();
customTextBean.sendMail(selectedUsers.get(i).getEmail(), "Tillykke du har vundet");
}
else {
stats.setGamesPlayed(gc++);
session.update(stats);
session.flush();
tx.commit();
customTextBean.sendMail(selectedUsers.get(i).getEmail(), "Tillykke " + winnersName + " skal lave kaffe");
}
}
If you create a new transaction (session.beginTransaction();), then a new DB connection is created. So you have a transaction which has a read-lock on stats (from the for loop) and inside of that you try to write to the same row -> Deadlock.
To fix that, you first fetch all StatUsers with a second loop, close the first transaction and then iterate over the result in the code above. If you can't do that because you run out of memory, then Hibernate is no longer your friend and you must use custom SQL.
Other solutions: Use optimistic locking or read the data to be changed with custom SQL and instantiate the objects in the loop.