Getting `id` of newly created record after `save()` - fat-free-framework

As per save Cursor Method documentation
This method saves data to the database. The Cursor class automatically determines if the record should be updated or inserted as a new entry, based on the return value of dry.
In case a new record is created how do I retrieve its auto-increment primary key id (this is how my tables are defined) ?
I'm used to look for the mapper instance propery _id but this is undocumented (afaik).
I suppose I can set up an afterinsert() event handler but I was looking for a more straightforward approach. Is there one?

It is very easy and straighforward:
after a save() on a "dry" record (a new record has been created) autoincrement primary keys are updated on the mapper object, so in my case:
$mapper->save();
$id = $mapper->id;

Related

Is JpaRepository.save() suitable for entities with auto generated IDs if we want to UPSERT them?

I'm facing a problem with duplicate records in a MySQL database when I'm upserting using JpaRepository.saveAll() entities which are already present in the database. I want new entities to be inserted, existing ones to be updated(if there are changes to any of the properties), otherwise no action is expected.
The entity classes id property is annotated with #GeneratedValue(GenerationType.IDENTITY) and the id column in the corresponding table in MySQL has auto-increment enabled. I'm pointing that out because JpaRepository.save(), which is invoked for each entity in saveAll(), does a check by id if the entity is already present in the database.
Here is where in my opinion the contradiction between save(), when used for updating, and auto-generation of IDs occurs: You can't update existing records because all of the entities passed into saveAll() will have newly generated IDs and thus the check in save() will always say that they are not present in the database.
Is my logic correct?
The only solution to the problem that I can think of is to create a custom query that compares the records in the database with the newly passed entities by the values of another column whose values are unique. I can't compare them by id because I will encounter the same problem as in save().
Is that good enough and are there any other solutions?
Depending how you look at it, your are either wrong or right.
What you describe in terms of behaviour is correct: If you pass in an entity with id set to null to save you will always create a new row in the database and never perform an update. In that sense you are correct. That behaviour is independent of how the id gets generated for new entities.
But the id of an entity defines its identity. If two entities have the same id they represent the same row in the database thus the same logical entity and the behaviour of save is exactly that of an upsert. This is also independent of how the id gets generated for new entities.
If you want an upsert based on a different column (or columns) you need to write custom code, for example using an actual upsert statement in a query annotation. Alternatively you can try to load the entity by the columns in question and if you succeed set its values as desired and otherwise create a new entity and save that.

JPA/JPQL insertion & fetch in one

I have a table with an INT primary-key that is autoincremented.
I'm looking to get the value of
this key-field for the row I just inserted.
I can do that
1) by using LAST_INSERT_ID()
or
2) merely querying it by the value I inserted.
However, there "feels" to be a more direct way of retrieving that value.
In (1) above, it is giving me the value on the last inserted row-- not necessarily the one i inserted.
In (2), still there is an extra go-between.
I'm using JPA/JPQL on a MySQL database. JPQL does not have INSERT-- I can only do the insertion
directly on the EntityManager. So, I can't combine a query to get the field value. I only can do a query on the same transaction as I've done the insertion is on.
Is there a way of getting around this-- getting the value of the key-field on the row yi've just entered?
//=============================
EDIT:
I am looking to find out how to get the new, autoincremented key once it is there. I'm aware that the key value is incremented & assigned automatically without me having to do anything. I need that key value, because I have a use for it elsewhere.
JPA has support for autogenerated identifiers (which BTW, are the recommended strategy). Just annotate your ID field with
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
and JPA will know that the ID is generated by the database, using an auto_increment column, and will get the last inserted ID for you, transparently.

how to implement unique IDs across many tables

