简体   繁体   中英

Hibernate Batch Save Nested Objects

I have the below class structure:

class A{
    int id;
    List<B> blist;
    List<C> clist;
    List<D> dlist;
}

I get a json as an input which is mapped to object A by a mapper. Now, i have object A which has the list of B,C and D objects. I want to use batching to save the insert time taken. I went through the documentation which describes the solution if I want to save multiple parent objects. How would I use the batching capability in my case which has nested list of objects of multiple type.

I have enabled batch inserts using

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

This by itself doesnt give me any batching unless I clear and flush the session. Any suggestions on how do I go about with this?

The problem is that you're using IDENTITY strategy.

Whenever you save a new entity, Hibernate will place it into the Session's 1LC; however, in order to do that the identifier must be known. The problem with IDENTITY strategy is that Hibernate must actually perform the insert to determine the identifier value.

In the end, batch insert capabilities are disabled.

You should either try to load your data using business key values that are known up front or worse case use SEQUENCE generation type with a sequence optimizer to minimize the database hit. This will allow batch inserts to work.

UPDATE

For situations where you have no business key that defines the uniqueness for a row and your database doesn't have SEQUENCE support, you could manage the identifiers yourself. You can either elect to do this using a custom identifier generator or just doing this in your loop as code.

The caveat here is that this solution is not thread-safe . You should guarantee that at no point would you ever be running this logic in two threads simultaneously, which is typically not something one does anyway with bulk data loads.

  1. Define a variable to store your identifier in. We will need to initialize this variable based on the existing max value of the identifier in the database. If no rows in the database exist, we likely will want to initialize it as 1.

     Long value = ... // createQuery ( "SELECT MAX(id) FROM YourEntity" ) value = ( value == null ? 1L : value + 1); 
  2. The next step is to change the @Id annotated field. It should not be marked as @GeneratedValue since we're going to allow the application to provide the value.

  3. For each row you're going to insert, simply call your #setId( value ) method with the value variable generated from step 1.

  4. Increment your value variable by 1.

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