I'm implementing a small project and I'm wondering if ORMLite supports inverse mapping for #DatabaseMappings. What I am looking for is this similar to JPA's/Hibernates's inverse mapping. Following, hypothetical and rather silly example, a table BlogPost:
#DatabaseTable
public class BlogPost {
#DatabaseField(foreign = true)
private Author owner;
}
and the according Author class, not really that important:
#DatabaseTable public class Author { }
This results in the following SQL (just the relevant parts):
CREATE TABLE blogpost ( ... , owner_id INTEGER NOT NULL, ... )
CREATE TABLE author ( ... )
See how table blogpost now has a foreign key for author. However, I'd prefer it the other way around, i.e. author should have a blogpost_id foreign key. (I told you it was a silly example... ;).
With inverse mapping I could utilize cascades for deletes but I haven't found anything in the ORMlite docs about this. Is it not a feature or am I just missing something?
I'm a bit confused by the question but I thought I'd try to answer it anyway.
I don't understand how that would work #ilikeorangutans. I assume that there are multiple blogposts for a single author? So how could there be a single blogpost_id on the account channel? You could have a join table which contains an author_id and a blogpost_id but that just adds complexity.
If you take a look at this discussion and this webpage, you can see that Hibernate's inverse mapping is about who controls the relationship and is responsible for updating the rows. In both cases, BlogPost would have an author_id and not the other way around.
ORMLite does support the concept of "foreign collections" where you can add a BlogPost to the database by adding it to the collection in the Author object. For more information see the foreign collection documentation.
Sorry if I'm missing something.
Related
I have a User model which can post Comments and vote on them. Comments can also be parented to each other (for nested comments like on HN or Reddit`).
model User {
[...]
// Comments the user has posted
comments Comment[] #relation("UserToComment")
// Comments the user has voted on
upvotedComments Comment[] #relation("_UpvoterToComment")
downvotedComments Comment[] #relation("_DownvoterToComment")
}
model Comment {
[...]
// Comment's author
author User #relation("UserToComment", fields: [authorId], references: [id])
authorId String
// Users who voted on the comment
upvoters User[] #relation("_UpvoterToComment")
downvoters User[] #relation("_DownvoterToComment")
// One-to-many self-relation for nested comments
parentId String?
parent Comment? #relation("Parent", fields: [parentId], references: [id])
children Comment[] #relation("Parent")
}
I have a few questions on how to correctly name these relations.
How should relation that describes the User being an author of several Comments be named:
"UserToComment"?
"Author"?
"CommentAuthor"?
"UserComments"?
I've read somewhere that many-to-many relation names are supposed to start with an underscore (but I'm not sure why, and whether this applies to one-to-many relations as well). How should the relation that describes the multiples Users being upvoters of multiple Comments be named:
"_UpvoterToComment"?
"UpvoterToComment"?
"UserUpvoted"?
"Upvoters"?
Finally, I have a Comment relating to itself for the nested comments. Should this relation be named:
"Parent"?
"Children"?
"ParentChildren"?
"CommentToComment"?
Any of the above but with the underscore in front?
Can you guys help me to understand the correct conventions here, give me some advice on how should name my relations?
General Advice on naming in prisma
Naming is a bit subjective. Normally, I think you should do what makes the most sense for you and your use-case. There are some conventions and rules that Prisma recommends, that you should follow as well:
Convention for model names
Convention for field names
However, there aren't any guidelines on naming relations.
Naming for the specific usecases mentioned
In general, go with whatever you think concisely describes the relationship itself. I can give you my personal opinion about the specific naming questions you brought up:
How should relation that describes the User being an author of several Comments be named:
I think UserComments make sense.
I've read somewhere that many-to-many relation names are supposed to start with an underscore.
This is something that Prisma does internally when automatically generating the underlying SQL. You don't have to worry about this at all, nor should you explicitly add a _ at the beginning of a name.
How should the relation that describes the multiples Users being upvoters of multiple Comments be named:
I would go with Upvoters.
Finally, I have a Comment relating to itself for the nested comments. Should this relation be named:
I would probably go with something like CommentResponses or CommentReplies.
I have two entities Account and Position. The POSITION table and the ACCOUNT table have contents but the POSITION_ACCOUNT table, which I think should have at least one row, is empty. What could I be doing wrong? Here is the relevant code (I am using EclipseLink 2.4.2:
In Position:
#ManyToMany
private List accounts;
In Account:
#ManyToMany(mappedBy = "accounts",fetch=FetchType.EAGER,cascade=CascadeType.PERSIST)
#JoinTable(name="POSITION_ACCOUNT")
Confusing to me and perhaps relevant is that some examples I see annotate the getters and setters but others, as I am doing here, annotate the actual Lists.
It turns out that I needed to specify cascade=CascadeType.PERSIST on both sides of the relationship but there were other application-specific issues along the way. I don't know if reading the original question or this answer will be of much help to anyone. Sorry.
With these Django ORM models:
class A(Model):
pass
class B(A):
pass
The table for B in the resulting schema contains the field:
"a_ptr_id" integer PRIMARY KEY
Just for the sake of better understanding Django's design choices - It there any rationale documentation that mentions what "ptr" signifies?
My only guess is that it's an abbreviation for "pointer", but that seems pretty dumb since essentially any field with a foreign key constraint conceptually resembles a pointer.
It does stand for "pointer", but it's only used specifically for model inheritance in order to point to the parent model. Normal FKs only get "_id".
While creating a schema from a database many-to-many relationships between tables are not created.
Is this a principal problem?
Is it possible to detect from the table structure that many-to-many relationships exist and create the respective code in schema classes automagically?
It is indeed a somewhat fundamental problem -- many_to_many is a "relationship bridge" and not a "relation." The documentation explains that "the difference between a bridge and a relationship is, that the bridge cannot be used to join tables in a search, instead its component relationships must be used."
On the other hand, this means that if the real relationships are correctly discovered it should be straightforward to add the many-to-many relationships automatically: First, search for tables that have two or more has_many relationships. Then, for each pair of such relationships, create a many-to-many relationship bridge. (Of course, one might hope that DBIx::Class would do this itself.)
The problem with developing this kind of code is that many tables that contain multiple references are not many-to-many tables, and have multiple references for other reasons. For instance, I'll make up a schema for some fictional app where something could be regarded as a many-to-many table, when it is not.
create table category (
id primary key,
...
);
create table sub_category (
id primary key,
category references category(id),
...
);
/* EDIT:
This is the table that could be regarded as many_to_many
by an automated system */
create table product (
id primary key,
category references category(id),
sub_category references sub_category(id),
...
);
Something could be built this way for ease of use, without having to do multiple table joins in the database on a website, especially when considering speed. It would be difficult for a piece of code to say definitively 'this is not a many_to_many' situation, while the developer should be able to easily figure it out, and add in the many_to_many line below the checksum.
I consider DBIX::Class schema outputs a good starting point, and little more, especially when working with auto numbering in non-MySQL databases, among other things. I often need to modify above the "Don't modify above this line" stuff (although many_to_many can obviously go below that checksum, of course.
I have a table structure like the following:
Companies Addresses
********* *********
ID ID
AddressID ...
BillingAddressID ...
AddressID and BillingAddressID are foreign keys which are present in the Addresses table. When I generate my model based on this table instead of getting what I would expect to get (the AddressID, BillingAddressID) in the company class. I get the following:
public Addresses Addresses { .. }
public global::System.Data.Objects.DataClasses.EntityReference<Addresses> AddressesReference { .. }
public Addresses Addresses1 { .. }
public global::System.Data.Objects.DataClasses.EntityReference<Addresses> Addresses1Reference { .. }
It seems to be replacing BillingAddress with Addresses1 (not quite sure why that's happening). Also this seems to be common wherever I have a foreign key i.e. instead of the ID I get Table then the TableReference.
I think I can see whats happening i.e. instead of giving me the ID alone, it will be doing a lookup and finding the actual record the ID refers to. However, I am not quite sure what the TableReference field is for....
Can explain this a little better for me?
Thanks in advance.
Relationships are represented as objects in Entity Framework, in the same manner as entities. Even if you are not going to work a lot directly on them, relationship object are first class citizens in EF. EF kreates ObjectStateEntry objects for tracking changes on relationships, just like it does it for entities.
That is why there are two references. First one, AddressesReference is a reference to the relationship object, not the exact entity, and second one Addresses is actual entity.
Peter Chan (link), and Julia Lerman in her book Programming Entity Framework, 1st Edition, say that understanding how relationship works in EF is very important. Also they mention that this is first thing that is confusing developer when they start using EF.
The foreign keys are replaced by a reference to the entity (collection) the foreign key points to.
So to add an address to a company you would do something like:
Address a = new Address();
// ... set variables for address here
currentCompany.Addresses = a;
// or, the other way round (for collections)
a.Companies.Add(currentCompany);
EF uses the table names as the reference point when it builds the model and this is why you see "Addresses" and Addresses1". You can open up the entity model in the GUI format and click on each of the associations. These can be renamed to whatever you like, just click on the reference, view the mapping, ensure it is the one that maps "BillingAddressID" to "BillingAddressID" and rename that reference to "BillingAddress".
Note the current "Addresses" reference may be the one mapping the "BillingAddressID" so you have to check both references.
It would probably be best to change the mapping for "AddressID" to be "Address" instead of "Addresses" if it is a one to one mapping as well.