If you look at facebook's graph API, it seems as though all objects share the same ID space, and all Ids are unique even if they are in different tables.
Is there a feature in MySQL that handles this? (if not, high level idea of how to implement?)
You may want to check out UUID(). It returns a globally unique ID so your IDs will never clash.
To convert it to integer format, you can
UNHEX(REPLACE(UUID(),'-',''))
for storing in a BINARY(16) column.
(Source for converting to integer: Nicholas Sherlock's comment at MySQL reference)
If you have a single master database server, you can create a table called Object that has an integer auto-incrementing primary key and an object type column. Every time you create an object, you insert a row into this Object table first, get the id, then use that id to insert a row into whatever table will hold the object information. So to create an Event:
INSERT INTO Object (object_type) VALUES ('Event')
Get the last insert id, let's say it's 12345.
INSERT INTO Event (id, name, location) VALUES (12345, 'Cookout', 'My back yard')
OR use a single sequence to drive the ID values.

Entity Framework 4.2 - How to realize TPT-Inheritance with Database-generated Primarykey Value?

I want to use the EF (4.2) in the following scenario:
There exists a database already (so I chose the database-first approach) and it is a SQL Anywhere DB.
I want to use persistence-ignorant business objects, so I use the DbContext Template to generate POCO classes from the EDM.
There is one simple inheritance hierarchy among my entities: an abstract base entity and two concrete derived entities.
In the database there is one table for each type of the inheritance hierarchy (Table-Per-Type Strategy).
Each of these three tables has a primary key column (Id, type:integer), and the association of a concrete entity to the base entity is done by having the same Id in both tables (that means that the primary key (Id) of the concrete type tables is at the same time a foreign key to the base table; a pretty common approach I think).
I had to define the Inheritance manually in the designer, since the EDM assistant does not automatically recognize, that is want to have an inheritance association between the described entities.
Until this point there wasn't any bigger problem. Now to the issue at hand:
There is a restriction for the database I use: Primarykey values have to be generated by the database, using a database function.
I want to call this function in a before-insert-trigger defined on the base-table.
To let the entity framework know that a value is generated by the database, I set the StoreGeneratedPattern property of the Id Property of the base-entity to Identity (As I understood, this is the way to tell EF to get the generated value after inserting a new instance of an entity).
When I create a new instance of a derived entity, add it to the corresponding DbSet of the DbContext and call SaveChanges on the context, a DbUpdateException is thrown, stating that a foreignkey constraint is violated.
By checking the request-log of the DB, I see that the base entity got inserted in the base table, but on inserting the row in the derived table, the above mentioned error occurs, because it obviously doesn't use the newly generated Id of the new entry in the base table.
Since I don't think there is much I can do on a database level against that, the question is, if the EDM or DbContext can be configured (or modified) to insert the base row first, then take the generated Id and use it for insertion of the derived row.
I know there are several way to avoid this situation (not using inheritance, using a stored procedure to insert a new derived entity, calling the id-generating db-function before inserting and set the Id property myself on the entity), but at the moment the above-described behavior would be the most preferable, so I want to make sure not to overlook something before deciding for any "plan B".
Any suggestions on this topic are much appreciated,
Thanks in advance.
Here is the code of the trigger:
ALTER TRIGGER "TRG_GENERATE_ID" before insert order 1 on
BASE_TABLE
referencing new as NewEntry
for each row
begin
declare NewID integer;
set NewID = F_GET_NEW_ID('BASE_TABLE', NewEntry.SOME_OTHER_ID);
set NewEntry.ID = NewID
end
The function "F_GET_NEW_ID" is called in the trigger to generate the new ID for a new entry in the base table. It has two parameters:
"Tablename" -> The name of the table for which a new ID should be generated,
and a second parameter that takes the value of a standardcolumn in all tables of the database (it is required to generate the new ID).

When are LinqToSql Entity Id's assigned?

Are they assigned at SubmitChanges? or when a new object is created? If the latter, I would imagine there would be collisons?
If the id field is an autogenerated (identity/guid) field, the id is assigned when the record is inserted into the database. LINQToSQL does a select after insert to get the assigned value and updates it in the object. There are no collisions using identity columns as long as you don't turn on allow identity insert. If the id is not autogenerated, then you will be responsible for creating the id and ensuring that there aren't collisions.