Doctrine 3: one-to-one Unidirectional relationship doesn't return all fields - orm

I have 2 Entities: Thesis and DoList.
Every DoList belongs to 0 or 1 Thesis. So we have a unidirectional one-to-one relationship from DoList to Thesis. Here is Thesis:
class Thesis
{
/**
* #ORM\Id
* #ORM\Column(type="integer")
* #ORM\GeneratedValue
* #var int
*/
protected int $thesisID;
and DoList:
/**
* #ORM\OneToOne(targetEntity="Thesis")
* #ORM\JoinColumn(name="thesisID", referencedColumnName="thesisID", nullable=true)
*/
protected $thesisID;
Of course i cut down the classes to show only the part that matters.
As far as my understanding is going. #ORM\JoinColumn should join the tables DoList and Thesis on
DoList.thesisID and Thesis.thesisID.
I have no problem persisting thesisID in this relationship but i can't retrieve the value of thesisID when selecting all values from DoList it just always is null.
Edit:
The column names have to be thesisID on both sides.

The error was that i was not joining the tables when using the query builder.
I thought that when doing a query and selecting all rows from a table with query builder doctrine reads the relationship that i specified on the model and does the join query automatically.
NOTE: DOCTRINE DOES NOT AUTOMATICALLY JOIN TABLES WHEN YOU SPECIFY THAT OPTION ON YOUR MODEL. YOU NEED TO DO THE JOIN FUNCTIONALLITY ON QUERYBUILDER.
$qb->select(['u', 'c'])
->from('ThesisNET\Models\DoList', 'u')
->join('u.thesisID', 'c')
->where('u.instructor = ?1')
->setParameter('1', $username);
this is how it eventually worked. (i just added the join option.)

Related

How to get relational data in Symfony?

I have created two Entities.
1. Bookings
2. Restaurants
While generating booking inquiry, user will also select one restaurant from drop down list of all restaurants. So I have set Many2one relation in Bookings Entity.
class Bookings
{
...
/**
* #var int
*/
/**
* #ManyToOne(targetEntity="Restaurants", inversedBy="restaurant_id")
* #JoinColumn(name="restaurant_id", referencedColumnName="id", onDelete="CASCADE")
*/
private $restaurantId;
...
public function __construct() {
$this->restaurantId = new ArrayCollection();
}
...
}
So one restaurant is associated with each booking inquiry and multiple booking inquiries will be associated with every booking.
Now while fetching list of all booking inquiries from controller. I am getting only bookings table details. but how can I also get associated restaurant details like id and res_name along with every booking inquiry.
below is the query for fetching all booking inquiries.
$bookings = $this->getDoctrine()
->getRepository('AppBundle:Bookings')
->findAll();
but this query is returning only booking details not restaurant details, though I have set relationship in bookings entity. How can I get restaurant details along with every booking inquiry automatically in result set.
I can tell you straight away that your ManyToOne looks wrong:
/**
* #ManyToOne(targetEntity="Restaurants", inversedBy="restaurant_id")
* #JoinColumn(name="restaurant_id", referencedColumnName="id", onDelete="CASCADE")
*/
inversedby refers to the property which contains the OneToMany collection, which in your case would not be restaurant_id, it would be bookings.
So correctly:
/**
* #ManyToOne(targetEntity="Restaurants", inversedBy="bookings")
* #JoinColumn(name="restaurant_id", referencedColumnName="id", onDelete="CASCADE")
*/
protected $restaurant; // id not needed here, you're referencing a whole entity in doctrine not a single id
And Restaraunt entity should look something like:
/**
* Booking entity collection
*
* #OneToMany(targetEntity="Booking", mappedBy="restaurant")
*/
protected $bookings;
I recommend you read the association mapping documentation and make sure you have a thorough understanding how relations in doctrine work.
After doing Rnd for an hours, I discovered that the entities were not using PHP annotations, but rather the XML versions. So I added proper relations setting in xml file and its working now.

How to join Two tables of two non relashinship defined columns using Nhibernate QueryOver

Using NHibernate QueryOver, I want to join two tables using two columns which are not defined in the mapping as a relationship.
E.g. This is not my exact scenario but this can explain that
Tables:
Employee(Id, Name, DepartmentId, SomeCode,Address)
Department (Id, Name, ,Code)
Select
SELECT *
FROM EMPLOYEE E
JOIN DEPARTMENT D
ON D.Code = E.SomeCode
Can someone please tell me how to do this query using NHibernate QueryOver. Note that "SomeCode" in Employee and "Code" in Department are not defined as a relationship. DepartmentId is the foreign key and I can join these using JoinAlias but I want it in a somewhat different way.
There are similar questions, e.g.
NHibernate (+ FluentNhibernate) : Join two detached tables
Hibernate Criteria Projection without mapped association of tables
And the answer is:
either use HQL and CROSS JOIN (with WHERE)
There is NO way how to do that with QueryOver/Criteria)
See the doc:
14.2. The from clause
Multiple classes may appear, resulting in a cartesian product or "cross" join.
from Formula, Parameter
from Formula as form, Parameter as param
So using HQL in your case, we can do it like this:
SELECT ...
FROM EMPLOYEE E, DEPARTMENT D
WHERE D.Code = E.SomeCode
...
BUT I would suggest: create that mapping in the code. Simply introduce many-to-one relation. It will be loaded lazily (only if used) and will nicely serve to our needs - be used in QueryOver as a relation for Join
If there is such relation, if this exist in the business object domain, we should not be scared to use it. We can hide it via security etc...

