Define unique columns on ManyToMany in Doctrine - doctrine-orm

I'm trying to add unique columns on a pivot table created via a ManyToMany association.
I found this page of the documentation explaining how to generate a database unique constraint on some columns with this example:
/**
* #Entity
* #Table(name="ecommerce_products",uniqueConstraints={#UniqueConstraint(name="search_idx", columns={"name", "email"})})
*/
class ECommerceProduct
{
}
But this only works if I create the pivot table via a third entity and, in my case, I created the pivot table using a ManyToMany relation (in the same fashion as this code).
Is there a way to add unique columns on pivot table while still using ManyToMany or do I need to rely on a third entity?

While #Table annotation proposes a uniqueConstraints option, #JoinTable does not. Thus, if you want to add a unique constraint on your association table, you will have to actually create another entity explicitly.
That being said, the default join table should not need anything more than the default configuration set up by Doctrine. Currently, when adding a ManyToMany association, the join table is composed of two fields and a composite primary key relying on both fields is created.
If your association table only contains the two basic fields referring to both sides of your association (which is necessarily the case if you use #ManyToMany), the composite primary key should be all you need.
Here is the generated SQL for the basic example where a User has a ManyToMany association with Group (from this section of the documentation):
CREATE TABLE users_groups (
user_id INT NOT NULL,
group_id INT NOT NULL,
PRIMARY KEY(user_id, group_id)
) ENGINE = InnoDB;
ALTER TABLE users_groups ADD FOREIGN KEY (user_id) REFERENCES User(id);
ALTER TABLE users_groups ADD FOREIGN KEY (group_id) REFERENCES Group(id);
As you can see, everything is properly set up with a composite primary key which will ensure that there can't be duplicate entries for the couple (user_id, group_id).

Of course there is another alternative, Alan!
If you need a Zero to Zero relationship, the only alternative is defining the unique constraint per each pk in the agregated table, to make doctrine figuring out about zero to zero relationship.
The problem is that Doctrine's people hadn't considered zero to zero relationships, so the only alternative for this is manytomany relationship with one unique constraint per pk.
If you have doubts about final-state of your doctrine implementation of your E-R model, I strongly recommend mysql-workbench-schema-exporter. With this php tool, you can easily export your mysql workbench E-R schema to a Doctrine's working classes schema, so you would be able to easily explore all your alternatives ;-)
Hope this helps

Related

Django Related Models - magic behind the scenes

I was trying to find the answer in Django Documentation, but failed to do so.
Can anyone please explain how does Django "match" the objects of the related models?
eg. I have two models, and I am showing Django that they are related:
class Reporter(models.Model):
# ...
pass
class Article(models.Model):
reporter = models.ForeignKey(Reporter, related_name='report')
Then the magic happens and Django matches the two models, and adds _id field.
My question is:
How does Django know which objects of those two models are related?
Is it checking each and every field of those objects and sees if there is a match?
EDIT:
How does Django determine that a particular Reporter object is related to a particular Article object?
I understand that when it finds a match it adds the _id field, what I do not understand is based on what django "matches" two objects from different models.
To be more specific:
Let's say that there are two Reporter objects - r1 and r2.
There is one object in Article class - a1
How does django know that a1 is related to r1 and not to r2?
Thanks for your help!
It looks like you're not really SQL-savy, because there's really no "magic" involved and it's all basic relational model design.
Your above models translates to the canonical one to many SQL schema:
CREATE TABLE yourappname_reporter (
id int(11) NOT NULL AUTO_INCREMENT,
PRIMARY KEY(id)
);
CREATE TABLE yourappname_article(
id int(11) NOT NULL AUTO_INCREMENT,
reporter_id int(11) NOT NULL,
PRIMARY KEY(id),
CONSTRAINT `reporter_id_refs_id_XXXX` FOREIGN KEY (`reporter_id`) REFERENCES `yourappname_reporter` (`id`)
);
As you can see, Django adds an 'id' primary key to your models (since you didn't explicitely defined one yourself), and the Article.reporter field translates to the reporter_id foreign key which references reporter.id. Here again Django uses the reporter.id primary key as foreign key reference as a (very sensible) default since you didn't explicitely told him to target another field.
Now when you create a new Article, you have to provide a Reporter instance, ie (assuming you have a reporter with id 1):
reporter = Reporter.objects.get(id=1)
article = Article.objects.create(reporter=reporter)
Then the ORM will issue the SQL query insert into yourappname_article (reporter_id) values (1), hence relating this new article row with this reporter row, and you can now get all articles from reporter 1 with select * from yourappname_article where reporter_id=1 (which is the query Django ORM will issue for Article.objects.filter(reporter_id=1))
To make a long story short: Django ORM is only a thin wrapper over your database, and you do have to know what a relational database is, how it works and how to properly use it (including how to properly design your db schema) if you expect to do anything good. If you don't even know what a foreign key is then by all means first learn about the relational model, proper relational design and basic SQL stuff.

Add a Relation foreign key in AX2012

I have to create 2 new tables: EmployerTypeTable and ListDocTable
------------------- ------------------
-EmployerTypeTable- - ListDocTable -
------------------_1______________________________*__------------------
- - - -
- - - -
------------------- ------------------
An object of EmployerTypeTable can have many objects of ListDocTable (one to many)
How can I implement this in AX2012?
How to: Create Tables
How to: Add a Relation to a Table
The initial steps for adding a relation are the same regardless of the relation type that you are adding. The later steps diverge based on the relation type.
Remember to save your changes in the AOT.
In the AOT, move to Data Dictionary > Tables, and then expand the table that the relation will be added to.
Right-click the Relations node, and then select New Relation.
Right-click the newly added relation, and then select Properties.
Set the name of the new relationship by modifying the Name property.
In the Table property, select the related table.
Use the Validate property to determine whether the relation should be used to validate data when information is entered into forms.
Right-click the new relation, select New, and then click one of the following:
Normal to specify relation fields without conditions.
Field fixed to specify relation fields to restrict the records in the primary table.
Related field fixed to specify relation fields that restrict the records in the related table.
ForeignKey to specify a correspondence between a foreign key field in the present table to the primary key field in another parent table.
Proceed to the subsection that corresponds to the relation type that you selected in the earlier step.

How to relationship with mysql table in QT QSqlRelationalTableModel?

I am trying to work with QSqlRelationalTableModel of QT. I am new to MySQL table relationship but still I tried and can't make it work properly in QT.
I can get the result from MySQL:
create table stu(idd int auto_increment primary key,stu_name varchar(60),stu_age int);
create table stuInfo(idd int auto_increment primary key,stu_city varchar(60),stu_sub varchar(100), foreign key(id) references stu(id));
select stu.stu_name,stuInfo.stu_city from stu inner join stuInfo on stu.id=stuInfo.id;
To retrieve data from MySQL :
select stu.stu_name,stuInfo.stu_city from stu inner join stuInfo on stu.id=stuInfo.id;
In QT I can't make it work. I am getting confused with setRelation() and QSqlRelation() . I am not exactly understanding that how I can execute the same query in QT, I tried it in various way but sometime I get blank data, ugly header, errors etc.
Here is my learning code:
model = new QSqlRelationalTableModel();
model->setTable("stu");
model->setRelation(0,QSqlRelation("stu","id","stu_name","stu_age"));
model->setRelation(0,QSqlRelation("stuInfo","id","stu_city","stu_sub"));
model->select();
ui->tableView->setModel(model);
A QSqlRelation replaces the value of a field by the value of the other field in the relation, the replaced field won't appear in the query anymore, so you can't have 2 relations assigned to the same column, and you can't assign a relation to the primary key (as stated in the documentation of setRelation).
Basically the structure for which QSqlRelationalTableModel should be used would be a main table which would have 1 or more foreign index fields, and each of these fields could be replaced by the value of a chosen field in the tables from which the foreign indexes comes from (e.g.: to replace a "city_id" numerical field in the main table by the name of the city coming from another table for which that "city_id" is the primary key).
For what you want to do, you should use QSqlQueryModel with a manually constructed query instead of QSqlRelationalTableModel.
The problem is that your code does not really express the model you described.
You have a primary table called stuInfo, which references another table called stu.
To do this in Qt, you should create a table based on "stuInfo" (and not "stu"!):
model=new QSqlRelationalTableModel();
model->setTable("stuInfo");
Then you can implement your foreign key, as a relation:
model->setRelation(3,QSqlRelation("stu","id","stu_name"));
You need to point to index "3", which is the position of the reference field "id", on stuInfo table (0 will point to the primary key, which is not what you want!). The parameters of the QsqlRelation are the reference table name ("stu") the primary field name ("id") and the reference table field to which you want to point: in this case I am pointing to "stu_name"; if I wanted to point to the age, I could do something like this instead:
model->setRelation(3,QSqlRelation("stu","id","stu_age"));
After this code:
model->select();
ui->tableView->setModel(model);
you should have a view that shows you all the fields on stuInfo, and whose last field ("id") is mapped to the name (or age) on the "stu" table;

django models complex query

I have 3 tables say, TextObj, User, SecurityCheck. The third table has a Foreign Key attribute (textobj) referencing TextObj and there is a many-to-many field (sharedWith) from SecurityCheck to User.
class SecurityCheck(models.Model):
textobj=models.ForeignKey(TextObj)
owner=models.CharField(max_length=255)
sharedWith=models.ManyToManyField(User)
def __init__(self,owner,filename,requestingUsername):
self.owner=owner
self.textobj=TextObj.filter(filename=filename)
self.sharedWith.add(User.objects.filter(username=requestingUsername))
I need to do a query which fetches all the instances of Textobj which have a particular user in the sharedWith field and a particular filename(which is an attribute of TextObj)
You can easily do queries that span (reverse) relationship:
TextObj.objects.filter(securitycheck__sharedWith=user, filename="foo")
https://docs.djangoproject.com/en/dev/topics/db/queries/#lookups-that-span-relationships
Django offers a powerful and intuitive way to “follow” relationships in lookups, taking care of the SQL JOINs for you automatically, behind the scenes. To span a relationship, just use the field name of related fields across models, separated by double underscores, until you get to the field you want.
It works backwards, too. To refer to a “reverse” relationship, just use the lowercase name of the model.

Open JPA how do I get back results from foreign key relations

Good morning. I have been looking all over trying to answer this question.
If you have a table that has foreign keys to another table, and you want results from both tables, using basic sql you would do an inner join on the foreign key and you would get all the resulting information that you requested. When you generate your JPA entities on your foreign keys you get a #oneToone annotation, #oneToMany, #ManyToMany, #ManyToOne, etc over your foreign key columns. I have #oneToMany over the foreign keys and a corresponding #ManyToOne over the primary key in the related table column I also have a #joinedON annotation over the correct column... I also have a basic named query that will select everything from the first table. Will I need to do a join to get the information from both tables like I would need to do in basic sql? Or will the fact that I have those annotations pull those records back for me? To be clear if I have table A which is related to Table B based on a foreign key relationship and I want the records from both tables I would join table A to B based on the foreign key or
Select * From A inner Join B on A.column2 = B.column1
Or other some-such non-sense (Pardon my sql if it is not exactly correct, but you get the idea)...
That query would have selected all column froms A and B where those two selected column...
Here is my named query that I am using....
#NamedQuery(name="getQuickLaunch", query = "SELECT q FROM QuickLaunch q")
This is how I am calling that in my stateless session bean...
try
{
System.out.println("testing 1..2..3");
listQL = emf.createNamedQuery("getQuickLaunch").getResultList();
System.out.println("What is the size of this list: number "+listQL.size());
qLaunchArr = listQL.toArray(new QuickLaunch[listQL.size()]);
}
Now that call returns all the columns of table A, but it lack's the column's of table B. My first instinct would be to change the query to join the two tables... But that kind of makes me think what is the point of using JPA then if I am just writing the same queries that I would be writing anyway, just in a different place. Plus, I don't want to overlook something simple. So what say you stack overflow enthusiasts? How does one get back all the data of joined query using JPA?
Suppose you have a Person entity with a OneToMany association to the Contact entity.
When you get a Person from the entityManager, calling any method on its collection of contacts will lazily load the list of contacts of that person:
person.getContacts().size();
// triggers a query select * from contact c where c.personId = ?
If you want to use a single query to load a person and all its contacts, you need a fetch in the SQL query:
select p from Person p
left join fetch p.contacts
where ...
You can also mark the association itself as eager-loaded, using #OneToMany(lazy = false), but then every time a person is loaded (vie em.find() or any query), its contacts will also be loaded.