Is it possible to write JPQL query like following:
select count(*) > 0 from Scenario scen where scen.name = :name
that would return true/false boolean values depending of whether entity filling criteria exists or not?
I would like to use the query this way:
boolean exists = entityManager.createQuery(query,Boolean.class).setParameter("name",name).getSingleResult();
The query from my example just isn't syntactically correct (parse error), but is there any correct way of doing checks like that in JPQL, that would return boolean value, or is it only possible in Java code?
Yes, it is possible with following:
select case when (count(scen) > 0) then true else false end
from Scenario scen where scen.name = :name
What about just:
select count(scen) > 0
from Scenario scen where scen.name = :name
I was having the same problem, then I updated my hibernate to 4.3.11.Final and now it's working.
I had success with:
#Query(nativeQuery = true, value = "select if(count(name) > 0, 'true', 'false') from Scenario scene where scene.name = :name")
Boolean nameExists(#Param("name") String name);
NOTE: I'm using MySQL with MariaDB
Just use
#Query("select count(scen) > 0 from Scenario scen where scen.name = :name")
Related
I am using MySQL DB with ef core all works fine but the following query does nto return expected result.
var query = _context.ServiceData.
Include(x => x.Country)
.Include(x=>x.Country.CountryLocale)
.Where(x=>x.Country.CountryLocale.Any(l=>l.Locale == "en-US"));
After executing and doing
query.First().Country.CountryLocale.Count // Returns count of greater than 1 when expected count is 1
The table only has 2 entries and the above pulls both when only 1 is expected.
Table Layout
Id Name Locale
1 Test en-US
2 Test en-GB
All examples I have seen seem to suggest doing it how I am doing it so not sure what I am missing.
Here is the sql generated by above Linq
SELECT `a`.`Id`, `a`.`ServiceDataCode`, `a`.`CountryId`, `a`.`Enabled`, `a`.`LastUpdated`, `a`.`TimezoneId`, `c`.`Id`, `c`.`DialingCode`, `c`.`Enabled`, `c`.`IsoNumeric`, `c`.`IsoThreeLetterCode`, `c`.`IsoTwoLetterCode`, `c`.`LastUpdated`, `c0`.`Id`, `c0`.`IsoTwoLetterCode`, `c0`.`LastUpdated`, `c0`.`Locale`, `c0`.`Name`
FROM `ServiceData` AS `a`
INNER JOIN `CountryData` AS `c` ON `a`.`CountryId` = `c`.`Id`
LEFT JOIN `CountryLocale` AS `c0` ON `c`.`IsoTwoLetterCode` = `c0`.`IsoTwoLetterCode`
WHERE EXISTS (
SELECT 1
FROM `CountryLocale` AS `c1`
WHERE (`c`.`IsoTwoLetterCode` = `c1`.`IsoTwoLetterCode`) AND (`c1`.`Locale` = 'en-US'))
ORDER BY `a`.`Id`, `c`.`Id`, `c0`.`Id`
I guess a stored procedure is another option but wanted to do it without.
Well, here is an object query with a right paths of country and specific country locale that belong to first service data:
using (var query = _context.ServiceData
.Include("Country.CountryLocale")
.Where(x => x.ServiceData.CountryId == x.Country.Id)
.Where(x => x.Country.IsoTwoLetterCode == x.Country.CountryLocale.IsoTwoLetterCode)
.Where(x => x.Country.CountryLocale.Locale == "en-US"))
{
query.FirstOrDefault();
}
Hope this helps.
But updation works with below code snippet
Department department= departmentRepository.findOne(300L);
department.setName("rajiv");
departmentRepository.saveAndFlush(department);
but then this scenario being onetone mapping it could be a case where i would end up hitting 3 queries which include 2 select queries and one one update query .
To optimize the way i update it i'm trying to use this approach which is not getting updated thought executeUpdate() returns affected row as 1 .
There is a small mistake in your query.
You have used the = operator instead you should have used the like operator
You can also take help of #NamedNativeQueries
Example
DepartmentRepository.java
#Query(nativeQuery = true)
public List<Department> update(Long id);
Department.java
#SqlResultSetMapping(name="updateResult", columns = { #ColumnResult(name = "count")})
#NamedNativeQueries({
#NamedNativeQuery(
name = "Department.update",
query = "UPDATE departmemnt SET name like 'rajiv' WHERE id = ?",
resultSetMapping = "updateResult")
})
NativeQueries works more faster than normal Hibernate Queries
Yeah may this would help , in case of spring data i found a way to make it updatable and since they insist to use #transactional and extend the functionality of jparepository and now it hits only one line of statement
#Modifying(clearAutomatically = true)
#Transactional(readOnly=false)
#Query("update Department d set d.name =:name where d.id=:id")
int update(#Param("name")String name,#Param("id")Long id);
in case if i choose to for nativeQuery
#Modifying(clearAutomatically = true)
#Transactional(readOnly=false)
#Query(value="update Department d set d.name =:name where d.id=:id",nativeQuery=true)
int update(#Param("name")String name,#Param("id")Long id);
I am struggling with JPQL dynamic where condition. I tried searching the syntax for the same but coluldn't find one.
in my case if user is passing the name parameter then the select query should be
select * from user where name = 'sanjay'
if user is not passing name parameter then select query should be
select * from user
Below is my jpql query format which fails when name parameter is not passed.
entity_manager.createQuery("select u from user u where u.name = :name").setParameter("name",params[:name]).getResultList()
How can i update above JPQL query to support both the cases i.e when the name parameter is passed and when the name parameter is not passed ??
This is not possible in JPQL. You even cannot do something like
createQuery("select u from user u where u.name = :name OR :name IS NULL")
It is not possible. That simple. Use two queries or use the Criteria API.
This is the answer I get when I tries to do like you it is working with some modification.
In my case I had the problem that my optional parameter was a List<String> and the solution was the following:
#Query(value = "SELECT *
FROM ...
WHERE (COLUMN_X IN :categories OR COALESCE(:categories, null) IS NULL)"
, nativeQuery = true)
List<Archive> findByCustomCriteria1(#Param("categories") List<String> categories);
This way:
If the parameter has one or more values it is selected by the left side of the OR operator
If the parameter categories is null, meaning that i have to select all values for COLUMN_X, will always return TRUE by the right side of the OR operator
Why COALESCE and why a null value inside of it?
Let's explore the WHERE clause in all conditions:
Case 1: categories = null
(COLUMN_X IN null OR COALESCE(null, null) IS NULL)
The left part of the OR will return false, while the right part of the OR will always return true, in fact COALESCE will return the first non-null value if present and returns null if all arguments are null.
Case 2: categories = ()
(COLUMN_X IN null OR COALESCE(null, null) IS NULL)
JPA will automatically identify an empty list as a null value, hence same result of Case 1.
Case 3: categories = ('ONE_VALUE')
(COLUMN_X IN ('ONE_VALUE') OR COALESCE('ONE_VALUE', null) IS NULL)
The left part of the OR will return true only for those values for which COLUMN_X = 'ONE_VALUE' while the right part of the OR will never return true, because it is equals to 'ONE_VALUE' IS NULL (that is false).
Why the null as second parameter? Well, that's because COALESCE needs at least two parameters.
Case 4: categories = ('ONE_VALUE', 'TWO_VALUE')
(COLUMN_X IN ('ONE_VALUE', 'TWO_VALUE') OR COALESCE('ONE_VALUE', 'TWO_VALUE', null) IS NULL)
As in Case 3, the left part of the OR operator will select only the rows for which COLUMN_X is equale to 'ONE_VALUE' or 'TWO_VALUE'.
I would like to do a check in my PostgreSQL database with Eclipse Link in a named query and return a boolean. However when I change my count statement (which returns a correct value) to a case statement I get a NoResultException. What is the problem?
Following a simplified example:
#NamedQuery(name = "User.isExistent",
query = "SELECT CASE WHEN COUNT(u) > 0 THEN true ELSE false END
FROM User u WHERE u.someField = :someField")
Usage
TypedQuery<Boolean> query = em.createNamedQuery("User.isExistent", Boolean.class);
query.setParameter("someField", "someFieldValue");
Boolean result = query.getSingleResult();
I'm learning jpa-hibernate basics.
I have this query for getting all users:
CriteriaBuilder cb = getEntityManager().getCriteriaBuilder();
CriteriaQuery cq = cb.createQuery();
cq.select(cq.from(Utente.class));
return getEntityManager().createQuery(cq).getResultList();
Now I want to filter by a boolean field named 'ghost' where it equals true (or false, it depends).
Translated:
SELECT * FROM users WHERE ghost = 0;
Do I have to use cq.where() ? How?
Yes, you have to use cq.where().
Try something like this:
Root<Utente> utente = cq.from(Utente.class);
boolean myCondition = true; // or false
Predicate predicate = cb.equal(utente.get(Utente_.ghost), myCondition);
cq.where(predicate);
Where I have used the canonical metamodel class Utente_ that should be generated automatically. This avoids the risk of making errors in typing field names, and enhances type safety. Otherwise you can use
Predicate predicate = cb.equal(utente.get("ghost"), myCondition);