How to avoid unnecessary inner join on a simple query on entity inheritance mapped with JOINED strategy?

I'm using JPA 2 with Hibernate 4.2.0-Final as provider and I have the following entities:
#Entity
#Inheritance(strategy=InheritanceType.JOINED)
public class Person {
#Id
private String id;
.. Person attributes ..
.. Getters/Setters ..
}
#Entity
#Table(uniqueConstraints={#UniqueConstraint(name="UniqueCode", columnNames="code")})
public class Customer extends Person {
#Column(nullable=false)
private String code;
.. Other Customer attributes ..
.. Getters/Setters ..
}
And I have the following JPQL:
SELECT count(distinct c.code) FROM Customer c
For which Hibernate is generating the following SQL:
select
count(distinct customer0_.code) as col_0_0_
from
Customer customer0_
inner join
Person customer0_1_
on customer0_.id=customer0_1_.id
But I only need to count Customers with distinct code, which happens to be a field that is specific to Customer, so there is no need for the inner join to 'Person'. I'd like Hibernate to generate the SQL like follows (i.e. without joinning table 'Person'):
select
count(distinct customer0_.code) as col_0_0_
from
Customer customer0_
Is there a way to tell Hibernate to avoid the unnecessary inner join? Maybe some Hibernate-specific Query Hint?
The JOINED Strategy in JPA uses a separate table for each class in the object hierarchy.
So if you want to load objects for a subclass you also have to load information from the parent class (As the subclass alone does not represent complete picture without the attributes in the parent class). This results in a JOIN when querying for the sub-object.
From the JPA documentation you can see this as being a main disadvantage for The JOINED strategy.
1) Aside from certain uses of the table-per-class strategy described
below, the joined strategy is often the slowest of the inheritance
models. Retrieving any subclass requires one or more database joins,
and storing subclasses requires multiple INSERT or UPDATE statements.

SQL subquery result in LINQ and Entity Framework Code First

I want to make a query that'll return me entities and additionally a number of one of their associated entities. For example:
select *, (select COUNT(*) from Forms where Contact_Id = Contacts.Id)
as FormsCount from Contacts;
My Contact entity has a property named FormsCount, but it isn't mapped since there's no column named like that in the table. Is it possible to write one LINQ query that'll return me Contact entities with the additional FormsCount property filled in?
Alternatively, I'd be happy if I could get the FormsCount values in a separate field and I can copy them to the entities manually. The result from the query could be in this form for example:
{
Contact Contact;
int FormsCount;
}
Then I can iterate over the results and copy FormsCount to Contact. Maybe this can be achieved by using projections?
I know how to do that using 2 queries:
a) fetch contact entities first
b) fetch pairs or contact ID and FormsCount for contacts returned in the first query.
But I'd like to do that using one query. Also, I don't want the FormsCount property to be always filled in my Contact entity, I want to have a control over that. Any ideas?
Thanks,
Michal
You are right about the projection.
If Contact has a navigation property Forms you can project:
from c in context.Contacts
select new { Contact = c, FormsCount = c.Forms.Count() }
If not, you'll have to use a subquery:
from c in context.Contacts
select new
{
Contact = c,
FormsCount = context.Forms.Count(f => f.Contact_Id == c.Id)
}
EF will handle both situations in one SQL query.

