5 Replies Latest reply on Apr 22, 2009 12:09 PM by bedek_bedkowski

    Seam persistence

      Hi,


      I've very simple problem: I want to save object in database and show it's newly create id in log.
      What I did was run this code is seam component method:


      // create object
      Car car = new Car();
      car.setName("My car");
      
      // persist object
      entityManager.persist(car);
      
      // force to insert
      entityManager.flush();
      
      // retrieve id
      log.debug("Car id: " + car.getId());



      This code works fine and object is being saved in database after executing this code but in line in which I'm trying to get object id it returns null.


      I was trying to use this code:


      entityManager.getTransaction().commit();



      but it exception:



      javax.ejb.EJBTransactionRolledbackException: A JTA EntityManager cannot use getTransaction()
        • 1. Re: Seam persistence
          brandonsimpson

          I'm still pretty new to Seam/Persistence, but from what I can tell there are a ton of ways to set up persistence and your particular setup can greatly affect the results you see. My guess is that at the time you are doing your entityManager.flush(); it's not really writing to the database but queuing it until the transaction commits (maybe in your setup, Seam is controlling the transactions), so the id hasn't been assigned yet. If you have it set up to show the SQL, do you see that executed before your log.debug()?


          As far as the entityManager.getTransaction().commit(), it sounds like you are using JTA transactions and getTransaction() is only used with resource local transactions. There is a different interface for working with JTA transactions and I think Seam even provides another API that will work with either...but I doubt you need to control the transaction to fix your issue.


          You could try doing a entityManager.refresh(car) before your log statement and see if that forces it to reload the id.

          • 2. Re: Seam persistence
            gonorrhea

            1) assuming you are using an EJB3 component (SLSB/SFSB), then by default there is a transaction required for that method (also assuming it is a business method, which means it is defined in a local/remote interface).  If you are using CMT, then the tx will commit at the end of the method.  After that time you should be able to retrieve the id of the car instance (e.g. in a JSF dataTable, etc.)


            2) If you're using CMT, then you can't use BMT (i.e. this code is illegal in that context: entityManager.getTransaction().commit();).


            for more info on this, read up on transaction semantics in JSR220...

            • 3. Re: Seam persistence

              To Brandon Simpson:


              According to your assumption:



              My guess is that at the time you are doing your entityManager.flush(); it's not really writing to the database but queuing it until the transaction commits (maybe in your setup, Seam is controlling the transactions), so the id hasn't been assigned yet. If you have it set up to show the SQL, do you see that executed before your log.debug()?

              It's not like that - I've set to show SQL and see that hibernate is showing query for database before I call log.debug to get the id, but the id is null.


              Regards,
              Adam.

              • 4. Re: Seam persistence

                To Arbi Sookazian:


                I'm calling my code in class with annotations @Name(carManage) and @Statefull - I've also tried with @Stateless.


                According to your post:



                ...If you are using CMT, then the tx will commit at the end of the method...

                I think that's the reason for null id - query is generated by hibernate but it's committed at the end of the method.


                And here is my problem - I need to know id before method finishes because I'm sending it to remote EJB. Is it possible?

                • 5. Re: Seam persistence

                  Here is resolution of this problem: add @GeneratedValue annotation to getId() of Car class - this way it's possible to retrieve id before transaction finishes.