简体   繁体   中英

Correct way to use hibernate to populate a table with data

I have an Equipment table that I am trying to populate with data. The table has one auto-increment id and a manufacturer column.

I stored all the manufacturer data in a List called manufacturerList.

I then looped through the entire list and for each entry create a new Equipment object with that entry and store in a variable temp. In the same loop, I try to save temp to my table using hibernate session.

However, when I run this, I am getting this error

java.lang.IllegalStateException: Session/EntityManager is closed

What is correct way to implement this loop while using hibernate?

    SessionFactory factory = new Configuration()
            .configure("hibernate.cfg.xml")
            .addAnnotatedClass(Equipment.class)
            .buildSessionFactory();

    Session session = factory.getCurrentSession();

            try{
                   List<String> manufacturerList = new List<String>();
                   //populate the list here
                   //...

                    for (String manufacturer:manufacturerList) {
                        System.out.println(manufacturer);
                        Equipment temp = new Equipment(manufacturer);
                        session.beginTransaction();
                        session.save(temp);
                        session.getTransaction().commit();
                    }

            } catch (IOException e) {
                e.printStackTrace();
            } finally {
                factory.close();
            }

Thanks.

Playing around inserting and removing thing from the scope of the loop, I believe the correct ordering this particular implementation of hibernate using Session to ensure that session is not closed prematurely is as below:

        SessionFactory factory = new Configuration()
               .configure("hibernate.cfg.xml")
               .addAnnotatedClass(Equipment.class)
               .buildSessionFactory();

        Session session = factory.getCurrentSession();

        try{
               List<String> manufacturerList = new List<String>();
               //populate the list here
               //...

                session.beginTransaction();
                for (String manufacturer:manufacturerList) {
                    System.out.println(manufacturer);
                    Equipment temp = new Equipment(manufacturer);
                    session.save(temp);
                }
                session.getTransaction().commit();

        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            factory.close();
        }

A transaction should be started before anything is saved to session. And after all saves should the transaction be committed.

After changing to this, the program runs without error.

Please feel free to let me know if there is anything I am missing or could optimize.

You don't show how you acquire the session value. Apparently the session you have is closed, or was never opened properly, but that part of your code is not shown. Also, you show the closing of a factory but that variable is not involved in the snippet you show.

Generally you can keep an EntityManagerFactory around for a long time, but the EntityManager instances should have fairly short lifespans. Don't reuse the entity manager (or Session ) for multiple sessions; kill it after each one and start a new one when you need it. This will make it much easier to reason about what is open or closed, and will prevent the infamous session overfill.

We have to assume that Equipment is a properly declared and managed entity type, since that isn't shown here either and seems unrelated to your error message.

So the correct way to implement your loop is to initialize an EntityManager somewhere in the class that has the loop, use it for the loop, and close it some time after the loop, but to leave the EntityManagerFactory to its own logic flow.

Also, you don't "populate a table" with Hibernate or any JPA solution. Hibernate/JPA are for an object model, not a table model. Write your entity types as object types (no artificial "ID" key field!). Let JPA handle the mapping instead of your code doing it. Think objects, not tables.

Bulk operations are often better done with JDBC than JPA. JPA is for modeling entities, not managing data.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM