How do I read-write foreign keys using ActiveAndroid? - android

In ActiveAndroid, I can build relationships by directly referencing the POJO. For instance, if House had many Windows, this would be fairly straightforward.
Rather than using this direct reference, is there a way to manually set the foreign key and still be able to ActiveAndroid Select later on?
The reason for this is that we are performing data syncing from the server to Android. The data comes in JSON, but rather than being nested the data already comes with foreign keys. I would like to set the foreign keys to our data models without diving too deep into SQLite code.
UPDATE to #ssh's answer:
I am not trying to dynamically change the database structure. Rather, I would like to manually set the foreign key of my models. My assumption is that ActiveAndroid wraps around foreign key queries to directly access other objects that are defined as attributes. Is there a way to access that foreign key table directly?
Thanks for the current answer - I'll look more into setting that value in the foreign key column directly using SQLite.

ActiveAndroid does not support a mechanism for dynamically changing database structure. It is inconvenient, but this is true.
If you want to change your database structure the only way to do that is execute SQLite query.
It can be possible via reflection, using dynamically adding annotation, but Java is not supported this.
For change column name you can use this thread.

Related

Clearing the Auto-Increment value after calling clearAllTables()

Android Room version 1.1.0 now provides the method clearAllTables().
Altough this method is very convenient, it does not clear the auto-increment value generated by the by autoGenerate(), as stated in the official documentation.
I would also like to clear the primary keys of all the tables in my database, without having to call individual queries for each table.
Based on this answer, I would assume that this SQL statement would work:
DELETE FROM sqlite_sequence WHERE name='table1' OR name='table2';
...chaining on as many OR clauses as needed.
However, sqlite_sequence is not a Room-managed table, so you may need to execute this SQL using a SupportSQLiteDatabase. You get one of those by calling getOpenHelper().getWritableDatabase() on your RoomDatabase.
However, I would not bother with this. IMHO, you should not be relying on any particular behavior of AUTOINCREMENT (e.g., always starting from some specific value). In that case, it's unclear what value there is in hacking SQLite to reset these values.

Android Ormlite mapping to Sqlite

I can't find the Ormlite DataType mapping for Android to Sqlite. I've found OrmLite SQL Data Types but the Sqlite column is blank. Anyone know were I can find them?
I need them to update my database schema ie:
meetingDao.executeRaw("ALTER TABLE meeting ADD closed ????");
I'm not exactly sure what you are asking but Sqlite is a type-less database. Everything is stored as a string basically with certain functions allowing numerical, time, etc. calculations at runtime on those strings.
To quote from the Sqlite data-type docs:
SQLite is "typeless". This means that you can store any kind of data you want in any column of any table, regardless of the declared datatype of that column. (See the one exception to this rule in section 2.0 below.) This behavior is a feature, not a bug. A database is suppose to store and retrieve data and it should not matter to the database what format that data is in. The strong typing system found in most other SQL engines and codified in the SQL language spec is a misfeature - it is an example of the implementation showing through into the interface. SQLite seeks to overcome this misfeature by allowing you to store any kind of data into any kind of column and by allowing flexibility in the specification of datatypes.
In the SQL Data Types page you mentioned, the Sqlite column is blank because it uses the base data columns without the need to override them. Even if I changed the base types for a class, Sqlite will not override any of the types because, again, it is a type-less database.
Actually, the mapping table linked by the original question: OrmLite SQL Data Types shows the correct types that ORMLite is using, although it only shows differences for each database from the Base Database column. For example a Java long is created as a column with the BIGINT type.
While SQLite3 doesn't have types, it has the concept of type affinities which ORMLite uses when creating the table.
You should probably include the types in database upgrades as well, or you'll get a different table definition when ORMLite is automatically creating the table form scratch and when you upgrade.

simple messaging database design for text messages

I want to make a simple database model for sms messages , i have the following model is it good or is there a better way to model them .
sms_message(_id,conversation_id,sender_id,time,text)
conversations(_id,last_msg_id,opposite_user_id,msges_counter_inside,has_new_msg_flag)
contacts(_id, display_name)
phone_numbers(user_id,phone_no)
I want to make it as sms message app on android
When designing databases, it is a good practice using singular names for the tables and columns. Otherwise it may cause confusion because when you retrieve records, you do not know if it is for just one object or many, and remember that the columns should be atomic (just one value). So, for example, use phone_number instead of phone_numbers.
Without knowing the hole scenario, the rest of the design seems good, as you separate the different elements in separate tables and relate them. (Do not forget to use foreign keys, primary keys and so on to keep your integrity ok!)

Android: ContentProvider for each table / handling one-to-many relationships

