Why does JPQL's "OR" operator narrow result set? - jpa

I have three tables: "User", "Employee" and "Worker". "User" table has one-to-zero-or-one relationship with "Worker" and the same one-to-zero-or-one with "Employee". User entity bean has following mapping attributes:
#OneToOne(cascade = CascadeType.ALL, mappedBy = "user")
private Worker worker;
#JoinColumn(name = "id_employee", referencedColumnName = "id")
#OneToOne
private Employee idEmployee;
My aim is to get all "User" records which have one of this attributes filled (not null). I try to use the query:
SELECT u FROM User u WHERE u.idEmployee IS NOT NULL OR u.worker IS NOT NULL
ORDER BY u.login
I suppose to get 15 records, but I get only 6. I divided this query into two separate:
SELECT u FROM User u WHERE u.idEmployee IS NOT NULL ORDER BY u.login;
SELECT u FROM User u WHERE u.worker IS NOT NULL ORDER BY u.login;
I get 9 and 6 records, respectively. Put together - required 15 records.
It looks like "OR" narrows the result set to only those records, which have worker field not null. Why does it work in such way? Thanks in advance.

The worker association is mapped by a foreign key in the worker table. This means that using u.worker makes an inner join to the worker table, and the is not null is always true. The resulting SQL should look like this:
select u.* from user u, worker w where u.id = w.user_id and w.user_id is not null.
You need to use a left join to accept users having no worker:
select u from User u
left join u.worker w
left join u.employee e
where w is not null or e is not null

i actually had similar problem recently, and it turns out i was using old version of eclipse link, where statements is null and is not null wasn't correctly executed if they were part of and/or statement.
If i remember fix for that was in eclipse link 2.2.0. if you are not using eclipse link, ignore my post.

Related

how to call spring jap query none parameters

I use spring data jpa with native query
I have already some query like this
How to use native query none parameter.
String q="SELECT t1.blockNumber-1 FROM someTAble t1 LEFT JOIN someTAble t2 ON t2.blockNumber = t1.blockNumber-1 WHERE t2.blockNumber IS NULL AND t1.blockNumber> 0 ORDER BY t1.blockNumber";
#Query(value = q,nativeQuery = true)
List<Entity> findByBlockNumberIs();
they are occur errors Column 'sequence' not found.
That query means are when i insert some Contiguous data int value then i find missing data.
But
this query working
SELECT *,t1.blockNumber-1 FROM someTAble t1 LEFT JOIN someTAble t2 ON t2.blockNumber = t1.blockNumber-1 WHERE t2.blockNumber IS NULL AND t1.blockNumber> 0 ORDER BY t1.blockNumber
The difference between the two queries is whether there is a '*' or not
how to change simple to my query.
How to i changed error
OR How to use spring data jpa predicate
QEntity qBe1= QEntity .blockEntity;
QEntity qBe2= QEntity .blockEntity;
build.and(qBe2.blockNumber.eq(be.getBlockNumber()-1))
.and(qBe2.blockNumber.isNull().and(qBe1.blockNumber.gt(0)));
is predicate can use left join?
well...
use this.
List<Integer> findByBlockNumber()

Linq GroupJoin (join...into) results in INNER JOIN?

