Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Play! framework immediate save?

In Play! if you call this:

void method()
{
User u = User();
u.name = "bob";
u.save();
while(true){/* endless loop */}
}

Nothing will actually be saved into the db (The Play! class needs to get the hand back to flush the saves.)

How do I have to proceed in order to either force a flush or to make it automatically flush at save ?

like image 246
Flavien Volken Avatar asked Dec 13 '11 11:12

Flavien Volken


3 Answers

The reason why your changes are not visible in the database, is that the transaction is not yet commited and so other transactions can't see your changes (at least in a good database like PostgreSQL, Oracle, MSSQL, DB2). To make your changes seen, you'll have to commit your transaction before it enters the infinite loop, like this:

void method()
{
    User u = User();
    u.name = "bob";
    u.save();
    JPA.em().flush();
    JPA.em().getTransaction().commit();

    while(true){/* endless loop */}

}

If you want to access your database inside the infinite loop or after it (if you have a break condition), you'll have to begin a new transaction or you'll get exceptions from hibernate. Do this like this

void method()
{
    User u = User();
    u.name = "bob";
    u.save();
    JPA.em().flush();
    JPA.em().getTransaction().commit();

    while(true){
      // do some stuff

      /* TRANSACTIONAL BLOCK BEGINS */
      JPA.em().getTransaction().begin();
      try{
          // do some stuff
          // fetching, updating, deleting, whatever

          JPA.em().getTransaction().commit();
      }
      catch (Exception e)
      {
          // if an error occurs, rollback the transaction
          JPA.em().getTransaction().rollback();
      }
      /* TRANSACTIONAL BLOCK ENDS */
      // do some other stuff
    }
   // copy the TRANSACTIONAL BLOCK from above, if you want to do stuff after the "infinite loop" as well.
}

It's important that you either commit or rollback the transaction in the loop, if you start it there, as else you'll run into problems with too many open transactions soon.

like image 151
Dominik Dorn Avatar answered Jan 01 '23 10:01

Dominik Dorn


As already said by Andrei Bodnarescu, you can use JPA.em().flush() or User.em().flush() to flush persistence context explicitly.

Note, however, that doing so won't make the saved entity immediately available to other transactions, since the current transaction should be committed first. You can commit the current transaction as JPA.em().getTransaction().commit().

like image 20
axtavt Avatar answered Jan 01 '23 10:01

axtavt


Try

User.em().flush();

If I'm not mistaken, the default Play! model holds a refference to the EntityManager which can be accessed like that.

like image 35
Shivan Dragon Avatar answered Jan 01 '23 09:01

Shivan Dragon