My Querybuilder statement looks like this:
$qb->from('models\Order', o');
$qb->innerJoin('o.fStatus', 'fs');
$qb->select('COUNT(o.id), PARTIAL fs.{name, id}');
If I run this I get the error
SELECT COUNT(o.id),': Error: Cannot select entity through identification variables without choosing at least one root entity alias.
However, if I change my select statement to either of these:
$qb->select('PARTIAL o.{id}, PARTIAL fs.{name, id}');
$qb->select('COUNT(o.id), fs.name, fs.id');
The query will run.
Why can I not select from the root entity and also a partial object that has been joined to it?
Doctrine gives a bit of explanation in their documentation:
A common mistake for beginners is to mistake DQL for being just some form of SQL and therefore trying to use table names and column names or join arbitrary tables together in a query. You need to think about DQL as a query language for your object model, not for your relational schema.
When you select using DQL or the QueryBuilder, it is traditionally expecting you to select the root entity (the one in your FROM clause), or some combination of columns/aggregates (COUNT, SUM, etc.). When you select a partial object from a joined table but don't select the root entity, Doctrine doesn't know how to hydrate - what if there is a one-to-many/many-to-one, how does it return the data? It won't make those assumptions.
Doctrine by default does not allow partial objects. It seems like you would be better off just returning columns for your query since that's really what you're looking for in that case.
Others have worked around the issue using the WITH clause - see Doctrine query distinct related entity.
Related
I have some difficulties in DQL (and SQL !). I always write simple querys but now I need something more specific and I don't know how to do it.
I have an entity User in OneToMany with my entity Program which is in OneToMany with my entity Exercice which is in OneToMany with my Reps.
I would like to know for an specific User all the reps is done.
What would be the best way to do it ?
$this->createQueryBuilder('user')
->select('rep')
->join('user.programs', 'program')
->join('program.exercices', 'exercice')
->join('exercice.reps', 'rep')
->getQuery()
->getResult();
Explication:
This code must be in your repository. The user repository one.
$this->createQueryBuilder('user')
is equivalent to
$this->_em->createQueryBuilder()
->select('user')
->from('user')
You can override the select with the second line:
->select('rep')
Then do the join as described in your question.
programs must be the entity attribute you defined in user to join program
Same goes for exercices and reps. They correspond to the inversed side of the relationship.
The second paramter in join() function is the alias. It can be anything you want. You use aliases in select and in the next join()
I am trying to build a query via query builder.
$photosQuery = $photoRepository->createQueryBuilder('p')
->join('AppBundle:User', 'u')
->where('LOWER(p.title) LIKE :phrase OR LOWER(u.username) LIKE :phrase AND p.isActive = :isActive AND p.isModerated = :isModerated')
->setParameter('phrase', '%'.strtolower($phrase).'%')
->setParameter('isActive', true)
->setParameter('isModerated', true)
->getQuery();
It gives me
SELECT p0_.id AS id_0,
p0_.title AS title_1,
p0_.description AS description_2,
p0_.name AS name_3,
p0_.creation_date AS creation_date_4,
p0_.edit_date AS edit_date_5,
p0_.is_moderated AS is_moderated_6,
p0_.moderation_date AS moderation_date_7,
p0_.is_active AS is_active_8,
p0_.user_id AS user_id_9,
p0_.category_id AS category_id_10
FROM photos p0_
INNER JOIN users u1_ ON (LOWER(p0_.title) LIKE ?
OR LOWER(u1_.username) LIKE ?
AND p0_.is_active = ?
AND p0_.is_moderated = ?)
Why are my WHERE parameters in the join ON() portion and not a traditional WHERE?
Thank you!
Doctrine provides a wrapper around lower-level database connections that to not necessary have all the features present in DQL. As such, it emulates some features (such as named parameters, or splitting array parameters into multiple separate values).
You're seeing that in action here: the named parameters are converted into positional parameters in the raw query. Doctrine still knows what the mapping is, though, and is able to correctly order them when the query and parameters are sent to the server.
So the answer from jbafford explained some information Doctrine but did not explicitly answer why the ON was used instead of the WHERE, and it stems from a common mistake (of which I recently made as well).
In your query, when you use
->join('AppBundle:User', 'u')
you are simply telling the query builder that you need to join on the User table, but it doesn't specifically know that you want to join on the user association of your Photo entity. You may think - why doesn't this happen automatically? Well, imagine if you had 2 another association on your table that linked to a User entity as well (maybe a createdBy field or similar). In that case Doctrine wouldn't know the association you wanted.
So, instead the proper thing to do is join directly on your association rather than generically on the entity, like so:
->join('p.user', 'u')
and then Doctrine will handle the rest. I couldn't actually tell you why it uses the where() condition for the join, unless it's just assuming that's what you wanted, since it needs to know how to join on something.
So just remember that when you are joining on an association you already defined, join on the association as described in your entities rather than thinking of it in a straight SQL format where you'd join on the table.
You have a query say :-
select p from profiles p, group g where p.profileId = g.profileId
How will you implement it using JDO. It could be basic but I am new to JDO and was not able to goolge something meaningful.
In JDOQL you dont really have something like a JOIN. As #sihaya mentioned, retrieving a object will also fetch all of its members (depending on the configured fetch type ("eager" will load everything and "lazy" will load it later))
Looking at the docs, you can use something similiar, called "unbound variables":
Unbound variables, which serve as a replacement for the JOIN operation of SQL
Unbound variables are supported by ObjectDB, but considered optional by JDO. Queries with unbound variables are similar to JOIN queries in SQL because every combination of variables has to be checked for every candidate object. Just like JOIN queries in SQL, queries with unbound variables may become very slow, so caution is needed when using them.
Here is the link: https://www.objectdb.com/database/jdo/manual/chapter7
In JDO and other object-relational mapping frameworks such as JPA the join condition for a relation between two entities is inferred from the meta-model.
In your example you presumably have two entities Profile and Group and a n-1 relationship from Group to Profile. Then given the following entities:
#PersistenceCapable
public class Group {
private Profile profile;
...
}
and
#PersistenceCapable
public class Profile {
...
}
Executing the following JDO query will select all profiles that are referenced by a group:
select g.profile from Group g
I am currently using Symfony2 and Doctrine2 and am trying to join two tables together using query builder.
The problem I have is that all my annotated entities do not have the table relationships setup. I will at some point address this, but in the mean time I need to try and work round this.
Basically I have two tables: a product table and a product_description table. The product table stores the basic information and then I have a product_description table that stores the description information. A product can have one or more descriptions due to language.
I want to use query builder, so I can retrieve both the product and product_description results as objects.
At the moment I am using the following code:
// Get the query builder
$qb = $em->createQueryBuilder();
// Build the query
$qb->select(array('p, pd'));
$qb->from('MyCompanyMyBundle:Product', 'p');
$qb->innerJoin('pd', 'MyCompanyMyBundle:ProductDescription', 'pd', 'ON', $qb->expr()->eq('p.id', 'pd.departmentId'));
$query = $qb->getQuery();
$products = $query->getResult();
This gives me the following error:
[Syntax Error] line 0, col 71: Error: Expected Doctrine\ORM\Query\Lexer::T_DOT, got 'MyCompanyMyBundle:ProductDescription'
Can anyone point me in the right direction? I am up for doing it differently if there is an alternative.
Without having the relationships defined, I don't think you can join the tables. This is because when you use DQL, you're querying an object rather than a table, and if the objects are unaware of each other, you can't join them.
I think you should look at using a NativeQuery. From the docs:
A NativeQuery lets you execute native SELECT SQL statements, mapping the results according to your specifications. Such a specification that describes how an SQL result set is mapped to a Doctrine result is represented by a ResultSetMapping. It describes how each column of the database result should be mapped by Doctrine in terms of the object graph. This allows you to map arbitrary SQL code to objects, such as highly vendor-optimized SQL or stored-procedures.
Basically, you write raw SQL, but tell Doctrine how to map the results to your existing entities.
Hope this helps.
I am facing a big problem with simple linq query.. I am using EF 4.0..
I am trying to take all the records from a table using a linq query:
var result = context.tablename.select(x=>x);
This results in less rows than the normal sql query which is select * from tablename;
This table has more than 5 tables as child objects (foreign key relations: one to one and one to many etc)..
This result variable after executing that linq statement returns records with all child object values without doing a include statement..
I don't know is it a default behavior of EF 4.0 ..
I tried this statement in linqpad also..but there is no use...
But interesting thing is if I do a join on the same table with another one table is working same is sql inner join and count is same..but I don't know why is it acting differently with that table only..
Is it doing inner joins with all child tables before returning the all records of that parent table??
please help me..
This table has more than 5 tables as
child objects (foreign key relations:
one to one and one to many etc)..
This result variable after executing
that linq statement returns records
with all child object values without
doing a include statement..
So we are probably talking about database view or custom DefiningQuery in SSDL.
I described the same behavior here. Your entity based on joined tables probably doesn't have unique identification for each retruned row so your problem is Identity map. You must manually configure entity key of your entity. It should be composite key based on all primary keys from joined tables. Entity key is used to identify entity in indenty map. If you don't have unique key for each record only first record with the new key is used. If you didn't specify the key manually EF had infered its own.
The easiest way to troubleshoot these types of issues is to look at the generated SQL produced by the ORM tool.
If you are using SQL Server then using the SQL Profiler to view the generated SQL.
From what you are describing, a possible explanation might be that your relationships between entities are mandatory and thereby enforcing INNER joins instead of LEFT OUTER joins.