Spring Data MongoDB - no signature of method is applicable for argument types - mongodb

I had a certain method that called MongoOperations.find(Query query, Class<T> entityClass, String collectionName), and returned a List<T> as expected. I want to change the method to stream(), in case the number of returned objects from the query is exceptionally large. According to the documentation, there should be an identical signature for stream(), but when I try to call the function with a collectionName, I get an error:
groovy.lang.MissingMethodException: No signature of method: org.springframework.data.mongodb.core.MongoTemplate.stream() is applicable for argument types: (org.springframework.data.mongodb.core.query.Query, java.lang.Class, java.lang.String)
When I remove the collectionName, it runs without error. Could this be an issue of Spring Data versions? How can I solve this?
Thanks.

The overloaded stream method which takes collection name as an argument in MongoOperations is added in Mongo Spring 1.10 version.
The change is covered as part of the ticket. https://jira.spring.io/browse/DATAMONGO-1431

Related

C# Entity Framework : include with string parameter versus include with lambda expression [duplicate]

I am using entity framework and I want to execute a query and would like to know which is the besr way to execute a query. Which is best practice and why, and which one is more per-formant.
Option 1)
return
this.Storage.Customer.OfType<Preferred>()
.Include("Order")
.Where("it.Id = #customerId AND it.CustomerType = #cusType", new ObjectParameter("customerId ", customerId), new ObjectParameter("cusType", (int)cusType))
.Execute(MergeOption.OverwriteChanges)
.SingleOrDefault();
OR
return
this.Storage.Customer.OfType<Preferred>()
.Include(b => b.Order)
.Where(cust => cust.Id == customerId && cust.CustomerType== (int)cusType)
.SingleOrDefault();
The second question is why in option 2 us the .Execute not available? It appears red.
Thanks in advance.
The performance difference should be negligible compared with the actual data access, but you need to measure it to determine for sure.
Include with a lambda just uses reflection to get the property name then calls the version with a string parameter, so the only overhead is parsing the expression. (This is an implementation detail, however, so it is subject to change)
The benefit of using a lambda is type safety - using the wrong property name in a lambda will break the build, but using the wrong string will only fail at run-time.
The reason Execute is not available is because Include with a lambda parameter is an extension method on IQueryable<T> that returns an IQueryable<T> in order to chain methods like Where. Include with a string parameter is a method on ObjectQuery<T> that returns an ObjectQuery<T>. Execute is a method on ObjectQuery<T>, not IQueryable<T> so it is not available when you use IQueryable methods.

Spring data deleteBy query doesnt return deleted object

In Spring-data-mongodb, can we return the single deleted object from query method of repository like below
public interface MyRepository extends MongoRepository<MyObject, String>{
Optional<MyObject> deleteByXAndY(String x, String y);
}
if there will be always single document that's get deleted by above query.
I tried it but it throws exception like cant convert Long to MyObject. I think only void, long or List or Stream are supported. Is there any way to achieve what I am trying to do?
Spring doesn't know that only one object can ever be deleted by this method, so it won't allow you to define it with a single result returned. After all, there is no guarantee in the "contract" you have defined here that there will only be one match. You should probably define the method to return a List and then just get the first object from the list if you are sure there will only be one.

Solution for "Failed to create query for method" findOne

So, I was getting this exception when starting up my app that uses spring-data-jpa 2.0.3
java.lang.IllegalArgumentException: Failed to create query for method public abstract package.Entity package.repositories.EntityRepository.findOne(java.lang.Integer)! No property findOne found for type Entity!
So, the issue was that my EntityRepository extends CrudRepository. CrudRepository already provides the findOne() method. A previous developer had duplicated the method in our EntityRepository interface. By removing the duplicate method, everything worked.
I also had to remove the findAll() : List methods. In this case, it wasn't a straight removal, because the CrudRepository returns Iterable instead. Still an easy fix.

Automatically casting RHS values for specific JOOQ columns

