Add failing testcases for wrong order in batch save and possible fix for one of them

This commit is contained in:
Roland Praml
2021-09-16 16:52:20 +02:00
parent b262c2e19d
commit bf62efd220
5 changed files with 252 additions and 10 deletions
@@ -29,8 +29,6 @@ import java.util.List;
*/
public final class BatchControl {
private static final Object DUMMY = new Object();
/**
* Used to sort queue entries by depth.
*/
@@ -52,7 +50,7 @@ public final class BatchControl {
* Set of beans in this batch. This is used to ensure that a single bean instance is not included
* in the batch twice (two separate insert requests etc).
*/
private final IdentityHashMap<Object, Object> persistedBeans = new IdentityHashMap<>();
private final IdentityHashMap<Object, String> persistedBeans = new IdentityHashMap<>();
/**
* Helper to determine statement ordering based on depth (and type).
@@ -181,15 +179,22 @@ public final class BatchControl {
* Add the request to the batch and return true if we should flush.
*/
private boolean addToBatch(PersistRequestBean<?> request) {
Object alreadyInBatch = persistedBeans.put(request.entityBean(), DUMMY);
int depth = transaction.depth();
BeanDescriptor<?> desc = request.descriptor();
// batching by bean type AND depth
String key = desc.rootName() + ":" + depth;
String alreadyInBatch = persistedBeans.put(request.entityBean(), key);
if (alreadyInBatch != null) {
// special case where the same bean instance has already been
// added to the batch (doesn't really occur with non-batching
// as the bean gets changed from dirty to loaded earlier)
return false;
BatchedBeanHolder beanHolder = getBeanHolder(request, alreadyInBatch);
int ordering = depthOrder.orderingFor(depth);
return beanHolder.getOrder() > ordering;
}
BatchedBeanHolder beanHolder = getBeanHolder(request);
BatchedBeanHolder beanHolder = getBeanHolder(request, key);
int bufferSize = beanHolder.append(request);
bufferMax = Math.max(bufferMax, bufferSize);
@@ -342,14 +347,11 @@ public final class BatchControl {
* Return an entry for the given type description. The type description is
* typically the bean class name (or table name for MapBeans).
*/
private BatchedBeanHolder getBeanHolder(PersistRequestBean<?> request) {
private BatchedBeanHolder getBeanHolder(PersistRequestBean<?> request, String key) {
int depth = transaction.depth();
BeanDescriptor<?> desc = request.descriptor();
// batching by bean type AND depth
String key = desc.rootName() + ":" + depth;
BatchedBeanHolder batchBeanHolder = beanHoldMap.get(key);
if (batchBeanHolder == null) {
int ordering = depthOrder.orderingFor(depth);