How can I join three entities in GreenDao? - android

I tried joining the three entities using the example that GreenDao provides here but it gives me an error on the last line under the leadTopersonJoin parameter that says "Type Mismatch, expected Join<*, Lead> found Join< Lead, Person> and I can't figure out how to fix it.
var daoSession: DaoSession = Application.getInstance().daoSession
var queryBuilderLead: QueryBuilder<Lead> = daoSession.leadDao.queryBuilder()
var leadToPersonJoin: Join<Lead, Person> = queryBuilderLead.join(LeadDao.Properties.LeadPersonId, Person::class.java, PersonDao.Properties.PersonLeadId)
var personToAddresJoin = queryBuilderLead.join(leadToPersonJoin, PersonDao.Properties.PersonAddressId, Address::class.java, AddressDao.Properties.AddressPersonId)
What raw Sql can I use to join the three tables? or alternatively what am I doing wrong in the greenDao Query?

Related

Migrate embedded object to separate table. Room

CertificateElementEntity entity had an embedded class ImgData.
I have divided CertificateElementEntityand ImageData into separate tables.
But now I can't figure out how to make the migration.
open class CertificateElementEntity(
#IgnoreJson
#PrimaryKey
#ColumnInfo(name = "local_id")
var localId: Long? = null,
var data: String? = null,
var imageData: ImgData? = null)
Maybe someone made similar migrations
You can try this general migration schema (honestly, I haven't experienced such a migration, so may be there is way easier):
Create temporary table [CertificateElementEntityTemp] with the same structure.
Copy all data from table [CertificateElementEntity] to [CertificateElementEntityTemp].
Drop table [CertificateElementEntity].
Create table [ImgData].
Create table [CertificateElementEntity] with new structure (with just imageId instead all fields from embedded table). Create Foreign Key for [imageId].
Copy needed data from [CertificateElementEntityTemp] to [ImgData].
Copy needed data from [CertificateElementEntityTemp] to [CertificateElementEntity].
Drop table [CertificateElementEntityTemp].
All this of course you should write in migration section with equivalent SQL statements.

Paging library + room not fetching #relation

In an app I'm working on, I need to very simply fetch data from a Room database. There are relations involved. Everything was working perfectly with simple queries returning LiveData, however, the size of the data that needs to be retrieved grew much larger than expected and it also contains blobs (images), which can make the query very slow. I've resolved to using the Paging library, implemented as follows, but for some reason the #relation annotation simply doesn't work anymore.
The entity fetched is a DTO, looks basically like this:
data class EntityOtherAnotherDTO(
var id: Long? = null,
var name: String? = null,
...,
#Relation(parentColumn = "id", entityColumn = "entity_id", entity = OtherEntity::class)
var others: List<OtherEntity>,
#Relation(parentColumn = "id", entityColumn = "entity_id", entity = AnotherEntity::class)
var anothers: List<AnotherEntity>
)
The query:
#Query("SELECT * FROM other
JOIN entity ON entity.id = other.entity_id
JOIN another ON entity.id = another.entity_id
WHERE entity.deleted = 0
ORDER BY
CASE WHEN other.some_column IS NULL THEN 1 ELSE 0 END,
other.some_column ASC,
entity.some_other_column DESC")
fun getAllEntityOtherAnotherDTOs(): DataSource.Factory<Int, EntityOtherAnotherDTO>
When the query was like this: fun getAllEntityOtherAnotherDTOs(): LiveData<List<EntityOtherAnotherDTO>> everything worked just fine. The results were ordered as required and all data was fetched, including the lists annotated with #relation. But after changing the return type to DataSource.Factory and of course implementing a paging adapter, the relations return empty.
The ordering still works perfectly, the query appears to be working exactly as before, the paging also works, but the data is simply missing. All the columns in the entity table are there (name, some_other_column etc.), the relations are the only but major problem.
(I can provide further details about the paging implementation, if that's of any relevance.)
Turns out this is an issue in Room which can happen even when you don't use the Paging library, given a large-ish (hundreds of results+) query.
There is no solution, but there is a workaround for 1:1 relations: using #embedded instead of #relation. That can however complicate things through the need of setting a prefix and enumerating all columns in the query and giving them aliases. That's pain but such is life. Room sucks.
Or if the joined entity doesn't have too many columns and there aren't any duplicate names, it works just as fine to copy those columns/properties in the DTO that is returned by the query.

Room database many to many relation get from couple tables one response

I have three tables Notes, Tags and join table with foreign keys of Note and Tag called NoteTagJoin, but how can I return Note with all Tags as one response?
Here is query to get Note and Tags:
SELECT n.*,t.* FROM notes n INNER JOIN note_tag_join nt ON n.entryId = nt.noteId INNER JOIN tags t ON t.tagId = nt.tagId WHERE n.entryId =:noteId
And here is response class which has to hold note and list of tags:
data class NoteResponse(
#Embedded
var note: Note? = null,
#Relation(parentColumn = "entryId", entityColumn = "tagId", entity = Tag::class)
var tags: List<Tag>? = null
)
But tags list is empty on response just note is there, I know for sure that Tags and Note exists in db and Join table has right foreign keys because all other queries works so my guess is that Query is wrong or NoteResponse class is wrong because I use annotation #Relation which I don't need, but if I don't add #Relation annotation on tags it throws error that room doesn't know what is this list so how to do it? I can't find any references for this, documentation only mentions embedding one class in POJO but no examples for Lists and all similar posts talks only about inserting list.
please see my realization of many-to-many relationship CinemaActorJoinDao
You can instead my code , replace with your , if you have any question , i will try ask to you :)

sqlite select query with foreign key for another table

I am working on a project with xamarin android using the sqlite.net library. I have a select query that will execute and create a collection of custom objects called worker :
var command = conn.CreateCommand("SELECT * FROM tblWorkers");
var results = command.ExecuteQuery<Worker>();
ObservableCollection<Worker> workers = new ObservableCollection<Worker>(results);
return workers;
One of the columns is a foreign key and I need to get a value from that table just wondering what the best way to do that is. The foreign key on the data table tblWorkers is TitleID On that table is a varchar(datatable : tblTitles column : Title - nvarchar) I need to retrieve just wondering what the best way to do that is?
var command = conn.CreateCommand("SELECT * FROM tblWorkers LEFT JOIN tblTitles ON tblWorkers.TitleID = tblTitles.id");
Now, the above will work, but in general you'll want to avoid SELECT * usage. Only get the fields you want. Ideally, something like this...
var command = conn.CreateCommand("SELECT tblWorkers.SomeFieldYouWant, tblWorkers.SomeOtherFieldYouWant, ... , tblTitles.Title FROM tblWorkers LEFT JOIN tblTitles ON tblWorkers.TitleID = tblTitles.id");

Sugar ORM for Android cant find my column name

Well I'm trying to select all entities where entitie_id = *some id*
I do this with this rule:
List<NodeSugar> nodesugars = NodeSugar.find(NodeSugar.class, "entitie_id = ? ", String.valueOf(nodeid));
I know I should get some results back and I get an error.
this error:
E/SQLiteLog﹕ (1) no such column: entitie_id
I know the column exists because I can set it in a different part of code.
Where am I going wrong?
You should be able to query with "entitieid".
Sugar ORM does some conversion when it creates the columns in the tables. Here is a basic example:
String firstName; //creates column first_name
int entitie_id; //creates column entitieid
The documentation only specifies the conversion from camel case to underscore separation. I had to figure the other one out.
You can use NamingHelper.toSQLNameDefault() to wrap column names when building queries. Try:
List<NodeSugar> nodesugars = NodeSugar.find(NodeSugar.class, NamingHelper.toSQLNameDefault("entitie_id") + " = ? ", String.valueOf(nodeid));
NamingHelper is used in the Sugar ORM library to create tables and column names:
https://github.com/satyan/sugar/blob/master/library/src/main/java/com/orm/helper/NamingHelper.java
SugarORM currently uses toSQLName() method of the StringUtil class to generate names for columns
For example in your case:
List<NodeSugar> nodesugars = NodeSugar.find(NodeSugar.class, StringUtil.toSQLName("entitie_id")+" = ? ", String.valueOf(nodeid));
The other and neat way to do it would be to use the Select class:
List<NodeSugar> nodesugars = Select.from(NodeSugar.class).where(Condition.prop(StringUtil.toSQLName("entitie_id")).eq(nodeid)).list();
https://satyan.github.io/sugar/query.html

Categories

Resources