I have the following code, where "CI_COL" is of type citext (https://www.postgresql.org/docs/current/static/citext.html)
String str = "testING";
int countBad = context.fetchCount(select(Tables.MY_TABLE.CI_COL)
.from(Tables.MY_TABLE)
.where(Tables.MY_TABLE.CI_COL.eq(str)));
int countGood = context.fetchCount(select(Tables.MY_TABLE.CI_COL)
.from(Tables.MY_TABLE)
.where(Tables.MY_TABLE.CI_COL.eq(cast(str, new DefaultDataType<>(SQLDialect.POSTGRES, String.class, "citext")))));
The first query returns 0, and the second query correctly returns > 0.
It took me a long time to track down the root cause, because when the first query was printed (or found in the DEBUG logging), it seemed to execute in the terminal just fine.
Once I got down to the statement level and actually started binding values, that's where the root cause seemed to be. It seems to be an issue (or on purpose) in the postgres driver. This post illustrates the binding issue with citext: https://www.postgresql.org/message-id/CAJFs0QB90bo0vWw5pZcw0c%3DLjOcOX04qPEM4nSd6uY7-T2r5hA%40mail.gmail.com
Is it possible to fix this at the JOOQ level, by having JOOQ automatically perform a cast on all right hand side values for a specific column?
Side note
new DefaultDataType<>(...)
Ghasp! You're using internal API :)
Correct solution
The correct way to introduce new data types in jOOQ is to use a Converter, or in this case a data type Binding:
http://www.jooq.org/doc/latest/manual/sql-building/queryparts/custom-bindings
While most Binding method implementations would simply delegate to jOOQ's DefaultBinding, you can override the sql() method (which generates the bind variable's SQL string) to this:
#Override
public void sql(BindingSQLContext<JsonElement> ctx) throws SQLException {
ctx.render().sql("?::citext");
}

IQueryable doesn't implement IDbAsyncEnumerable

The question was originally asked at http://entityframework.codeplex.com/discussions/399499#post928179 .
Good day! Please tell me if it is wrong place to post this question.
I have a query as follows:
IQueryable<Card> cardsQuery =
dataContext.Cards
.Where(predicate)
.OrderByDescending(kc => kc.SendDate)
.AsQueryable();
Then I try:
Task<Card[]> result = cardsQuery.ToArrayAsync();
And then exception rises:
The source IQueryable doesn't implement IDbAsyncEnumerable<Models.Card>
I use modified version of 'EF 5.x DbCotext generator'.
How to avoid it?
UPDATE
Important remark is that I have method to produce IQuerayble<Card> as follows:
class Repository {
public IQueryable<Card> GetKudosCards(Func<Card, bool> predicate) {
IEnumerable<KudosCard> kudosCards = kudosCardsQuery.Where(predicate);
return kudosCards
.OrderByDescending(kc => kc.SendDate)
.AsQueryable();
}
}
What is the point of calling AsQueryable? If you compose a query with the extension methods starting from an IQueryable source collection (e.g. DbSet, ObjectSet), the query will be IQueryable too.
The purpose of AsQueryable is to wrap an IEnumerable collection with an IQueryable proxy/adapter that uses a Linq provider that is capable of compiling IQueryable queries into a Linq to Object queries. This can be useful in scenarios when you would like to use inmemory data queries.
Why is the AsQueryable call necessary? What if you just simply remove it?
Update
Okey, now it seems I understand your problem. After a quick look on the ODataQueryOptions.ApplyTo I realized that it just extends the underlying expression tree of the query. You can still use it to run the query in the way you want, however you need a little trick to transform the query back to generic.
IQueryable<Card> cardsQuery =
dataContext.Cards
.Where(predicate)
.OrderByDescending(kc => kc.SendDate);
IQueryable odataQuery = queryOptions.ApplyTo(cardsQuery);
// The OData query option applier creates a non generic query, transform it back to generic
cardsQuery = cardsQuery.Provider.CreateQuery<Card>(odataQuery.Expression);
Task<Card[]> result = cardsQuery.ToArrayAsync();
The problem is as follows.
I have a method:
class Repository {
public IQueryable<Card> GetKudosCards(Func<Card, bool> predicate) {
IEnumerable<KudosCard> kudosCards = kudosCardsQuery.Where(predicate);
return kudosCards
.OrderByDescending(kc => kc.SendDate)
.AsQueryable();
}
}
The problem is that kudosCards has type IEnumerable<KudosCard>. That throws exception. If I change predicate type to Expression<Func<Card, bool> predicate then everything works just fine.
I had the same problem when I was using the LinqKit library expression builder, which in the end, was producing AsQueryable(), and very surprisingly it was happening for me from the XUnit Integration Tests call.
I was going wild about why the same problem wasn't happening when calling the same API endpoint via Swagger.
It turned out I had to do an elementary change.
I had to replace:
using System.Data.Entity;
with:
using Microsoft.EntityFrameworkCore;
I had the same problem when I was using the LinqKit library expression builder, which in the end, was producing AsQueryable().
And very surprisingly, it was happening for me from the XUnit Integration Tests call.
I was going wild about why the same problem wasn't happening when calling the same API endpoint via Swagger.
It turned out I had to do an elementary change.
I had to replace the:
using System.Data.Entity;
with:
using Microsoft.EntityFrameworkCore;
In the place where I was calling the LinqKit expression method.
If you want to use the List<T> for Linq query, Avoid chaining it with ToListAsync(). It uses the class IDbAsyncEnumerable that is not available to a normal List<T> object