I am referencing the accepted answer to this question:
LINQ to SQL multiple tables left outer join
In my example, I need all of the Person records regardless if there is a matching Staff record.
I am using the following query (simplified for illustation's sake):
var result = from person in context.Person
join staffQ in context.Staff
on person.StaffID equals staffQ.ID into staffStaffIDGroup
from staff in staffStaffIDGroup.DefaultIfEmpty()
select new PersonModel()
{
ID = person.ID,
Fname = person.Fname,
Lname = person.Lname,
Sex = person.Sex,
Username = staff != null ? staff.Username : ""
};
However, contrary to my expectations, the query results in the following SQL with an INNER JOIN, which eliminates records I need in the the result set.
SELECT
[Extent1].[ID] AS [ID],
[Extent1].[fname] AS [fname],
[Extent1].[lname] AS [lname],
[Extent1].[sex] AS [sex],
[Extent2].[username] AS [username]
FROM [dbo].[Person] AS [Extent1]
INNER JOIN [dbo].[Staff] AS [Extent2] ON [Extent1].[StaffID] = [Extent2].[ID]
I thought that GroupJoin (or join...into) is supposed to get around this? I know I must have made a dumb mistake here, but I can't see it.
In general the query should generate left outer join.
But remember, this is EF, and it has additional information coming from the model. In this case looks like the StaffID property of Person is an enforced FK constraint to Stuff, so EF knows that there is always a corresponding record in Staff table, hence ignoring your left outer join construct and generates inner join instead.
Again, the model (properties, whether they are required or not, the relationships - required or not etc.) allows EF to perform similar smart decisons and optimizations.
Use a Navigation Property instead of a Join. If you're using a Join in EF LINQ you're almost always doing the wrong thing.
Something like
var result = from person in context.Person
select new PersonModel()
{
ID = person.ID,
Fname = person.Fname,
Lname = person.Lname,
Sex = person.Sex,
Username = person.StaffId != null ? Person.Staff.Username : ""
};

JPA query using named parameter from a oneToOne joined table

I am trying to create a query that references fields in the WHERE from both the current table and a table joined on a column. I have no problems creating a query from a single parameter in the Participation table.
#NamedQuery(name="Participation.byUserID", query="SELECT c FROM Participation c WHERE c.userID = :userID")
Here is the fun part... Within the Participation entity, I have a join:
#OneToOne(optional=false)
#JoinColumn(name = "EventID", insertable = false, updatable = false)
private Event event;
The Event entity has some fields I would like to use in my query. For example, eventDate or eventType.
I am wanting something like WHERE Participation.userID = 123 AND Event.eventType = "meeting" using JPA queries instead of SQL. How can I expand the simple named query above to include comparisons from the joined table?
So far I have not been able to get this working, so any help would be appreciated.
This is a really simple requirement, I suggest you go through some basic JPA tutorials.
SELECT c FROM Participation c WHERE c.userID = :userID and c.event.eventType = :eventType

JPA: Querying an object and single values from other entity

Is it possible with JPA to query a database to get an entity filled with an additional field belonging to another table/entity?
I have a reservations table holding a foreign key to a record(an entity) in another table pois which has to columns of interest: poiId and poiType.
Instead of having a field ReservationEntity.poi (to finally obtain poi.poiType) I want to have a ReservationEntity.poiId and ReservationEntity.poiType and I wonder if it's possible to achieve this through a NamedQuery:
#NamedQuery(name="ReservationEntity.findByRfId", query="SELECT r, p.poiType FROM ReservationEntity r LEFT JOIN PoiEntity p ON r.poiId = p.poiId WHERE r.rfId = :rfId")
...since you read my question you can imagine that this DOESN'T work. ;-)
Is it possible to do it in such a kind?
Here's the exception:
Internal Exception: com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: Unknown column 'POITYPE' in 'field list'
Error Code: 1054
Call: SELECT reservationId, endTime, notification, poiId, POITYPE, startTime, status, timeZone, tstamp, type FROM reservations WHERE (reservationId = ?)
bind => [1 parameter bound]
Query: ReadObjectQuery(name="ReservationEntity.findById" referenceClass=ReservationEntity sql="SELECT t1.reservationId, t1.authInfo, t1.endTime, t1.evsp, t1.notification, t1.poiId, t1.POITYPE, t1.startTime, t1.status, t1.timeZone, t1.tstamp, t1.type FROM reservations t1 LEFT OUTER JOIN pois t0 ON (t1.poiId = t0.poiId) WHERE (t1.reservationId = ?)")
at org.eclipse.persistence.exceptions.DatabaseException.sqlException(DatabaseException.java:340)
By now I made it work using a database view instead of a table for the #Entity(...) annotation.
Yet I don't have the requirement to update the entity. However, it is possible to update a view as long as only one table' column are modified and an INNER JOIN is used: http://dev.mysql.com/doc/refman/5.6/en/view-updatability.html

How do I traverse a relationship in a WHERE clause with OpenJPA?

I am new to JPA and OpennJPA. I have two entities UserDmo and SupplierDmo. Each Supplier can have several users and this relationship is established as follws,
In UserDmo,
Column(name="id_supplier")
private long idSupplier;
#ManyToOne(optional=true)
#JoinColumn(name="ID_SUPPLIER")
private SupplierDmo supplier;
In here column ID_SUPPLIER is the FK with referenced by ID column of the SupplierDmo. Using these two entities I tried to obtain result by following query.
SELECT u.id, u.modifiedDate FROM UserDmo u JOIN u.idSupplier s WHERE s.id = 1
But I got, Error message: Attempt to query field "s.id" from non-entity variable "s". Perhaps you forgot to prefix the path in question with an identification variable from your FROM clause?
I really appreciate your help on this
Try something like this :
SELECT u.id, u.modifiedDate FROM UserDmo u WHERE u.supplier.id = 1