I'm trying to use spring PagingAndSortingRepository with a find MyEntity where field in fieldValues query as follows:
#Repository
public interface MyEntity extends PagingAndSortingRepository<MyEntity, String> {
List<MyEntity> findByMyField(Set<String> myField);
}
But of no success.
I expected the above function to return all entities whose field matches one of the field values but it only returns empty results.
Even though it seems like a pretty straight forward ability i could not find any reference to it in the docs.
Is / How that could be achieved?
Thanks.
This should indeed be possible if you are searching on a specific field within your entity and you want to return a list of all that field matches at least one entry in some collection. The documentation here says this can be achieved using the keyword In example: findByAgeIn(Collection<Age> ages) and is equivalent to … where x.age in ?1
From your post i'm not 100% sure if this is the use case you are after but give this a try. You will need to search on a specific field, so replace 'field' with whatever field you are searching on. If you are searching on multiple fields it may be possible to concatenate the results with the Or keyword and specify multiple fields that way.
#Repository
public interface MyEntity extends PagingAndSortingRepository<MyEntity, String> {
List<MyEntity> findByFieldIn(Set<String> myField);
}
http://docs.spring.io/spring-data/jpa/docs/current/reference/html/
Your method name has to be findByMyFieldIn so you got to add an In at the end to get a where ... in (..) query.
Related
I have a co-worker that just blew my mind. We have a Java 11/Spring Boot/Hibernate/JPA app talking to a MySQL DB. Apparently JPA JPQL (or something similar to that) is capable of -- but only if you write the repository methods correctly -- building out queries based on your method name.
So for instance if we have a JPA entity:
#Entity
#Table(name = "accounts")
#Data
public class Account {
#Column(name = "account_email")
private String email;
// ... many more fields down here
}
And then a repository for it:
#Repository
public interface AccountRepository extends JpaRepository<Account,Long> {
#Query("FROM Account WHERE email = :email")
Account findByEmail(#Param(value = "email") String email);
}
Apparently (and this might be a bad example) I could just simplify that to:
#Repository
public interface AccountRepository extends JpaRepository<Account,Long> {
Account findByEmail(String email);
}
And JPA/JPQL will figure out that since I want to "findByEmail" and Account#email exists, it just wants me to do a SELECT * FROM accounts where email = ?. Amazing!
The only problem is: I don't see this documented anywhere well, and I don't see it documented anywhere officially. There's a few old blogs that I was able to find that insinuate the same things, but nowhere official (JPA docs, JPQL docs, etc.) that go into detail as to how it works and what its limitations are.
Can anyone point me in the right direction? What is this mysterious feature/technology called and what are its limitations/capabilities? Can it only work on SELECTs or can it handle inserts/updates/deletes as well?
This is part of the Spring Data support for JPA. You can find more info at the documentation Query Methods and all the supported query-keywords in the appendix section. Here is an excerpt from the documentation:
Query subject keywords
Keyword
Description
find…By, read…By, get…By, query…By, search…By, stream…By
General query method returning typically the repository type, a Collection or Streamable subtype or a result wrapper such as Page, GeoResults or any other store-specific result wrapper. Can be used as findBy…, findMyDomainTypeBy… or in combination with additional keywords.
exists…By
Exists projection, returning typically a boolean result.
count…By
Count projection returning a numeric result.
delete…By, remove…By
Delete query method returning either no result (void) or the delete count.
…First…, …Top…
Limit the query results to the first of results. This keyword can occur in any place of the subject between find (and the other keywords) and by.
…Distinct…
Use a distinct query to return only unique results. Consult the store-specific documentation whether that feature is supported. This keyword can occur in any place of the subject between find (and the other keywords) and by.
Query predicate keywords
Logical keyword
Keyword expressions
AND
And
OR
Or
AFTER
After, IsAfter
BEFORE
Before, IsBefore
CONTAINING
Containing, IsContaining, Contains
BETWEEN
Between, IsBetween
ENDING_WITH
EndingWith, IsEndingWith, EndsWith
EXISTS
Exists
FALSE
False, IsFalse
GREATER_THAN
GreaterThan, IsGreaterThan
GREATER_THAN_EQUALS
GreaterThanEqual, IsGreaterThanEqual
IN
In, IsIn
IS
Is, Equals, (or no keyword)
IS_EMPTY
IsEmpty, Empty
IS_NOT_EMPTY
IsNotEmpty, NotEmpty
IS_NOT_NULL
NotNull, IsNotNull
IS_NULL
Null, IsNull
LESS_THAN
LessThan, IsLessThan
LESS_THAN_EQUAL
LessThanEqual, IsLessThanEqual
LIKE
Like, IsLike
NEAR
Near, IsNear
NOT
Not, IsNot
NOT_IN
NotIn, IsNotIn
NOT_LIKE
NotLike, IsNotLike
REGEX
Regex, MatchesRegex, Matches
STARTING_WITH
StartingWith, IsStartingWith, StartsWith
TRUE
True, IsTrue
WITHIN
Within, IsWithin
Not much of a mystery and quite well documented to be perfectly honest. What you mention is called a derived query which basically infers the JPQL query from the method name. A simple Google search can turn up quite some documentation of this feature. Also the Spring Data JPA documentation clearly documents this and well as its usage. Check here for more.
I write two classes in one mongo collection, say One and Two. In these classes I have field someId. Then I want to get all One objects with specified someId. I created a method:
Page<One> findBySomeId(String id, Pageable pageable);
But get error:
org.springframework.data.mapping.model.MappingInstantiationException: Failed to instantiate ...
As I see, mongo take both One and Two objects, and then trying to create One objects from them.
I tried write next:
Page<One> findOneBySomeId(String id, Pageable pageable);
and got the same error. How to write a proper method to retrieve only specified objects from mongo DB with spring data?
Your query should be like this
Page<IOne> findByOneSomeId(String id, Pageable pageable);
public interface IOne {
public One getOne();
}
You should limit the query by specifying something that distinguishes One and Two. For example, you can filter by:
the (internal) _type field that spring automatically persist, which is equal to the fully qualified class name (unless #TypeAlias is provided, when it could be whatever you set)
some other property that you know is present only in the One documents (Page<One> findBySomeIdAndPropertyExistsTrue(String id, Pageable pageable))
With Spring Data you can use following syntax :
One findFirstBySomeId(String someId);
Here is documentation about spring data(4.4.5. Limiting Query Results) where you find the explanation and examples: https://docs.spring.io/spring-data/jpa/docs/current/reference/html/#reference
List findAll(#Nullable Specification spec) return all value that matches the Specification .
Example: If in specification i have a parameter = 3.0 , findAll return me all the value matches.
So it return for example 543.0 , but i want just 3.0
Do you know a function that return me just the values that are exactly that?
If I understand correctly what you want to achieve, you don't need Specification.
Assuming that you want to fetch a list of YourObject based on the value of a field named price, you just have to add a method in the repository interface :
public interface YourObjectRepository extends JpaRepository<YourObject, Short>, JpaSpecificationExecutor<YourObject> {
public List<YourObject> findByPrice(Double price);
}
Spring will automaticaly implements the prototype as you want it : fetching all YourObjects that have field price equaks to the value given in parameter.
You need to call:
List findBySpecification(#Nullable Specification spec)
How your database tables look like?
After some reserch I don t discover any predefined method.
So I rezolved this with a #Query
#Query(Select t FROM Table t Where (t.price= :priceValue or null= :priceValue) and ( t.location= :locationValue or null= :locationValue)
List<Entity> getAllWithExactValue(#Param("priceValue") String priceValue, #Param("locationValue") String locationValue);
This let you have endpoints like this:
localhost:8080/param?locationValue=ClujNapoca&priceValue=1234
or
localhost:8080/param?priceValue=1234
or
localhost:8080/param?locationValue=ClujNapoca
And in return we will receive just variables with the exact value we asked
What is the best way to go about defining #QueryResult classes?
I have defined a repository method annotated with query like
"MATCH(p:Person{name:{0}) - [r]-(e)
RETURN distinct label(e) as type ,count(label(e)) as count;"
On neo4j console output looks like map.
type count
---- -----
Account 2
Document 5
Organization 4
So i have defined return type of the method like Map<String, Long> but doesn't work. Then I tried other ways - it returns the counts combined not individual. now am planning to use java driver to solve this problem. What the best way to go about designing #QueryResult to fit my situation. Any resources will be helpful along with the answer to my problem. :)
Your query should return count(e) and not count(labels(e)).
You can then use a org.neo4j.ogm.model.Result to hold the results of your query :
#Query("MATCH(p:Person{lastName:{0}}) -[r]-(e) RETURN distinct labels(e) as type ,count(e) as count")
Result resultExample(String name);
I have an #Entity Video having a one-to-many relation with a List<Tag> tags as one of its fields. I use the following #Repository using Spring Data to get the most popular tags:
#Repository
public interface TagRepository extends CrudRepository<Tag, Integer>{
#Query("SELECT t FROM Tag t WHERE (SELECT SUM(v.views) FROM Video v WHERE t MEMBER OF v.tags) > 0")
public List<Tag> findMostViewedTags(int maxTags);
}
The Query is processed and considered valid by Spring, I tested the generated SQL vs my database locally and it returned 2 Tags. In my Code however, I receive the value Null when I call the method findMostViewedTags(100).
The Query lookup strategy is the default "CREATE_IF_NOT_FOUND".
If there are no results found, should the method return an empty list or Null? My desired behavior is to receive an empty list.
Why does the method call return Null instead of a List<Tag> with size() 2?
The normal behavior is indeed returning an empty list if no results are found. If a List<Object> is the return value of the method in the defined interface, the method should never return Null.
The problem is that a parameter is given to the method and is not used anywhere in the Query. For some reason Spring decides to return a Null in that case. Solution: remove the unused parameter or use the parameter in the Query.
I have experienced similar problem. The cause was that I was using Mockito and have not correctly mocked the data with when().