2

I'm using EclipseLink (JPA 2.0) on Netbeans 7.0 with a MySQL database - which I configured according to this screencast. But sometimes when I persist an Object/Entity my table get's cleared before that object persists, and I get a table with only this object (like it has been cleared). I'm only simply adding new entries in (populating) the database.

How can I prevent this?

Here's my code:

Movie movie = new Movie(
    jsondata.path("Title").getTextValue(),
    jsondata.path("Year").getValueAsInt(),
    jsondata.path("Genre").getTextValue(),
    jsondata.path("Plot").getTextValue(),
    jsondata.path("Poster").getTextValue());
persist(movie);

My persist() function:

public static void persist(Object object) {
    EntityManagerFactory emf = Persistence.createEntityManagerFactory("AllmoviesPU");
    EntityManager em = emf.createEntityManager();
    em.getTransaction().begin();
    try {
        em.persist(object);
        em.getTransaction().commit();
    } catch (Exception e) {
        e.printStackTrace();
        em.getTransaction().rollback();
    }
    em.close();
}

My Movie object/entity:

@Entity
public class Movie implements Serializable {
    private static final long serialVersionUID = 1L;
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    private String title;
    @Column(name="MOVIEYEAR")
    private int year;
    private String genre;
    private String synopsis;
    private String image;

    public Movie(String title, int year, String genre, String synopsis, String image) {
        this.title = title;
        this.year = year;
        this.genre = genre;
        this.synopsis = synopsis;
        this.image = image;
    }

    public Movie() {
    }

    /* ... Getters and Setters stuff ... */

}

My persistence.xml:

<?xml version="1.0" encoding="UTF-8"?>
<persistence version="2.0" xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd">
  <persistence-unit name="AllmoviesPU" transaction-type="RESOURCE_LOCAL">
    <provider>org.eclipse.persistence.jpa.PersistenceProvider</provider>
    <class>allmovies.data.Movie</class>
    <properties>
      <property name="javax.persistence.jdbc.url" value="jdbc:mysql://123.123.123.123:3306/psanta_allmovies"/>
      <property name="javax.persistence.jdbc.password" value="XXXXXX"/>
      <property name="javax.persistence.jdbc.driver" value="com.mysql.jdbc.Driver"/>
      <property name="javax.persistence.jdbc.user" value="psanta_allmovies"/>
    </properties>
  </persistence-unit>
</persistence>
guido
  • 18,864
  • 6
  • 70
  • 95
pedrosanta
  • 244
  • 1
  • 8
  • 14
  • 1
    Have you posted this question before somewhere else? Complete with (working!!) DB login settings *en public*? Couldn't it just be some joker which truncated your table from time to time? Try to change your password and don't post the DB connection details in the world wide web... – BalusC May 19 '11 at 02:59

2 Answers2

3

Try turning on logging to FINEST or FINE to see what is occurring. ("eclipselink.logging.level"="finest").

EclipseLink does have an option to recreate tables on startup ("eclipselink.ddl-generation"="drop-and-create-tables"), ensure you are not using that. NetBeans or Glassfish may be setting this by default, I think they may do this when in development mode.

James
  • 17,965
  • 11
  • 91
  • 146
2

There are bunch of things that need to be addressed in your code, although I cannot guarantee they are related to your problem.

The first thing is that creating your entity manager factory and your entity manager every time you simply want to persist an entity is way too expensive. Also, you are not closing your entity manager factory.

The right way to do it is, create an entity manager factory and keep it available for the entire life of your application. Every time you start a conversation with your user (i.e. a transaction) then request from it a entity manager, use it to persist everything you want to persist and then close the entity manager.

When your application finishes, close the entity manager factory.

A second aspect that you might like to take into account is that certain exceptions already imply a rollback, for instance, any exeception thrown during commit execution. Therefore if you attempt a second rollback, then you will get a second exception which you are not handling.

I cannot guarantee anything of these changes would solve your problem, but they are certainly a good start.

That being said, it is not evident for me, from your code, where you are persisting more than one entity. I guess, more context is required.

I'd suggest somewhat like this:

public class DataAccessLayer {

    private EntityManagerFactory emf;

    public DataAccessLayer (){
    }

    public synchronized void start(){
       if(isStarted())
         throw new IllegalStateException("Already started");
       this.emf = Persistence.createEntityManagerFactory("AllmoviesPU");
    }

    public synchronized void stop(){
       if(!isStarted())
         throw new IllegalStateException("Not started");
       this.emf.close();
       this.emf = null;
    }

   public synchronized boolean isStarted(){
     return this.emf != null;
   }

    public void doPersistenceStuff(InputData o){
            if(!isStarted())
              throw new IllegalStateException("Not started");
        EntityManager em = emf.getEntityManager();
        EntityTransaction t = entityManager.getTransaction();
        try {
            t.begin();
            //do persistence stuff here
            t.commit();
        }
        catch (RollbackException e) {
            //transaction already rolledback
            throw new MyPersistenceException(e);
        }
        catch (Exception e) {
            t.rollback(); //manual rollback
            throw new MyPersistenceException(e);
        }
        em.close()
    }
}

And you can make sure the emf is closed when your application is finished (like when the user clicks the exit button, or when your server stops or shuts down) by invoking the stop() method in the data access layer instance.

Edwin Dalorzo
  • 76,803
  • 25
  • 144
  • 205
  • Consider that I run the same code when I want to persist another Entity/Object. Ok, thanks for the Factory tip. I'll try that. – pedrosanta May 18 '11 at 16:59
  • I run the code now while closing the Factory at the exit and the behavior is the same: table clears sometimes. – pedrosanta May 18 '11 at 17:05
  • Please, clarify, are you creating a global entity manager factory, or a you still creating a entity manager factory every time you persist? It is of paramount importance that you create a single entity manager factory for your application and that you reuse it every time you want to persist, and not create a new one very time. – Edwin Dalorzo May 18 '11 at 17:13
  • I'm creating a global factory as you told, that I close when I exit the program - a console application. But the problem still persists. – pedrosanta May 18 '11 at 17:30
  • @pedrosante Can you update your post with more contextual code from the place where you are actually invoking the persist method? I have updated my post as well with a few more recommendations. – Edwin Dalorzo May 18 '11 at 17:34