IndexedDB - Do I need an "id" field? - indexing

After reading several tutorials I still have problems understanding IndexedDB completely...
I already build a "playground-app" with it, but I have a question before continuing....
Is it recommended to have a distinct "id" field in the ObjectStores?
What happens if object at index 42 (without id-field) needs to be updated? [From what I know IndexedDB doesn't have an update command.] How would you exchange/update this object in-place without breaking the references to this objects?
When you have a id-field - How to find a unused id-value when you add a new object to an ObjectStore? Is there a clever way to do it?
I couldn't find a discussion about this on SO or somewhere else...
cheers!

Using an id is not required but is recommended because it simplifies writing your program. This advice applies to traditional relational databases (SQL) and indexedDB (NoSQL).
Using a simple integer counter is helpful and recommended, even when you have another property or group of properties (a composite/compound primary key) that uniquely identifies each object in a store.
indexedDB provides a way to generate 'unused' id values. Use the autoincrement flag when calling createObjectStore and setting the key path.
See the MDB documentation to learn more. Specifically, review the section on object store keys.
In regards to the 42 question, you can open a cursor, then advance the cursor by 42, and then retrieve the value, change its properties, and then, if the underlying transaction is in readwrite mode, you can call cursor.update to replace the object at the cursor's position. Using this technique is not recommended primarily because it is not practical and can be confusing. It is preferable to use a simple auto-incremented integer id, especially when you are just learning.
It does not matter what the name of the property that represents the key is, so long as it conforms to normal JavaScript object property naming rules, and you access it consistently.

Related

Nullablity of DB generated attributes

I'm working in a Kotlin based project and It force me to deal with any attribute that possibly can hold null. It's nice to find out somewhere nulls are possible while they are not welcome; but I see so much of ?.s and .!!s for attributes that DB generates, e.g. IDs. Maybe I'm abusing that operators?
Is there any convention to mark attribute as not nullable but still have DB generated values here? If I lookup an object It's safe to assume DB generated values are not null anymore. Can VM be made known to this? Maybe by framework or some annotations that language provide?
If your id is generated by the database it is nullable since the JVM/compiler/IDE has no way to know if your entity is already persisted or not.
What you could do though is implement additional methods that are guaranteed to return non-null values by throwing an exception otherwise.

Why use sql tags in struct in some go libs like gorm?

Well I know the necessity of tags in struct in golang and how is it accessed by reflect in golang. But I have searched and could not find a reliable answer to the question of why I should use sql tags in struct while writing struct for sql results. I have explored many sample code and people are using sql:"index" in the struct and sql:"primary_key" in the struct.
Now I have done indexing in the database layer, isn’t it enough? Should I have to use sql:"index" too get the best results? Like so I have defined primary key attribute in the database should I have to specify sql:"primary_key" as well?
My code seems to work fine without those. Just want to know their benefit and usages.
I think you are referring to an ORM library like gorm
In that case, metadata like sql:"primary_key" or sql:"index" will just tell the ORM to create an index while trying to setup the tables or maybe migrate them.
A couple of examples in gorm could be: indexes, primary keys, foreign keys, many2many relations or when trying to adapt an exiting schema into your gorm models, setting the type explicitly, like for example:
type Address struct {
ID int
Address1 string `sql:"not null;unique"` // Set field as not nullable and unique
Address2 string `sql:"type:varchar(100);unique"`
Post sql.NullString `sql:"not null"`
}
Depends on the package you are using and your use-case. Is it enough for CRUD? Almost always, unless the package says so which is often rare but possible. Few packages sometime do under the hood magic which may give rise to bugs. If you are aware of these behaviours, or are quite explicit in your code, you'll probably avoid it.
Indexing tags mostly allows you to use package's migration tools translating your model declaration into sql queries (CREATE statements). So if you always want to do this by yourself, then you probably needn't bother adding such tags.
But you may find yourself a bug if your package requires a tag. For example, in case of gorm, the Model method takes a struct pointer as an input. If this struct has a field named ID it uses it as a primary key, that is, say ID has a value of "4", it will add a WHERE id=4 automatically. In case your struct has ID, you needn't even add a primary_key tag and it will still be treated as one. This behaviour may cause issues when you have both a "non-primary-key" ID field, and another field which you are actually using as the primary key. Another example for gorm is this. A possible behaviour can also be checking for nullable property and throwing an error if an INSERT statement involves a NOT NULL field getting a NULL value.
On a different note, adding tags to your structs can be considered good practice since it gives context of its properties in the DB.

Unique Identifier for NSManagedObject

I have a need to obtain a unique identifier for a type of NSManagedObject I've created. It needs to be available as soon as the object has been created, never change, and be completely unique.
This rules out the NSManagedObjectID, as this can change when the context is saved. I believe the -hash method could be non-unique if my objects have the same properties.
I'd really like to avoid creating an otherwise useless uniqueIdentifier UUID field on the entity as this seems wasteful and messy. Is there an accepted best practice here?
try the URIRepresentation property of NSManagedObjectID. this is very unique ID for the current NSManagerObject but be careful until the NSManagedObject is not saved it gives you a temporary ID only, not a permanent one and they might be different. (I'm just saying it because I don't know for what and how you want to use the unique ID.)
UPDATE #1
this is not an imaginary unique ID only, this is pure unique URL for each individual NSManagedObject (like every file has a unique URL), using them you can find again the original NSManagedObject, after you lost their pointer. I know it is hard to understand, but this is the point of the NSManagedObjectID and its properties.
(if you don't understand how the CoreData and their objects work, you would not downvote the answer. please, read more documentation instead of the pointless downvoting.)
UPDATE #2
according to #NickLocking comment, I would extend the bold part of my answer above:
until saving the NSManagedObjectContext for the the new and still unsaved NSManagedObject classes has a temporary unique ID only. They will get the permanent unique ID after they are saved at first time.
Eventually I have decided that there is no good way to do this, so I just created a uniqueIdentifier field that I apply a UUID to on awakeFromInsert.
Saving the object causes other parts of my application, specifically NSFetchedResultsControllers, to update before I'm finished with the object. I briefly tried NSManagedObjectContext's obtainPermanentObjectIds:withError: method, thinking it would obtain the object IDs without saving the context, but in fact it does simply save the context.
The only unique identifiers provided automatically by CoreData is the object ID, but as you have noted it will change after it is initially created. But before you go coming up with another way to work around this, you might want to consider defining something like the following in your managed object class:
- (NSManagedObjectID *)permID {
if ([[self objectID] isTemporaryID]) {
// Save myself, returning nil if there are errors
}
return [self objectID];
}
This approach isn't perfect by any means, especially if you need to expose the permanent ID before the object is in a state where it is valid and can be saved to the database. But it will allow you to expose a permanent ID in a consistent way as long as you don't need it before the object can be saved.

Should one include ID as a property on objects persisted to a database?

I am creating the model for a web application. The tables have ID fields as primary keys. My question is whether one should define ID as a property of the class?
I am divided on the issue because it is not clear to me whether I should treat the object as a representation of the table structure or whether I should regard the table as a means to persist the object.
If I take the former route then ID becomes a property because it is part of the structure of the database table, however if I take the latter approach then ID could be viewed as a peice of metadata belonging to the database which is not strictly a part of the objects model.
And then we arrive at the middle ground. While the ID is not really a part of the object I'm trying to model, I do realise that the the objects are retrieved from and persisted to the database, and that the ID of an object in the database is critical to many operations of the system so it might be advantageous to include it to ease interactions where an ID is used.
I'm a solo developer, so I'd really like some other, probably more experienced perspectives on the issue
Basically: yes.
All the persistence frameworks ive used (including Hibernate, Ibatis) do require the ID to be on the Object.
I understand your point about metadata, but an Object from a database should really derive its identity in the same way the database does - usually an int primary key. Then Object-level equality should be derived from that.
Sometimes you have primary keys that are composite, e.g first name and last name (don't ever do this!), in which cases the primary key doesn't become 'metadata' because it is part of the Object's identity.
I generally reserve the ID column of an object for the database. My opinion is that to use it for any 'customer-facing' purpose, (for example, use the primary key ID as a customer number) you will always shoot yourself in the foot later.
If you ever make changes to the existing data (instead of exclusively adding new data), you need the PK. Otherwise you don't know which record to change in the DB.
You should have the ID in the object. It is essential.
The easiest use case to give as an example is testing equality:
public bool Equals(Object a, Object b) { return {a.ID = b.ID}; }
Anything else is subject to errors, and you'll find that out when you start getting primary key violations or start overwriting existing data.
By counterargument:
Say you don't have the ID in the object. Once you change an object, and don't have it's ID from the database, how will you know which record to update?
At the same time, you should note that the operations I mention are really private to the object instance, so ID does not necessarily have to be a public property.
I include the ID as a property. Having a simple unique identifier for an object is often very handy regardless of whether the object is persisted in a database or not. It also makes your database queries much more simple.
I would say that the table is just a means to persist an object, but that doesn't mean the object can't have an ID.
I'm very much of the mindset that the table is a means to persist the object, but, even so, I always expose the IDs on my objects for two primary reasons:
The database ID is the most convenient way to uniquely identify an object, either within a class (if you're using a per-table serial/autonumber ID) or universally (if you're maintaining a separate "ID-to-class" mapping). In the context of web applications, it makes everything much simpler and more efficient if your forms are able to just specify <input type=hidden name=id value=12345> instead of having to provide multiple fields which collectively contain sufficient information to identify the target object (or, worse, use some scheme to concatenate enough identifying information into a single string, then break it back down when the form is submitted).
It needs to have an ID anyhow in order to maintain a sane database structure and there's no reason not to expose it.
Should the ID in the object read-only or not? In my mind it should be read-only as by definition the ID will never change (as it uniquely identifies a record in the database).
This creates a problem when you create a new object (ID not set yet), save it in the database through a stored procedure which returns the newly created ID then how do you store it back in the object if the ID property is read-only?
Example:
Employee employee = new Employee();
employee.FirstName="John";
employee.LastName="Smith";
EmployeeDAL.Save(employee);
How does the Save method (which actually connects to the database to save the new employee) update the EmployeeId property in the Employee object if this property is read-only (which should be as the EmployeeId will never ever change once it's created).

Hibernate and IDs

Is it possible in hibernate to have an entity where some IDs are assigned and some are generated?
For instance:
Some objects have an ID between 1-10000 that are generated outside of the database; while some entities come in with no ID and need an ID generated by the database.
You could use 'assigned' as the Id generation strategy, but you would have to give the entity its id before you saved it to the database. Alternately you could build your own implementation of org.hibernate.id.IdentifierGenerator to provide the Id in the manner you've suggested.
I have to agree w/ Cade Roux though, and doing so seems like it be much more difficult than using built in increment, uuid, or other form of id generation.
I would avoid this and simply have an auxiliary column for the information about the source of the object and a column for the external identifier (assuming the external identifier was an important value you wanted to keep track of).
It's generally a bad idea to use columns for mixed purposes - in this case to infer from the nature of a surrogate key the source of an object.
Use any generator you like, make sure it can start at an offset (when you use a sequence, you can initialize it accordingly).
For all other entities, call setId() before you insert them. Hibernate will only generate an id if the id property is 0. Note that you should first insert objects with ids into the db and then work with them. There is a lot of code in Hibernate which expects the object to be in the DB when id != 0.
Another solution is to use negative ids for entities which come with an id. This will also make sure that there are no collisions when you insert an new object.