I have an entity with an #ElementCollection of strings:
#ElementCollection(fetch = FetchType.EAGER)
private Set<String> names;
While it is no problem to query by names:
List<MyEntity> findByNames(String name);
It seems not to work if i try to create a method with "contains". I want to find entities that have a matching name that contains given substring:
List<MyEntity> findByNamesContains(String substringOfname);
This yields no results but also no error. It seems that the "contains" keyword here is interpreted as the list of name should contain. If i change it to
List<MyEntity> findByNamesContains(List<String> substringOfname);
This methods works.
My question is: is there a combination of keywords to get a method that returns all entities that have a name matching a given substring?
If not how would a JPQL query look like?
As far I knew, No you can't do it wit Spring-JPA-Date repository method names, but it's very easy to be done with JPQL and Spring repository
here's JPQL
select e from MyEntity e join e.names name where name LIKE CONCAT('%', :name, '%')
for case-insensitive query use this
select e from MyEntity e join e.names name where LOWER(name) LIKE CONCAT('%', LOWER(:name), '%')
JPQL + Spring repository
#Query("select e from MyEntity e join e.names name where name LIKE CONCAT('%', :name, '%') ")
List<MyEntity> findByName(#Param("name") String name);
for more information use look here and this answer, Hope this help (:
In case of single string use containing keyword. Works in the same way as "like" in sql queries.
Ref: https://docs.spring.io/spring-data/jpa/docs/current/reference/html/#_supported_query_keywords
Related
We want to pass list of strings into JPA named native query.How we can achieve this.it is throwing invalid query parameter exception.
#Query(value = "select e from student so where so.name in ?1", nativeQuery = true)
List<Student> someFunName(List<String> stringList);
U can try something like this for a nativeQuery, for list of string as param.
(I just gave an example for Entity Student)
I am trying to get the result of one query using Spring Data JPA. Here I am sending some parameter and receiving result according to that.
My repository query is,
#Query("select u.username,p.pname from Users u join u.priviJoin p where u.username = :uname AND p.pname = :pname")
List<Users> findByUsername(#Param("uname") String uname , #Param("pname") String pname );
And calling from controller like the following,
#RequestMapping(value = "/joinResult", method = RequestMethod.GET)
public List<Users> joinResultShow()
{
return (List<Users>) userRepo.findByUsername("test_user","testRole");
}
Here we can see that if I am passing some value then only checking according to that parameter. Here I need to modify my query like if parameter is null, then not need to use AND condition in query.
How can I modify this query for avoiding AND condition if parameter is null? I am new to Spring Data JPA world.
Here are some possible options for you
1. Create multiple methods in your repository like
#Query("select u.username,p.pname from Users u join u.priviJoin p where u.username = :uname AND p.pname = :pname")
List<Users> findByusernamewithRole(#Param("uname") String uname , #Param("pname") String pname );
#Query("select u.username,p.pname from Users u join u.priviJoin p where u.username = :uname")
List<Users> findByUsernameWithoutRole(#Param("uname") String uname);
Write a custom respository and use EntityManager. With this you can create a dynamic queries based on your input using CriteriaBuilder and use this criteria in querying.
Last and the most preferred option in case of dynamic inputs(like you have) is Querydsl.
Some articles about querydsl
http://www.baeldung.com/querydsl-with-jpa-tutorial
http://www.querydsl.com/static/querydsl/latest/reference/html/ch02.html
I have an entity which have a collection of tags
#ManyToMany
private Set<Tag> listeTag;
I want to write a query which returns a list of my entity which contains all tags passed in parameters and not just one like this.
select distinct entity from Entity entity where and entity.listeTag in :listeTag
if there are two tags in listeTag I want only entities which have at least the two tags.
select e from SomeEntity e where :numberOfTagsInSet =
(select count(tag.id) from SomeEntity e2
join e2.listeTag tag
where e.id = e2.id
and tag.id in :setOfTagIds)
That should do the trick.
I have the following JPA Entity I want to update:
#Entity(name = "EmployeeImpl")
#Table(name = "EmployeeImpl")
public class EmployeeImpl {
#Id
#Column(name = "employeeId")
#GeneratedValue(strategy = GenerationType.AUTO)
private long id;
#ElementCollection
private List<String> phonenumber;
}
I thought I use a namedQuery like so
#NamedQuery(name = "updateEmployee",
query = "Update EmployeeImpl e SET e.phonenumber :number WHERE e.id = :id")
But that doesn't work: Exception Description: Error compiling the query [updateEmployee: Update EmployeeImpl e SET e.phonenumber = :number WHERE e.id = :id], line 1, column 28: invalid access of attribute [phonenumber] in SET clause target [e], only state fields and single valued association fields may be updated in a SET clause.
Question is, how do I update an #ElementCollection? If it's possible i'd like to do it with a jpql query.
No, that is not possible in JPQL. As kostja says: the message says it clear and also according to the JPA specification, Chapter "4.10 Bulk Update and Delete Operations" you may update only state fields and single values object fields.
The syntax of these operations is as follows:
update_statement ::= update_clause [where_clause]
update_clause ::= UPDATE entity_name [[AS] identification_variable]
SET update_item {, update_item}*
update_item ::= [identification_variable.]{state_field | single_valued_object_field} = new_value
new_value ::=
scalar_expression |
simple_entity_expression |
NULL
WHAT TO DO?
Probably the most clean way to do that is simply to fetch the entities and to add/replace the phone number/s, although you can always do that also with Native Queries, i.e SQL queries as kostja says.
The reason for the failure is stated in the error message. You cannot use bulk updates on non-singular attributes of your entity, since they are stored in a different table.
How do you do it instead? You update the collection table.
The default table name for collection tables is <parent_entity>_<field_name>. So the table you are interested in should be named EmployeeImpl_phonenumber. The id column for the EmployeeImpl (the foreign key) should be named EmployeeImpl_id per default.
EDIT What I posted initially was not valid in JPQL. You might want to use a native query instead. It is simple, so it should be portable:
The native query could then look like this:
UPDATE EmplyeeImpl_phonenumber
SET phonenumber = ?
WHERE employeeimpl_id = ?
I have a java entity class UserBean with a list of events:
#OneToMany
private List<EventBean> events;
EventBean has Date variable:
#Temporal(javax.persistence.TemporalType.TIMESTAMP)
private Date eventDate;
Now in UserBean I want to create a NamedQuery that returns all dates that fall within a specific range:
#NamedQuery(name="User.findEventsWithinDates",
query="SELECT u.events FROM UserBean u WHERE u.name = :name AND u.events.eventDate > :startDate AND u.events.eventDate < :endDate")
The above query does not compile though. I get this error:
The state field path 'u.events.eventDate' cannot be resolved to a valid type.
By the way, I use EclipseLink version 2.5.0.v20130507-3faac2b.
What can I do to make this query work? Thanks.
Path u.events.eventDate is an illegal construct in JPQL, because it is not allowed to navigate via a collection valued path expression. In this case u.events is a collection valued path expression. In JPA 2.0 specification this is told with following words:
It is syntactically illegal to compose a path expression from a path
expression that evaluates to a collection. For example, if o
designates Order, the path expression o.lineItems.product is illegal
since navigation to lineItems results in a collection. This case
should produce an error when the query string is verified. To handle
such a navigation, an identification variable must be declared in the
FROM clause to range over the elements of the lineItems collection.
This problem can be solved by using JOIN:
SELECT distinct(u)
FROM UserBean u JOIN u.events e
WHERE u.name = :someName
AND e.eventDate > :startDate
AND e.eventDate < :endDate