spring-data icon indicating copy to clipboard operation
spring-data copied to clipboard

Feature: create collections on startup

Open lotabout opened this issue 5 years ago • 9 comments

Currently the collections will be created when repository.save() is called if not already existed. Exceptions will be thrown if queries(e.g. repository.findAll()) were called before save because the tables do not exist.

I was expecting the tables are created on spring startup so that findAll() will return empty collections, like what hibernate does.

If I missed something in configuration, please tell.

  • ArangoDB version: 3.3.14
  • arangodb-spring-data version: 3.1.1

lotabout avatar Oct 20 '18 01:10 lotabout

Hi @lotabout,

are you sure that you have done nothing but repository.findAll()? Because findAll creates the collection too.

It uses ArangoOperations.query and passes the Class of your bean within the bindVars. Every value of type Class in bindVars is resolved as a collection - to get the collection name - and in this process the collection is created.

mvollmary avatar Oct 20 '18 12:10 mvollmary

@mpv1989 Sorry that my report is partly true. It is not findAll that I called but a custom query:

@Query("FOR v IN customers"
        + " SORT RAND()"
        + " LIMIT @count"
        + " RETURN v")
Set<Customer> findRandom(@Param("count") int count);

I also confirmed that other custom queries will fail too. Are there any difference between custom query and findAll/findById?

lotabout avatar Oct 20 '18 13:10 lotabout

Ok, now it makes sense for me.

findAll/findById derives the collection from the domain class, in this process it creates the collection. In your query, you pass the collection as a simple String which will not be analysed.

As a workaround - and also as a better practice - you should use the placeholder #collection instead of the collection name customers within your query. Using the placeholder also creates the collection when derivces the collection name for it.

@Query("FOR v IN #collection"
        + " SORT RAND()"
        + " LIMIT @count"
        + " RETURN v")
Set<Customer> findRandom(@Param("count") int count);

But you are right, the collection should be created earlier, so that this problem can not be occur.

mvollmary avatar Oct 20 '18 14:10 mvollmary

@mpv1989 Thanks! Confirmed the #collection trick works.

Besides, extended queries won't create collections automatically neither. Any workarounds?

public interface CharacterRepository extends ArangoRepository<Character, String> {
	Optional<Character> findByNameAndSurname(String name, String surname);
        // ...
}

lotabout avatar Oct 21 '18 01:10 lotabout

@mpv1989 can you please let me know if there is any workarounds for extended quries as @lotabout pointed out.

vivek-dhayalan avatar Aug 14 '19 13:08 vivek-dhayalan

I also faced same issue with derived query. As an workaround, I call findById with 'dummy' ID for all repositories while initializing my Spring boot Application or Service. Like below:

init {
  someRepositoryA.findById("id")   
  someRepositoryB.findById("id")
}

I believe that there must be better solution.

wildroco avatar Nov 09 '19 06:11 wildroco

I use operations.collection(MyCollection.class); to ensure the collection exists, where operations is an @Autowired instance of com.arangodb.springframework.core.ArangoOperations - but I also have a similar thought: There might be a better solution.

bthj avatar Nov 09 '19 15:11 bthj

So does it has some better solution to create collection automitically?

lidaling avatar Jun 12 '20 02:06 lidaling

using Spring I have a configuration like this (including spring-data-commons):

@Configuration
class ArangoDatabaseInit implements InitializingBean {

    @Autowired
    private ArangoOperations client;

    @Override
    public void afterPropertiesSet() {
        AnnotatedTypeScanner scanner = new AnnotatedTypeScanner(false, Document.class, Edge.class);
        scanner.findTypes("your.base.package").forEach(client::collection);
    }
}

aburmeis avatar May 04 '23 10:05 aburmeis