When using a content provider for SQLite database access
Is it better practice to have a content provider for each table or to use one for all tables?
How to handle one-to-many relationships when creating new records?
A ContentProvider is not a database
A ContentProvider is a way to publicly (or semi-publicly) access data as content. This may be done in a number of ways, via file access, SQLite or even web access. A ContentProvider in and of itself is not a database, but you can program a database for it. You may also have multiple ContentProviders accessing the same database, but distributing different levels of access, or the same content in different ways according to the requestor.
What you are really asking is not a ContentProvider question, but a database question "How to handle relationships in an SQLite database" because the ContentProvider doesn't use any database code unless you tell it to via an SQLiteOpenHelper and other similar classes. So, you simply have to program your database access correctly and your SQLite database will work as desired.
A database is a database
In the old days, databases were simply flat files where each table was often its own entity to allow for growth. Now, with DBMS, there is very little reason to ever do that. SQLite is just like any other database platform in this regard and can house as many tables as you have space to hold them.
SQLite
There are certain features that SQLite handles well, some that it handles - but not well, and some that it does not handle at all. Relationships are one of those things that were left out of some versions of Android's SQLite, because it shipped without foreign key support. This was a highly requested feature and it was added in SQLite 3.6.22 which didn't ship until Android 2.2. There are still many reported bugs with it, however, in its earliest incarnations.
Android pre 2.2
Thankfully being SQL compliant and a simple DBMS (not RDBMS at this time), there are some easy ways to work around this, after all, a foreign key is just a field in another table.
You can enforce database INSERT and UPDATE statements by creating CONSTRAINTs when you use your CREATE TABLE statement.
You can query the other table for the appropriate _id to get your foreign key.
You can query your source table with any appropriate SELECT statement using an INNER JOIN, thus enforcing a pseudo-relationship.
Since Android's version of SQLite does not enforce relationships directly, if you wanted to CASCADE ON DELETE you would have to do it manually. But this can be done via another simple SQL statement. I have essentially written my own library to enforce these kinds of relationships, as it all must be done manually. I must say, however, the efficiency of SQLite and SQL as a whole makes this very quick and easy.
In essence, the process for any enforced relationship goes as follows:
In a query that requires a foreign key, use a JOIN.
In an INSERT use a CONSTRAINT on the foreign key field of NOT NULL
In an UPDATE on the primary key field that is a foreign key in another TABLE, run a second UPDATE on the related TABLE that has the foreign key. (CASCADE UPDATE)
For a DELETE with the same parameters, do another DELETE with the where being foreign_key = _id (make sure you get the _id before you DELETE the row, first).
Android 2.2+
Foreign keys is supported, but is off by default. First you have to turn them on:
db.execSQL("PRAGMA foreign_keys=ON;");
Next you have to create the relationship TRIGGER. This is done when you create the TABLE, rather than a separate TRIGGER statement. See below:
// Added at the end of CREATE TABLE statement in the MANY table
FOREIGN KEY(foreign_key_name) REFERENCES one_table_name(primary_key_name)
For further information on SQLite and its capabilities, check out SQLite official site. This is important as you don't have all of the JOINs that you do in other RDBMS. For specific information on the SQLite classes in Android, read the documentation.
As for first question: you don't need to create content provider for every table. You can use in with multiple tables, but the complexity of provider increased with each table.
A Content Provider is roughly equivalent to the concept of a database. You'd have multiple tables in a database, so having multiple tables in your content provider makes perfect sense.
One to many relationships can be handled just like in any other database. Use references and foreign keys like you would with any other database. You can use things like CASCADE ON DELETE to make sure records are deleted when the records they reference in other tables are also deleted.

store and retrieve Vector in Android sqlite database

I need to store an retrieve a vector of an unknown number of objects in an android sqlite database.
Essentially, the setup is this: I am developing a task management app, where the user can add as many notes as they like to their tasks. My current setup uses one database, with one row per task. This presents a problem when I need to associate multiple notes and their associated information with one task. I can see two approaches: try to store an array of notes or a vector or something as a BLOB in the task's row, or have another notes database in which each row contains a note and it's info, as well the id of the task which the note belongs to. This seems a little easier to implement, as all I would have to do to retrieve the data would be to get a cursor of all notes matching a particular id and then iterate through that to display them to the user. However, it seems a little inefficient to have a whole new database just for notes, and it makes syncing and deleting notes a little more difficult as well.
What do you think? Is it worth it to have a separate notes database? Should I use a BLOB or go for the separate database? If a BLOB, are there any good tutorials out there for storing and retrieving objects as BLOBs?
It sounds like you need another table in your database (not another database). You already have a table for Tasks. Now make one for Notes. Make a column be a foreign key into the Tasks table. That is, Notes.Task_ID would hold the ID of the Task that the Note is for. Then when you want to get all of the notes for a task, query the Notes table.
I think the answer to this question really lies in how you're going to go about updating things should they change. For now, the BLOB route probably seems like a really good idea, but what happens if you want to add some new functionality and you want to store some new property of notes (think of things like starred or importance). What would you need to do in order to update the notes object to add this new field? If it's just a database table, it's quite easy to change the layout of the table and even add a default value. If it's a BLOB, you're going to need to go through each entry, de-serialize the BLOB object, fix it, and re-serialize. That could get tricky.
Also, and this probably isn't as important to a small application using an embedded database, but it's easier to modify the database outside of the application if the object isn't a BLOB. Not to mention the queries you'll be able to write with the separate table. For example, how might someone calculate the number of notes that are attached to a task? If it's separated out in the database, it's a simple query.
Just my two cents.

Categories

Resources