Skip to content

Commit 25b8270

Browse files
committed
#250 avoid collection creation or index creation inside transaction
1 parent b9b48d3 commit 25b8270

File tree

1 file changed

+34
-28
lines changed

1 file changed

+34
-28
lines changed

src/main/java/com/arangodb/springframework/core/template/ArangoTemplate.java

Lines changed: 34 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@
5757
import org.springframework.context.expression.BeanFactoryAccessor;
5858
import org.springframework.context.expression.BeanFactoryResolver;
5959
import org.springframework.dao.DataAccessException;
60+
import org.springframework.dao.InvalidDataAccessResourceUsageException;
6061
import org.springframework.dao.support.DataAccessUtils;
6162
import org.springframework.dao.support.PersistenceExceptionTranslator;
6263
import org.springframework.data.domain.Persistable;
@@ -155,30 +156,33 @@ private DataAccessException translateExceptionIfPossible(final RuntimeException
155156
return exceptionTranslator.translateExceptionIfPossible(exception);
156157
}
157158

158-
private ArangoCollection _collection(final String name) {
159-
return _collection(name, null, null);
159+
private ArangoCollection _collection(final String name, boolean transactional) {
160+
return _collection(name, null, null, transactional);
160161
}
161162

162-
private ArangoCollection _collection(final Class<?> entityClass) {
163-
return _collection(entityClass, null);
163+
private ArangoCollection _collection(final Class<?> entityClass, boolean transactional) {
164+
return _collection(entityClass, null, transactional);
164165
}
165166

166-
private ArangoCollection _collection(final Class<?> entityClass, final Object id) {
167+
private ArangoCollection _collection(final Class<?> entityClass, final Object id, boolean transactional) {
167168
final ArangoPersistentEntity<?> persistentEntity = converter.getMappingContext()
168169
.getRequiredPersistentEntity(entityClass);
169170
final String name = determineCollectionFromId(id).orElse(persistentEntity.getCollection());
170-
return _collection(name, persistentEntity, persistentEntity.getCollectionOptions());
171+
return _collection(name, persistentEntity, persistentEntity.getCollectionOptions(), transactional);
171172
}
172173

173174
private ArangoCollection _collection(final String name, final ArangoPersistentEntity<?> persistentEntity,
174-
final CollectionCreateOptions options) {
175+
final CollectionCreateOptions options, boolean transactional) {
175176

176177
final ArangoDatabase db = db();
177178
final Class<?> entityClass = persistentEntity != null ? persistentEntity.getType() : null;
178179
final CollectionCacheValue value = collectionCache.computeIfAbsent(new CollectionCacheKey(db.name(), name),
179180
key -> {
180181
final ArangoCollection collection = db.collection(name);
181182
if (!collection.exists()) {
183+
if (transactional) {
184+
throw new InvalidDataAccessResourceUsageException("Missing collection cannot be created during transaction");
185+
}
182186
collection.create(options);
183187
}
184188
return new CollectionCacheValue(collection);
@@ -187,7 +191,9 @@ private ArangoCollection _collection(final String name, final ArangoPersistentEn
187191
final ArangoCollection collection = value.getCollection();
188192
if (persistentEntity != null && !entities.contains(entityClass)) {
189193
value.addEntityClass(entityClass);
190-
ensureCollectionIndexes(collection(collection), persistentEntity);
194+
if (!transactional) {
195+
ensureCollectionIndexes(collection(collection), persistentEntity);
196+
}
191197
}
192198
return collection;
193199
}
@@ -334,14 +340,14 @@ public ArangoDBVersion getVersion() throws DataAccessException {
334340
@Override
335341
public <T> ArangoCursor<T> query(final String query, final Map<String, Object> bindVars,
336342
final AqlQueryOptions options, final Class<T> entityClass) throws DataAccessException {
337-
return db().query(query, bindVars == null ? null : prepareBindVars(bindVars), options, entityClass);
343+
return db().query(query, bindVars == null ? null : prepareBindVars(bindVars, false), options, entityClass);
338344
}
339345

340-
private Map<String, Object> prepareBindVars(final Map<String, Object> bindVars) {
346+
private Map<String, Object> prepareBindVars(final Map<String, Object> bindVars, boolean transactional) {
341347
final Map<String, Object> prepared = new HashMap<>(bindVars.size());
342348
for (final Entry<String, Object> entry : bindVars.entrySet()) {
343349
if (entry.getKey().startsWith("@") && entry.getValue() instanceof Class) {
344-
prepared.put(entry.getKey(), _collection((Class<?>) entry.getValue()).name());
350+
prepared.put(entry.getKey(), _collection((Class<?>) entry.getValue(), transactional).name());
345351
} else {
346352
prepared.put(entry.getKey(), toVPack(entry.getValue()));
347353
}
@@ -357,7 +363,7 @@ public MultiDocumentEntity<? extends DocumentEntity> delete(final Iterable<Objec
357363

358364
MultiDocumentEntity<? extends DocumentEntity> result;
359365
try {
360-
result = _collection(entityClass).deleteDocuments(toVPackCollection(values), entityClass, options);
366+
result = _collection(entityClass, options.getStreamTransactionId() != null).deleteDocuments(toVPackCollection(values), entityClass, options);
361367
} catch (final ArangoDBException e) {
362368
throw translateExceptionIfPossible(e);
363369
}
@@ -374,7 +380,7 @@ public DocumentEntity delete(final Object id, final Class<?> entityClass, final
374380

375381
final DocumentEntity result;
376382
try {
377-
result = _collection(entityClass, id).deleteDocument(determineDocumentKeyFromId(id), entityClass, options);
383+
result = _collection(entityClass, id, options.getStreamTransactionId() != null).deleteDocument(determineDocumentKeyFromId(id), entityClass, options);
378384
} catch (final ArangoDBException e) {
379385
throw translateExceptionIfPossible(e);
380386
}
@@ -391,7 +397,7 @@ public <T> MultiDocumentEntity<? extends DocumentEntity> update(final Iterable<T
391397

392398
final MultiDocumentEntity<? extends DocumentEntity> result;
393399
try {
394-
result = _collection(entityClass).updateDocuments(toVPackCollection(values), options);
400+
result = _collection(entityClass, options.getStreamTransactionId() != null).updateDocuments(toVPackCollection(values), options);
395401
} catch (final ArangoDBException e) {
396402
throw translateExceptionIfPossible(e);
397403
}
@@ -409,7 +415,7 @@ public DocumentEntity update(final Object id, final Object value, final Document
409415

410416
final DocumentEntity result;
411417
try {
412-
result = _collection(value.getClass(), id).updateDocument(determineDocumentKeyFromId(id), toVPack(value),
418+
result = _collection(value.getClass(), id, options.getStreamTransactionId() != null).updateDocument(determineDocumentKeyFromId(id), toVPack(value),
413419
options);
414420
} catch (final ArangoDBException e) {
415421
throw translateExceptionIfPossible(e);
@@ -428,7 +434,7 @@ public <T> MultiDocumentEntity<? extends DocumentEntity> replace(final Iterable<
428434

429435
final MultiDocumentEntity<? extends DocumentEntity> result;
430436
try {
431-
result = _collection(entityClass).replaceDocuments(toVPackCollection(values), options);
437+
result = _collection(entityClass, options.getStreamTransactionId() != null).replaceDocuments(toVPackCollection(values), options);
432438
} catch (final ArangoDBException e) {
433439
throw translateExceptionIfPossible(e);
434440
}
@@ -445,7 +451,7 @@ public DocumentEntity replace(final Object id, final Object value, final Documen
445451

446452
final DocumentEntity result;
447453
try {
448-
result = _collection(value.getClass(), id).replaceDocument(determineDocumentKeyFromId(id), toVPack(value),
454+
result = _collection(value.getClass(), id, false).replaceDocument(determineDocumentKeyFromId(id), toVPack(value),
449455
options);
450456
} catch (final ArangoDBException e) {
451457
throw translateExceptionIfPossible(e);
@@ -460,7 +466,7 @@ public DocumentEntity replace(final Object id, final Object value, final Documen
460466
public <T> Optional<T> find(final Object id, final Class<T> entityClass, final DocumentReadOptions options)
461467
throws DataAccessException {
462468
try {
463-
final VPackSlice doc = _collection(entityClass, id).getDocument(determineDocumentKeyFromId(id),
469+
final VPackSlice doc = _collection(entityClass, id, options.getStreamTransactionId() != null).getDocument(determineDocumentKeyFromId(id),
464470
VPackSlice.class, options);
465471
return Optional.ofNullable(fromVPack(entityClass, doc));
466472
} catch (final ArangoDBException e) {
@@ -481,7 +487,7 @@ public <T> Iterable<T> find(final Iterable<?> ids, final Class<T> entityClass, D
481487
try {
482488
final Collection<String> keys = new ArrayList<>();
483489
ids.forEach(id -> keys.add(determineDocumentKeyFromId(id)));
484-
final MultiDocumentEntity<VPackSlice> docs = _collection(entityClass).getDocuments(keys, VPackSlice.class, options);
490+
final MultiDocumentEntity<VPackSlice> docs = _collection(entityClass, options.getStreamTransactionId() != null).getDocuments(keys, VPackSlice.class, options);
485491
return docs.getDocuments().stream().map(doc -> fromVPack(entityClass, doc)).collect(Collectors.toList());
486492
} catch (final ArangoDBException e) {
487493
throw translateExceptionIfPossible(e);
@@ -496,7 +502,7 @@ public <T> MultiDocumentEntity<? extends DocumentEntity> insert(final Iterable<T
496502

497503
final MultiDocumentEntity<? extends DocumentEntity> result;
498504
try {
499-
result = _collection(entityClass).insertDocuments(toVPackCollection(values), options);
505+
result = _collection(entityClass, options.getStreamTransactionId() != null).insertDocuments(toVPackCollection(values), options);
500506
} catch (final ArangoDBException e) {
501507
throw translateExceptionIfPossible(e);
502508
}
@@ -512,7 +518,7 @@ public DocumentEntity insert(final Object value, final DocumentCreateOptions opt
512518

513519
final DocumentEntity result;
514520
try {
515-
result = _collection(value.getClass()).insertDocument(toVPack(value), options);
521+
result = _collection(value.getClass(), options.getStreamTransactionId() != null).insertDocument(toVPack(value), options);
516522
} catch (final ArangoDBException e) {
517523
throw translateExceptionIfPossible(e);
518524
}
@@ -529,7 +535,7 @@ public DocumentEntity insert(final String collectionName, final Object value, fi
529535

530536
final DocumentEntity result;
531537
try {
532-
result = _collection(collectionName).insertDocument(toVPack(value), options);
538+
result = _collection(collectionName, options.getStreamTransactionId() != null).insertDocument(toVPack(value), options);
533539
} catch (final ArangoDBException e) {
534540
throw translateExceptionIfPossible(e);
535541
}
@@ -610,7 +616,7 @@ public <T> void upsert(final Iterable<T> value, final UpsertStrategy strategy) t
610616
@Override
611617
public <T> void repsert(final T value, AqlQueryOptions options) throws DataAccessException {
612618
@SuppressWarnings("unchecked") final Class<T> clazz = (Class<T>) value.getClass();
613-
final String collectionName = _collection(clazz).name();
619+
final String collectionName = _collection(clazz, options.getStreamTransactionId() != null).name();
614620

615621
potentiallyEmitEvent(new BeforeSaveEvent<>(value));
616622

@@ -638,7 +644,7 @@ public <T> void repsert(final Iterable<? extends T> values, final Class<T> entit
638644
return;
639645
}
640646

641-
final String collectionName = _collection(entityClass).name();
647+
final String collectionName = _collection(entityClass, options.getStreamTransactionId() != null).name();
642648
potentiallyEmitBeforeSaveEvent(values);
643649

644650
final Iterable<? extends T> result;
@@ -730,7 +736,7 @@ private void updateDBFields(final Object value, final DocumentEntity documentEnt
730736
@Override
731737
public boolean exists(final Object id, final Class<?> entityClass, DocumentExistsOptions options) throws DataAccessException {
732738
try {
733-
return _collection(entityClass).documentExists(determineDocumentKeyFromId(id), options);
739+
return _collection(entityClass, options.getStreamTransactionId() != null).documentExists(determineDocumentKeyFromId(id), options);
734740
} catch (final ArangoDBException e) {
735741
throw translateExceptionIfPossible(e);
736742
}
@@ -751,18 +757,18 @@ public void dropDatabase() throws DataAccessException {
751757

752758
@Override
753759
public CollectionOperations collection(final Class<?> entityClass) throws DataAccessException {
754-
return collection(_collection(entityClass));
760+
return collection(_collection(entityClass, false));
755761
}
756762

757763
@Override
758-
public CollectionOperations collection(final String name) throws DataAccessException {
764+
public CollectionOperations collection(String name) {
759765
return ArangoOperations.super.collection(name);
760766
}
761767

762768
@Override
763769
public CollectionOperations collection(final String name, final CollectionCreateOptions options)
764770
throws DataAccessException {
765-
return collection(_collection(name, null, options));
771+
return collection(_collection(name, null, options, false));
766772
}
767773

768774
private CollectionOperations collection(final ArangoCollection collection) {

0 commit comments

Comments
 (0)