F# linq filter column by null value - entity-framework

in F# query can't make filtering by null work
role.CompanyId is nullable column
query {
for role in roles do
where (role.CompanyId = null)
select role
}
Compiler gives error Solution api.sln
Project Roles.Domain
Roles\Roles.Domain\CompanyRoles\R.fs:66 The type 'Nullable<int>' does not have 'null' as a proper value. To create a null value for a Nullable type use 'System.Nullable()'.
Can somebody help ?

This works
query {
for role in roles do
where (role.Company = null)
select role
}

Related

JPA Criteria on PostgreSQL boolean type creates invalid query

I have a regular JPA Entity which has a boolean field:
#Entity("UserAccount")
public class UserAccount {
...
#Column(name = "isActive")
private boolean isActive = false;
...
}
This is backed by a table in PostgreSQL 15. In the table definition, the field is of type BOOLEAN (not integer!):
CREATE TABLE UserAccount(
...
isActive BOOLEAN NOT NULL,
...
)
When I attempt to use the JPA Criteria API with it:
criteriaBuilder.isTrue(root.get("isActive"))
... then it will be rendered as = 1 in the SQL query which is sent to PostgreSQL:
SELECT ...
FROM UserAccount
WHERE isActive = 1
PostgreSQL rejects this query with the following error (which is pretty clear):
PSQLException: ERROR: operator does not exist: boolean = integer
Hint: No operator matches the given name and argument types. You might need to add explicit type casts.
My question is: how can I tell Hibernate that I'm using an actual PostgreSQL-native BOOLEAN type in my table instead of encoding the boolean as a number?

How to formulate JPQL query with or without parameter?

For example take this jpql query -
#Query("SELECT account.name, account.type From AccountEntity account WHERE account.id=:accountId")
getAccountNameById(#Param(accountId) int accountId); //i know Spring Data Derived Query can handles this automatically - but lets not use this for this discussion.
in the above jpql query, if no accountId is passed, i want to select records for all accountId's. Is it possible. I know i can use another query - getAllAccounts() and call it from service layer based on accountId is present or not. But I have to handle it from repo in this case.
So is it possibel that JPQL returns all records when parm value is missing or null.
A little bit late but...
In this example the 1st WHEN is going to evaluate :accountId
if it's null then the query is going to return all elements,
in the 2nd WHEN if :accountId is not null then is going to return all elements
where account.id = :accountId
SELECT account.name, account.type FROM AccountEntity account
WHERE CASE WHEN :accountId IS NULL THEN TRUE
WHEN :accountId IS NOT NULL AND account.id = :accountId THEN TRUE ELSE FALSE END
test if parameter is null
SELECT account.name, account.type From AccountEntity account WHERE (:accountId is null or account.id=:accountId)

Default return value for JPA query

I have a JPA query
#Query(value = "SELECT SUM(total_price) FROM ... WHERE ...", nativeQuery = true)
which works as expected when there are matching records. But when there are no matching records, the query returns null.
How can I return zero(0) instead of null when no records are found?
You can change return type to be an Optional;
#Query(value = "SELECT SUM(total_price) FROM ... WHERE ...", nativeQuery = true)
Optional<Integer> getSum(...);
Or you can wrap this getSum() with a default method;
#Query(..)
Integer getSum(...);
default Integer safeGetSum(..) {
return Optional.ofNullable(getSum(..)).orElse(0);
}
More info on null handling in repositories
When the return value is not a list, or some wrapper (plus some others check below), & there are no matching records, the return will be null, so there is no slick way to handle this with some defaultValue=0 through #Query
The absence of a query result is then indicated by returning null. Repository methods returning collections, collection alternatives, wrappers, and streams are guaranteed never to return null but rather the corresponding empty representation.
A native SQL option is COALESCE which returns the first non-null expression in the arg list
SELECT COALESCE(SUM(total_price),0) FROM ...

JPA Criteria "IS NULL OR NOT IN"

I am trying to build the CriteriaQuery equivalent of the following SQL where clause, using OpenJPA 2.4.0:
where employee_status is null or employee_status not in ('Inactive','Terminated')
I have created a list of employeeStatuses, and this is how I am adding the predicate:
predicates.add(
criteriaBuilder.or(
criteriaBuilder.isNull(domainEntity.get("employeeStatus")),
criteriaBuilder.not(domainEntity.get("employeeStatus").in(employeeStatuses))
)
);
The generated SQL looks like this:
AND (t0.EMPLOYEE_STATUS IS NULL OR NOT (t0.EMPLOYEE_STATUS = ? OR t0.EMPLOYEE_STATUS = ?) AND t0.EMPLOYEE_STATUS IS NOT NULL)
As you can see, the 'not in' statement is being transformed into multiple comparisons, with 't0.EMPLOYEE_STATUS IS NOT NULL' added at the end. In order for this to work, the translated clause should be contained in another set of parenthesis.
Any ideas about how I can get this to work?

JPQL: How to write dynamic where conditions

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'.