I have a simple query as follows. I get the expected result if I hard code the id value as follows. But it throws IllegalArgumentException exception if I try to get the value from the Param instead. Note that I have tried to use the Param as both long and String and still the same results. Please advise what I am doing wrong. Thanks.
My Query
public interface FeedDetailRepository extends JpaRepository<FeedDetail, Long> {
#Query("select fd.message from FeedDetail as fd where fd.feedId =: id")
String custom(#Param("id") long id);
}
At Controller, if I run the following, I get an exception.
#GetMapping("/something/{id}")
public String getDetail(#PathVariable long id){
return feedDetailRepository.custom(id);
}
But if I hard code the id value as follows, I get the wanted result.
public interface FeedDetailRepository extends JpaRepository<FeedDetail, Long> {
#Query("select fd.message from FeedDetail as fd where fd.feedId = 4")
String getDetailBasedOnFeedId(#Param("id") long id);
}
The exception
nested exception is java.lang.IllegalArgumentException:
org.hibernate.QueryException: Named parameter not bound : id
I would change
#Query("select fd.message from FeedDetail as fd where fd.feedId =: id")
To (difference lies in space)
#Query("select fd.message from FeedDetail as fd where fd.feedId = :id")
This is a small difference for you but big for Spring. He recognizes a parameter by attaching name to colon like that
:id
For more details refer to the official Spring Data JPA Reference.
I had the same issue:
Wrong query:
SELECT * FROM `cars` as c where c.driver_one = :id OR c.driver_two = **:id;**
Correct query:
SELECT * FROM `cars` as c where c.driver_one = :id OR c.driver_two = **:id**
This is likely because of the way you have provided space with in the query.
My suggestion would be to format the code and in the string quotes use something similar
SELECT fd.message from FeedDetail AS fd where fd.feedId = :id
Related
Below is my query to filter the json column in MySQL table ,
public interface MpaCustomizationRepository extends
JpaRepository<MpaCustomization, Serializable> {
#Query(nativeQuery = true, value = "select * from MPA_CUSTOMIZATION where json_contains(domain_based_properties, '{\"id\" : ?1}')")
MpaCustomization findByDomainBaseId(String domainId);
}
above method throws below SQL error,
but if I hard code the variable and run the query like below its works fine,
#Query(nativeQuery = true, value = "select * from MPA_CUSTOMIZATION where json_contains(domain_based_properties, '{\"id\" : 2}')")
MpaCustomization findByDomainBaseId(String domainId);
How to fix this issue?
Use $.id for values when using native query, as SQL accepts like it only.
Other way, you may use :id and bind parameter {\"id\":\"" + <value> + "\"} to the query.
Maybe the following will work.
#Query(nativeQuery = true, value = "select * from MPA_CUSTOMIZATION where json_contains(domain_based_properties, ?1 , '$.id'")
MpaCustomization findByDomainBaseId(String domainId);
Source
I am facing a problem with my JpaRepository in a spring boot application
I want to perform a simple update query on my database, but it turns out that the native query is quite annoying, please help
public interface ImageRepository extends JpaRepository<Image, Integer> {
#Modifying
#Transactional
#Query(value = "UPDATE image SET path =(0?), status = (1?) WHERE Id = (2?)", nativeQuery = true)
void update(String path ,String status,int Id);
}
the code above returns the following error message
com.microsoft.sqlserver.jdbc.SQLServerException: Incorrect syntax near '#P0'.
I have tried to change SQL dialect to
org.hibernate.dialect.SQLServer2008Dialect
org.hibernate.dialect.SQLServer2012Dialect
respectively and non of them worked.
I tried also to write the query in a different way which does not give me an error but it does not update the fields. it can detect the integer value from the method but it will set the string values to an emply value:
#Query(value = "UPDATE image SET physical_path =(0), status = (1) WHERE Id = (2)", nativeQuery = true)
If anyone has faced the same issue please support
Frame the query like this :
#Query(value = "UPDATE image i SET path =:path, status = :status WHERE i.Id = :Id", nativeQuery = true)
void update(#Param("path") String path , #Param("status") String status, #Param("Id") int Id);
For positional parameters :
#Query(value = "UPDATE image i SET path = ?1, status = ?2 WHERE i.Id = ?3", nativeQuery = true)
void update(String path , String status, int Id);
From the Spring Data JPA - Reference you can see that the parameters (in the way you want to use them) are defined like -> ?1, ?2 etc..
Also, please keep in mind that the JPQL syntax is slightly different than plain sql.
#Modifying
#Query("update Image i set i.path = ?1 where i.status = ?2 where i.id = ?3")
void update(String path, String status, int id);
I am trying to write a JPQL query with a like clause:
LIKE '%:code%'
I would like to have code=4 and find
455
554
646
...
I cannot pass :code = '%value%'
namedQuery.setParameter("%" + this.value + "%");
because in another place I need :value not wrapped by the % chars. Any help?
If you do
LIKE :code
and then do
namedQuery.setParameter("code", "%" + this.value + "%");
Then value remains free from the '%' sign. If you need to use it somewhere else in the same query simply use another parameter name other than 'code' .
I don't use named parameters for all queries. For example it is unusual to use named parameters in JpaRepository.
To workaround I use JPQL CONCAT function (this code emulate start with):
#Repository
public interface BranchRepository extends JpaRepository<Branch, String> {
private static final String QUERY = "select b from Branch b"
+ " left join b.filial f"
+ " where f.id = ?1 and b.id like CONCAT(?2, '%')";
#Query(QUERY)
List<Branch> findByFilialAndBranchLike(String filialId, String branchCode);
}
I found this technique in excellent docs: http://openjpa.apache.org/builds/1.0.1/apache-openjpa-1.0.1/docs/manual/jpa_overview_query.html
You could use the JPA LOCATE function.
LOCATE(searchString, candidateString [, startIndex]): Returns the
first index of searchString in candidateString. Positions are 1-based.
If the string is not found, returns 0.
FYI: The documentation on my top google hit had the parameters reversed.
SELECT
e
FROM
entity e
WHERE
(0 < LOCATE(:searchStr, e.property))
I don't know if I am late or out of scope but in my opinion I could do it like:
String orgName = "anyParamValue";
Query q = em.createQuery("Select O from Organization O where O.orgName LIKE '%:orgName%'");
q.setParameter("orgName", orgName);
There is nice like() method in JPA criteria API. Try to use that, hope it will help.
CriteriaBuilder cb = em.getCriteriaBuilder();
CriteriaQuery criteriaQuery = cb.createQuery(Employees.class);
Root<Employees> rootOfQuery = criteriaQuery.from(Employees.class);
criteriaQuery.select(rootOfQuery).where(cb.like(rootOfQuery.get("firstName"), "H%"));
Use below JPQL query.
select i from Instructor i where i.address LIKE CONCAT('%',:address ,'%')");
Use below Criteria code for the same:
#Test
public void findAllHavingAddressLike() {
CriteriaBuilder cb = criteriaUtils.criteriaBuilder();
CriteriaQuery<Instructor> cq = cb.createQuery(Instructor.class);
Root<Instructor> root = cq.from(Instructor.class);
printResultList(cq.select(root).where(
cb.like(root.get(Instructor_.address), "%#1074%")));
}
Use JpaRepository or CrudRepository as repository interface:
#Repository
public interface CustomerRepository extends JpaRepository<Customer, Integer> {
#Query("SELECT t from Customer t where LOWER(t.name) LIKE %:name%")
public List<Customer> findByName(#Param("name") String name);
}
#Service(value="customerService")
public class CustomerServiceImpl implements CustomerService {
private CustomerRepository customerRepository;
//...
#Override
public List<Customer> pattern(String text) throws Exception {
return customerRepository.findByName(text.toLowerCase());
}
}
Just leave out the ''
LIKE %:code%
Use JPQL query.
#Query("select e from Entity e where e.id = ?1 and e.code like CONCAT('%', CONCAT(?2, '%'))")
List<Entity> findByIdAndCodeLike(Long id, String code);
I have an interface public interface IAllAccountsRepo extends CrudRepository
and a method in that like below
#Query(value = "SELECT * FROM account a where a.id in :id AND a.accountType = :accountType", nativeQuery=true)
public AccountEntity findByIdAndAccountType(#Param("id") String id, #Param("accountType") String accountType);
When i call this method in a helper class, where I will get a list of ids and I loop through them and pass in a filter value to the above method, but i have issues when there is no record matching the query in the database.
It just stops by saying null(when there is no record in db). I do not want to through exception, need to ignore and proceed if i can do that. Is there anyway i can code it to ignore the null and proceed? or do i need criteria query or any other?
for (String id : accountIdList) {
accountEntityTemp = iAllAccountsRepo.findByIdAndAccounttype(id, accounttype);
System.out.println("bs" + accountEntityTemp.getId());
if (accountEntityTemp != null) {
accountsEntityList.add(accountEntityTemp);
}
}
accountEntityTemp = null for one id and accounttype and i'm getting the below error.
2015-12-10 14:20:03.784 WARN 10524 --- [nio-8080-exec-1] .m.m.a.ExceptionHandlerExceptionResolver : Handler execution resulted in exception: null
Thanks.
Uhm... First of all please..
#Query(value = "SELECT * FROM account a where a.id =:id AND a.accountType = :accountType", nativeQuery=true)
public AccountEntity findByIdAndAccountType(#Param("id") String id, #Param("accountType") String accountType);
That being said...
Just.. why? You're extending crudrepository, so you could as well just write
AccountEntity findByIdAndAccountType(String id, String accountType)
IF your attributes on AccountEntity bean are named
Id
AccountType
or change id to Integer, as I don't know its type..
plus man, some care of potential NPE..
you told us it's possible no accountentity is found... yet you do
accountEntityTemp = iAllAccountsRepo.findByIdAndAccounttype(id, accounttype);
System.out.println("bs" + accountEntityTemp.getId()); /// Null pointer here potentially...
if (accountEntityTemp != null) {
accountsEntityList.add(accountEntityTemp);
}
at most change it to
accountEntityTemp = iAllAccountsRepo.findByIdAndAccounttype(id, accounttype);
if (accountEntityTemp != null) {
System.out.println("bs" + accountEntityTemp.getId());
accountsEntityList.add(accountEntityTemp);
}
I don't even know why you use IN function when you are passing a single argument for an id.
Nevertheless, the method you want should look like this:
AccountEntity findByIdAndAccountType(Integer id, String accountType);
i am trying to do my first steps in Java, and i am blocked with the next problem: i have this hieararchy class "User -> Traveller".
#Entity
#Inheritance(strategy=InheritanceType.JOINED)
public class User {
// Some properties and accessors.
}
#Entity
#PrimaryKeyJoinColumn(name="user_id")
public class Traveller extends User{
// Some properties and accessors.
}
So, i need search a traveller by your username which is a User class property. I try this in my TravellerDao:
public Traveller findByUsername(String username){
EntityManager em = PersistenceHelper.getEm();
TypedQuery<Traveller> query = em.createQuery("FROM Traveller WHERE username = ?1", Traveller.class);
query.setParameter(1, username);
return query.getSingleResult();
}
But, a javax.persitence.NoResultException is catched. Where is the problem ? In the "where" clausule ? In the join ?. Any ideas ?
Notes:
1) The hierarchy works fine with "find" method. And the database is generated correctly.
2) I have an entry in the Traveller table that links up to one in User table.
3) In the database exists an user with the username that i am using to test.
4) The method get correctly the "username" parameter.
EDIT: Now works. The problem was the execution order of test cases. The query works fine.
I think your query is incorrect, I believe you are forced to name an alias for every entity you want to interact with. Have you tried this?
"SELECT t FROM Traveller t WHERE t.username = ?1", Traveller.class
Also you should have to cast the result when you call query.getSingleResult(). Because you pass in Traveller.class into the createQuery call which is paramaterized by Class<T> resultClass
Edit: Added a 1 after the ? as shown here. http://www.objectdb.com/java/jpa/query/parameter#Ordinal_Parameters_index_
public Country getCountryByName(EntityManager em, String name) {
TypedQuery<Country> query = em.createQuery(
"SELECT c FROM Country c WHERE c.name = ?1", Country.class);
return query.setParameter(1, name).getSingleResult();
}