Open emilniklas opened 9 years ago
Maybe I'm too java fan, but I would prefer JPA annotations
@luisvt,
I assume that you're talking about the difference between explicit migrations and specifying schema in models? I have considered this and here's my take on it:
I think the reason for mapping rows to objects at all is to decouple the application from the database. Therefore, it should be a priority to reduce the amount of database detail that the classes contain. Personally, I like the idea of having simple data structures that doesn't even depend on the ORM library, and still map database rows to them. However, most of the time we need to configure our models a bit to fit our database needs. To remain non-dependant on the actual database code (with the ability to reuse the models in front end code) annotations can be used.
I still feel like the annotations should be kept at a minimum, and storing the entire schema in the models force them to contain a lot of configuration. And I don't think it's the models responsibility to know that a field should be indexed in the database, for example.
If we store the schema of our rows in the objects that represent them, we lose control over the changes to the schema. Let's say I have a project that is already in production, with a User
class and a users
table with thousands of rows.
If I want to add a column to the users
schema, and I add it to the model (with annotations) then the ORM has to not only realize that something has changed in the schema, but then apply that change without truncating the table.
However, if we have explicit migrations, we can create a new migration that does the schema change, and then just migrate the database on the live server. The migrator will then see that the only migration that is not applied is the one that adds the column, so it knows (and we know) exactly what it should do.
sorry, maybe I didn't explain too well. When I say that I prefer JPA annotations. I mean this:
insteat:
@hasOne
@hasMany
@belongsTo
@BelongsToMany
@BelongsToOne
I prefer:
@OneToOne
@OneToMany
@ManyToMany
@ManyToOne
In Java JPA annotations are not used for migration of the database. However frameworks like Hibernate use them to create a database schema. Most of the time database migrations are done using Liquidbase wich uses XML, YAML, or SQL to do migrations, and also Flyway which is pure SQL.
In JPA they don't use @Field
they use @Column
to refer that the attribute is going to be mapped as column in the table. I don't like using @Column
since is highly tied to SQL dbs. In that case I would prefer @Field
. However this annotation is optional, so an attribute could be mapped to a column without having the annotation.
I see! If a field is annotated with @OneToMany
there is no hierarchy, right?
class Article {
@OneToMany List<Comment> comments;
}
class Comment {
@ManyToOne Article article;
}
what do you mean with hierarchy?
Logically, in a one-to-many relationship with articles and comments, each comment belongs to an article, and each article has many comments. There is a logical hierarchy there that I kind of like.
For example, each comment belongs to an article (article is parent, comment is child). A category can be shared between articles, but can be both the parent and the child (each category has articles, or each article has a category). By using has and belongs we establish a sense of hierarchy between the entities.
I don't know, the idea is quite elusive, but I think the syntax is very expressive. Do you disagree? (Don't get me wrong, I'm all for changing the terminology if you convince me that that's better :smile:)
Take articles and tags for example. I would say articles has tags, and tags belong to articles:
class Tag {
@belongsToMany List<Article> articles;
}
class Article {
@hasMany List<Tag> tags;
}
But with the JPA style that hierarchy is lost:
class Tag {
@manyToMany List<Article> articles;
}
class Article {
@manyToMany List<Tag> tags;
}
To begin with I'm not sure if it is better or not.
In general the annotation @OneToMany
and @ManyToMany
use a parameter called mappedBy
. This parameter is in charge of creating the hierarchy. It would be like this:
class Article {
@OneToMany(mappedBy="owner")
List<Comment> comments;
}
class Comment {
@ManyToOne Article article;
}
or for the case of ManyToMany
class Tag {
@ManyToMany
@JoinTable(
name="TAG_ARTICLE",
joinColumns={@JoinColumn(name="TAG_ID", referencedColumnName="ID")},
inverseJoinColumns={@JoinColumn(name="ARTICLE_ID", referencedColumnName="ID")})
List<Article> articles;
}
class Article {
@ManyToMany(mappedBy="articles")
List<Tag> tags;
}
I think one good point of using JPA annotations is that we would get more traction for JPA developers since it is going to be easier for them to migrate from java to dart.
I think that we should also realease a library called DPA, which contains all the JPA annotations, enumerations and interfaces, but not sure about that.
From looking at this i think we can do a lot better in terms of readability. I also think that attracting Java devs is a good idea but maybe not for a Dart only project. Feel free to fork the ORM and create a JPA style ORM using the underlying Trestle gateway, if you want/can!
I'll keep this in mind and think some more about it!
The ORM is being rewritten. The following is the specification of the target public API.