JPA #ManyToMany join table indexing

Hibernate allows adding indexes on #ManyToOne mappings by the use of #org.hibernate.annotations.Index.
Is there a way to specify index for the join table in a #ManyToMany relation?
If Entity A and Entity B have a #ManyToMany with A being the owning side, the join table will have a composite index (a1, b1).
I wonder if this is enough, or do I need to create another index (b1, a1)?
Answering a 6 year old question here, still relevant though. I came across this question while facing the same issue. Searching the web makes it look like JPA does not support indexes on join tables but it does, this is documented here.
When using #JoinTable you can specify the indexes on the annotation, for example
#ManyToMany()
#JoinTable(name = "car_driver",
joinColumns = #JoinColumn(name = "car_id"),
inverseJoinColumns = #JoinColumn(name = "driver_id"),
indexes = {
#Index(name = "idx_car_driver_car_id", columnList = "car_id"),
#Index(name = "idx_car_driver_driver_id", columnList = "driver_id")
}
)
private Set<Driver> drivers;
I too am searching for this - the holy grail, it seems.
In this post:
How can I ask Hibernate to create an index on a foreign key (JoinColumn)? an answerer seems to believe that adding #Index to the collection creates an index on the join table. It doesn't.
This post:
How do I create an index on join tables using Hibernate annotations? reveals what I am slowly coming to believe is the horrible truth. It's not possible, unless you revert to using an hbm.xml file to define your entities (ie: doesn't appear to be possible using annotations).
So whilst it does speed up queries tremendously to have a composite index on join tables, encompassing both FK columns, but there is currently no way to create said index automatically using annotations.
I am now looking into creating a task to be used after Hibernate's ExportSchema execution to identify join tables and create indexes. It's not going very well! Please do share any viable solutions you happen to come across. I'm hoping someone will share their approach for comparison.
I thought about it and I find solution. In case of many to many relation I used
#ManyToMany
#JoinTable(name = "core_auth_role",
joinColumns = { #JoinColumn(name = "auth_id") },
inverseJoinColumns = { #JoinColumn(name = "role_id") },
uniqueConstraints = { #UniqueConstraint(columnNames = {"role_id", "auth_id" }) })
#ForeignKey(name = "fk_testkey", inverseName = "fk_testkey_inverse")
private Set<Role> roles;
In result I have two idexes (auth_id, role_id) and (role_id, auth_id).
Schema created by Hibernate:
create table SOME_TABLE (
...
primary key (auth_id, role_id),
unique (role_id, auth_id)
);
primary key and unique cosntrainst are automatically indexed in database.
I came across this https://www.baeldung.com/jpa-many-to-many while looking for a way how to have control over the join table, so that I could have at least one of its keys indexed.
It breaks down the many-to-many relation into a many-to-one relation on the join table side and a typical OneToMany on each of the two associated entities, associating them to the join table, like so:
#Entity
class Student {
#OneToMany(mappedBy = "student")
Set<CourseRating> ratings;
}
#Entity
class Course {
#OneToMany(mappedBy = "course")
Set<CourseRating> ratings;
}
#Entity
class CourseRating {
#ManyToOne
#MapsId("student_id")
#JoinColumn(name = "student_id")
Student student;
#ManyToOne
#MapsId("course_id")
#JoinColumn(name = "course_id")
Course course;
}
The #Index annotation can be used on any of the fields in the CourseRating (join table) entity. In my case I used a composite key on the join entity because of reads on its table, so I actually needed to split the relation.
I hope this can be of help.