Search code examples
javahibernatepersistencespring-roo

Persist a collection of data to a lazy collection in Spring Framework


ds_schema I'm newbie in Spring. The picture above shows my db schema:

I need to download a new real time data for each station each minute and I have to assign it to that station. I would like to manage to:

  1. persist
  2. without the use of FetchType.EAGER (which resulted to be too much slow for this purpose)
  3. persist in a single time (i.e a single communication with db, without iterating on a list the persist function on each single RealTimeData) the collection of RealTimeData collected in the previous minute.

This is what I would like to do, if I should take a completely different way for doing something like that any advice is appreciated.

The station class is this:

@RooJavaBean
@RooToString
@RooJpaActiveRecord(finders = { "findStationsByNum" })
@RooJson
public class Station {

    private String address;
    private String name;
    private Integer num;
    @ManyToOne(cascade = CascadeType.ALL)
    private Location location;
    @ManyToOne
    private City city;
    @OneToMany(cascade = CascadeType.ALL, mappedBy = "station", fetch=FetchType.LAZY)
    private Set<RealTimeData> real_time_data = new HashSet<RealTimeData>();

}

And the RealTimeData class is this:

@RooJavaBean
@RooToString
@RooJpaActiveRecord(finders = { "findRealTimeDatasByCollect_dateEquals" })
@RooJson
public class RealTimeData {

    private Integer available_bike_stands;
    /* ... ... ... */
    @Temporal(TemporalType.TIMESTAMP)
    @DateTimeFormat(style = "M-")
    private Date collect_date;
    @ManyToOne
    private Station station;
}

Solution

  • You can read the details of the solution here: http://forum.spring.io/forum/spring-projects/roo/106714-bulk-operations-with-spring-roo

    However synthesizing it suggests to use this:

    @PersistenceContext
    private EntityManager entityManager;
    
    @Transactional
    public void storeList(List<MyEntity> entities) {
      int imported = 0;
      for (MyEntity e: entities) {
        entityManager.persist(e);
        if (++imported % 50 == 0) {
          entityManager.flush();
          entityManager.clear();
        }
      }
    }
    

    Or if you are using Spring Roo this:

    @Transactional
    public void storeList(List<MyEntity> entities) {
        int imported = 0;
        for (MyEntity e: entities) {
            e.persist();
            if (++imported % 50 == 0) {
                e.flush();
                e.clear();
            }
        }
    }
    

    Setting in the property of your persistence.xml:

    <property name="hibernate.jdbc.batch_size" value="50"/>