In a Java/Hibernate Application I have two classes `Cat` and `Kitten` in a bidirectional relation as depict below:

```
public class Cat {
  ...
  @OneToMany(mappedBy="cat", fetch = FetchType.LAZY)
  @OnDelete(action = OnDeleteAction.CASCADE)
  @LazyCollection(LazyCollectionOption.EXTRA)
  @Getter
  @Setter
  private List<Kitten> kittens = new LinkedList();
  public void addKitten(Kitten k) {
    kittens.add(k);
  }
  ...
}  

public class Kitten {
  ...   
  @ManyToOne(fetch=FetchType.LAZY)
  @Getter
  @Setter
  private Cat cat;
  ...
}

```

In a huge for-loop 20000 `Kitten` are added to different `Cat` entities which were created previously. The important code in the for-loop looks like this:

```
....
Kitten k = new Kitten();
k.setAttribut("foo");
k.setCat(currentCat);     // (a) line
currentCat.addKitten(k);  // (b) line
daoFactory.getKittenDao().save(k);
...

```

The code is working, but somehow the performance is very slow. In a previous iteration (uni-directional) the application was much faster. Since the final version should work on 1000000 `Kitten` there must be a way to improve. If I benchmark the time for the code above, it takes approximately 40 seconds. If I simulate uni-direction by removing line (a) or (b), it takes 10 seconds in both cases (but crahes later if I access the objects).

So my question is:
Do I miss something, or is the internal maintenance of bidirectional relations very slow in Hibernate? Since the simulates uni-direction is much faster, I would expect a runtime of approximately 15 seconds for the bidirection.

**Update:**

The code saving the entities is inside a SAX-Parser DefaultHandler implementation. Thus, while parsing the XML structure, first a `Cat` is saved in the `startElement()` function and later on the `Kitten` will be saved in another `startElement()` call. 
Regarding the suggestions/questions by @Bartun: I had a look into batching. The problem is, by using DAOs and the `startElement()` functions, it is hard to tell, when exactly 50 Entities have been saved to flush the session. A counter could do the trick though. However, it does not explain the performance impact by establishing the bidirection.
As Transaction management Spring `@Transactional` is used on the function starting the XML parsing.