typeorm: Unclear documentation: create() doesn't actually insert new row
Issue type:
[ ] question [ ] bug report [ ] feature request [x] documentation issue
Database system/driver:
[ ] cordova
[ ] mongodb
[ ] mssql
[ ] mysql / mariadb
[ ] oracle
[ ] postgres
[x] sqlite
[ ] sqljs
[ ] websql
TypeORM version:
[x] latest
[ ] @next
[ ] 0.x.x (or put your version here)
Steps to reproduce or a small repository showing the problem:
Currently, repository.create() creates new instance of entity, but doesn’t put it into db - you have to manually call repository.save() afterwards so that typeorm would actually run INSERT statement. I think that a lot of developers may not understand it from current documentation, and that it should be said so explicitly to avoid confusion.
(Will submit PR to docs myself if maintainers approve this).
About this issue
- Original URL
- State: open
- Created 6 years ago
- Reactions: 79
- Comments: 58 (11 by maintainers)
@pleerock that’s exactly the place I was talking about. You’re absolutely right that it doesn’t say that it inserts an element into a database, and I did feel like an idiot after I realized my mistake.
However, I don’t think that I’m the only one, and adding a short disclaimer would prevent a lot of other developers from making a similar mistake as me.
I had the same issue, it wasn’t until I read this post that I realised what a dork I am. 😃
I think this problem exist only for people who used sequelize, since
createcreates and saves in there. Can you please tell me where exactly “create” was not explained properly in docs?I know we have this line here.
And this explanation clearly says that
createcreates a new instance of User object and does not tell anything about saving into the database. Maybe you mean another place?Maybe we shall just remove this
createmethod 🤔Maybe a
createAndSavemethod will be great here.I just spent 20mins scratching my head wondering why create is not inserting any records to the DB lol
I find the
createmethod useful, it allows me to easily create multiple instances and skip having to do assignments e.g.can simply be written as:
You can also use arrays to
createmultiple entity instances:I personally find the
createmethod to be a useful shortcut and don’t see where the confusion persists, a quick look at the docs and you can easily work out whats going on.This is very confusing
It’s indeed really confusing. If it is simply an utility function for creating an object instance without interacting with the database, I really don’t see any point that it should exists in TypeORM (especially in the
RepositoryandEntityManager). 😹😈 yeah
createwithoutPromisewill hit DB.Maybe just rename to
createInstanceor just add big note to docs. We havemerge,hasId,getId. It will be shame do not havecreate-like method.@golergka Same here, was really confused by the
savevsinsertfor a moment…I think the
createmethod should be marked as deprecated and removed in a later release. Same withmerge.It’s confusing & provides little value. What other ORM has this?
The examples of its use in this thread can be handled by creating a base entity for your project that has a one line function. For objects, there’s already a mechanism to create a new instance - a constructor.
It seems to mostly have existed as a helper for the internals to create instances & combine instances. Mostly internal subject executor and relationship loader code.
If you’d like to implement it yourself for your entities you can absolutely do that - but on the repository it doesn’t make much sense when you can just as easily set up a constructor or write your own static “create” method that is less prone to errors than this one will be.
@Autognome are you sure it requires all the properties? Pretty sure it doesn’t & you can call save with partials. If you can’t that’s a separate bug.
This works:
@vlapo it has almost zero value. What is the point to do
getRepository(User).create()when you can just donew User()? I have same thoughts aboutmerge, we can use object rest to do same and its much more niceralso,
.creatematches the Create of CRUD, which to me aligns it with “hey, something’s going to happen here”.This needs to be changed immediately. This goes against all conventions and is extraordinarily confusing.
And still prisma is wrong. Having more downloads doesn’t mean that they are right.
They are the ones that need to clarify their documentation. And you should definitely comment on the issue that someone certainly opened there to defend their choice instead of asking TypeORM to explain why they did the correct semantic choice.
In Prisma
createis used to insert a record into a database: https://www.prisma.io/docs/concepts/components/prisma-client/crud. The “Create” in CRUD is analogous to an insert (https://en.wikipedia.org/wiki/Create,_read,_update_and_delete). I’ll agree that in OOPcreateis often analogous tonew, but when talking about DBscreateis strongly associated with an insert.My suggestion: remove it entirely. A repository is supposed to persist and fetch entity of the domain. The domain is the only context able to create an entity.
That typeorm exposes a way to create an entity is a violation to begin with, in my opinion.
Any suggestions other than
createInstance? I would prefer a single, simple and straightforward word.@cour64 Instead of
createthensave, have you tried simplysave? Like:The term
createis analogous to the structural tokennew.Considering a type
Foo,const foo = new Foo();andconst foo = createFoo();are analogous: in both case an instance ofFoois created and assigned to the constantfoo.I’m convinced that nobody would ever expect that
new Foo()actually insert a record into a database. There is no reason whycreateFoowould behave differently as both are exactly the same thing: bothcreateFooandnew Fooare factories to create an instance ofFoo.I think that this thread needs to stop being derailed by persons that try to convince us that the term
createmeans anything else than “create an instance of”. It was never the case. And never will.Very much agree with @pyyding. It’s not obvious to me from the documentation that it doesn’t save at the same time. “Create” is an ambiguous term. For example the manpages of touch say:
“The touch utility sets the modification and access times of files. If any file does not exist, it is created with default permissions.”
and in MySQL “CREATE” creates and saves the new table, it doesn’t just create a table that then needs to be committed/saved.
Regarding the original request I do agree that one shouldn’t create a breaking change, but I think a documentation would be very helpful
@pleerock
.instantiate(?@golergka The semantics of this library are a bit off. I rectify this on my end by creating a class called Model that extends BaseEntity, and have all my models extend Model instead of BaseEntity i.e
In short this allows:
const modelChildInstance = new ModelChild({...data});behavior.Prisma, which gets more weekly downloads than typeorm uses
createto insert a row. You can argue that the semantics ofcreateshouldn’t be to insert a row, but arguing no one should get confused about whether or notcreatewill insert a row (which is effectively what you’re doing) is pretty out of touch. I’ll leave my comments there, because I don’t think this is turning into a very productive discussion.Yes, it would be fundamentally wrong if a library would save a row into a database in response to the creation of a row instance. As I said, nobody would ever argue that such a behaviour is legit with
new Foo.I can’t comment about having a line about this in the documentation but what I can say for sure is that DBAL libraries that insert a row in response to a
createcall are the ones that should add a disclaimer in their documentation because it is a non expected behaviour.TypeORM’s semantic and behaviour are correct here. It is not because other libraries do differently that TypeORM should adapt, especially when the behaviour of those other libraries is highly debatable to begin with.
I fundamentally disagree with this argument.
The purpose is populating entities from objects as described. It is quite useful if you’re accepting JSON and wish to create an entity without saving in the database, mostly because it’s already saved and the request came from a previous call.
Eg think of user authentication where you use jwt tokens to store user data in the token and you don’t wish to query the database every time a user makes a request but you wish to use the already defined entity to work with the user entity. Hence you can reconstruct the entity from an object and use it as if you called find one. Straight forward use case.
Yup, same issue as everyone else here. I just spend 4 hours trying to debug why my test setup was not working until i figured out using a debugger that create does not in fact insert into the DB. This goes against basically every convention of what “create” represents. So no offense you guys - a beautiful ORM all in all, but this is a bad design decision IMHO.
What if you want to create nested instances and then call
savein the main one to do a cascade save in one operation? I think it is useful for creating instances with object’s syntax but it can be confusing so maybe renaming it tocreateInstanceshould be fine.I also was confused by this. Coming from activerecord, I expected that
createwas a combination ofnewandsave.In my use case
createallows me to create an instance with a DTO and then callsaveon that instance, skipping assignments.Using only
saveabove doesn’t work in this case in my experience because it expects all properties of the entity.NOTE: I am a noob developer