I have a Client bean ,
#DatabaseField(columnName = "client_id",generatedId = true,useGetSet = true)
private Integer clientId;
#DatabaseField(columnName = "client_nom",useGetSet = true)
private String clientNom;
#DatabaseField(columnName = "city_id",foreign = true,useGetSet = true)
private City city;
and a City bean ,
#DatabaseField(columnName = "city_id",generatedId = true,useGetSet = true)
private Integer cityId;
#DatabaseField(columnName = "city_name",useGetSet = true)
private String cityName;
#ForeignCollectionField
private ForeignCollection<Client> clientList;
Those beans are just an example but let's say , I want to delete all the clients having as foreign city cityId when deleting a city.
How is that possible please ?
ORMLite does not support cascading deletes #Majid. That is currently outside of what it considers to be "lite". If you delete the city then you need to delete the clients by hand.
One way to ensure this would be to have a CityDao class that overrides the delete() method and issues the delete through the ClientDao at the same time. Something like:
public class CityDao extends BaseDaoImpl<City, Integer> {
private ClientDao clientDao;
public CityDao(ConnectionSource cs, ClientDao clientDao) {
super(cs, City.class);
this.clientDao = clientDao;
}
...
#Override
public int delete(City city) {
// first delete the clients that match the city's id
DeleteBuilder db = clientDao.deleteBuilder();
db.where().eq("city_id", city.getId());
clientDao.delete(db.prepare());
// then call the super to delete the city
return super.delete(city);
}
...
}
To implement cascading while using ORMLite on Android you need to enable foreign key restraints as described here:
(API level > 16)
#Override
public void onOpen(SQLiteDatabase db){
super.onOpen(db);
if (!db.isReadOnly()){
db.setForeignKeyConstraintsEnabled(true);
}
}
For API level < 16 please read:
Foreign key constraints in Android using SQLite? on Delete cascade
Then use columnDefinition annotation to define cascading deletes. Ex:
#DatabaseField(foreign = true,
columnDefinition = "integer references my_table(id) on delete cascade")
private MyTable table;
This is assuming the table/object name is "my_table", as described here: Creating foreign key constraints in ORMLite under SQLite
Related
How to retrieve all the SQL queries generated by Room Android?
My Dao class:
#Dao
public interface MyDao {
#Query("SELECT * FROM user WHERE age > :minAge")
public User[] loadAllUsersOlderThan(int minAge);
}
I want to retrieve the content of #Query annotation.
I know I can use an annotation processor but this does not allow me to retrieve the queries used to create database tables and the one generated from #Insert, #Update, and #Delete.
I want to reuse those queries in another app with sqlite3 in Node.JS.
Edit:
I want to retrieve the queries programmatically to prevent writing them twice, once for the android app and once again for the Node.JS app.
You can get all the queries via the generated code yourDao(s) suffixed with _impl and your#DatabaseClass(s) also suffixed with _impl
e.g. For
#Dao
public interface CustomerDao {
#Insert
long insert(Customer customer);
#Query("INSERT INTO Customer (firstname, lastName, dateAdded) VALUES(:firstName,:lastName,:dateAdded)")
long insert(String firstName, String lastName, String dateAdded);
#Query("SELECT * FROM customer WHERE firstName=:firstName AND lastName = :lastName")
Customer getCustomerByName(String firstName, String lastName);
#Query("SELECT * FROM customer")
LiveData<List<Customer>> getAllCustomers();
}
then CustomerDao_Impl is :-
#SuppressWarnings({"unchecked", "deprecation"})
public final class CustomerDao_Impl implements CustomerDao {
private final RoomDatabase __db;
private final EntityInsertionAdapter<Customer> __insertionAdapterOfCustomer;
private final SharedSQLiteStatement __preparedStmtOfInsert;
public CustomerDao_Impl(RoomDatabase __db) {
this.__db = __db;
this.__insertionAdapterOfCustomer = new EntityInsertionAdapter<Customer>(__db) {
#Override
public String createQuery() {
return "INSERT OR ABORT INTO `Customer` (`id`,`firstName`,`lastName`,`dateAdded`) VALUES (?,?,?,?)";
}
..........
and for ShopDatabase
#Database(entities = {Customer.class}, version = 1)
//#TypeConverters({Converters.class})
public abstract class ShopDatabase extends RoomDatabase {
private static ShopDatabase instance;
..........
then ShopDatabase_Impl is :-
#SuppressWarnings({"unchecked", "deprecation"})
public final class ShopDatabase_Impl extends ShopDatabase {
private volatile CustomerDao _customerDao;
#Override
protected SupportSQLiteOpenHelper createOpenHelper(DatabaseConfiguration configuration) {
final SupportSQLiteOpenHelper.Callback _openCallback = new RoomOpenHelper(configuration, new RoomOpenHelper.Delegate(1) {
#Override
public void createAllTables(SupportSQLiteDatabase _db) {
_db.execSQL("CREATE TABLE IF NOT EXISTS `Customer` (`id` INTEGER, `firstName` TEXT, `lastName` TEXT, `dateAdded` TEXT, PRIMARY KEY(`id`))");
_db.execSQL("CREATE TABLE IF NOT EXISTS room_master_table (id INTEGER PRIMARY KEY,identity_hash TEXT)");
_db.execSQL("INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, '588832abfd9fd9c6aad8dcebe485e219')");
}
#Override
public void dropAllTables(SupportSQLiteDatabase _db) {
_db.execSQL("DROP TABLE IF EXISTS `Customer`");
if (mCallbacks != null) {
for (int _i = 0, _size = mCallbacks.size(); _i < _size; _i++) {
mCallbacks.get(_i).onDestructiveMigration(_db);
}
}
}
..........
your would probably not want the room_master_table as that is room specific and the hash is generated, I believe, from the code so is sensitive to changes being made.
where .......... indicates code omitted for brevity
If somebody else wants to export all queries automatically, what I have done instead of getting them manually in each of my DaoClassName_Impl is to export my room database schema then processing the json file exported. If you want to create a java module in android studio for easy reuse, I suggest to create an annotation processor (even if it does not process any annotation) that will run automatically every time you build your project.
I'm having issue on joining tables on ormlite. On the first load i have my pojo ready for insertion of data from api using retrofit and gson as the tools.
Here's my pojos:
public class ParticipantDetailsModel {
#DatabaseField(id = true)
private int id;
#DatabaseField
private String first_name;
#DatabaseField
private String last_name;
}
public class Trainings implements Serializable {
#DatabaseField
private int participant_id;
#DatabaseField
private int batch_id;
#DatabaseField
private int graduation_program_id;
#DatabaseField
private int id;
#DatabaseField(foreign = true, foreignAutoRefresh = true, foreignAutoCreate = true)
private ParticipantDetailsModel participant;
}
On that Pojo i am actually getting duplicate field id which is "participant_id". So what i did is to rename this field from private ParticipantDetailsModel participant to private ParticipantDetailsModel participants, just for me to get the data. but once i query im not getting any values:
QueryBuilder<Trainings, String> qb1 = dao1.queryBuilder();
QueryBuilder<ParticipantDetailsModel, String> qb2 = dao2.queryBuilder();
qb1.where().eq("id", item.getId()).and().in("participant_id", parId);
List<Trainings> u = qb1.join(qb2).query();
do you have any idea what im missing?
heres my db:
enter image description here
Have a look at the Ormlite documentation
2.12 Foreign Object Fields
...
Notice that the name of the field is not account but is instead account_id. You will
need to use this field name if you are querying for it. You can set the column name using
the columnName field in the DatabaseField annotation
To set the columnName use:
public static final String ID_COLUMN = "ID";
#DatabaseField(columnName = ID_COLUMN)
private int id;
To make the query work, you have to set a Where clause on qb2 as well.
qb1.where().eq("id", item.getId());
qb2.where().in("id", parId);
List<Trainings> u = qb1.join(qb2).query();
How do I query an object that has another object as a property? I need to get the values of the property as well. Here's my model:
public class Department {
public int DeptId;
public string DeptName;
}
public class Employee {
public int Id;
public string Name;
public int DeptId;
public Department Department;
}
I'm coming from a c# background, and I could do this with c# using Entity Framework. Now it seems like this model works but when I included a sqllite functionality for the objects I'm not sure how to query it.
Here's my first try, but I'm not sure if this is the best way
public List<Employee> getAllEmployeesWithDepartments(){
List<Employee> employees = new ArrayList<>();
SQLiteDatabase db = this.getReadableDatabase();
Cursor res = db.rawQuery("SELECT * FROM Employee e LEFT JOIN Department d on e.DeptId = d.Id" , null);
if(res.moveToFirst()){
do{
Employee emp = new Employee();
emp.Id = res.getInt(res.getColumnIndex("Id"));
emp.Name = res.getString(res.getColumnIndex("Name"));
Department dep = new Department();
dep.Id = res.getInt(res.getColumnIndex("Id"));
dep.Name = res.getString(res.getColumnIndex("Name"));
emp.Department = dep;
employees.add(emp);
}while (res.moveToNext());
}
return employees;
}
You're confused. SQLite doesn't have objects. Its a table based database (like almost all databases). You can map objects into tables, but you have to create those mappings yourself. Since SQLite doesn't have objects, it definitely doesn't have subobjects. You generally make something like it by joining another table with a foreign key constraint on the main table, but it really is defined by your schema. There is no generic answer for you.
I'm trying write a query using ORMLite. I need this query check a id of customer in other entity. How could I do it ?
Entities
#DatabaseTable(tableName = "customer")
public class Customer {
#DatabaseField(generatedId = true)
private Integer id;
#DatabaseField
private String name;
#DatabaseField
private Sale sale;
//gets sets
}
#DatabaseTable(tableName = "sale")
public class Sale{
#DatabaseField(generatedId = true)
private Integer id;
#DatabaseField
private Customer customer;
#DatabaseField
private Integer status;
//gets sets
}
Query
Customer customer = new Customer();
customer.setId(1);
customer.setName("Fernando Paiva");
QueryBuilder<Sale, Integer> qb = saleDAO.queryBuilder();
Where where = qb.where();
where.eq("sale.customer.id", customer.getId());
where.and();
where.eq("sale.status", 1);
PreparedQuery<Sale> pq = qb.prepare();
List<Sale> list = saleDAO.query(pq);
Log.i("SALE LIST->", list.size() + "");
You need to use JOIN
Here your example using Join:
First of all, you need a QueryBuilder to each Dao.
You can apply your filter to each QueryBuilder separately
Last but not least, you join the main QueryBuilder (Sales) with the Customer's QueryBuilder and
perform the query.
Here the code
Dao<Sale, Integer> saleDao = DaoManager.createDao(getConnectionSource(), Sale.class);
Dao<Customer, Integer> customerDao = DaoManager.createDao(getConnectionSource(), Customer.class);
QueryBuilder<Sale, Integer> saleQa= saleDao.queryBuilder();
saleQa.where().eq("status", 1);
QueryBuilder<Customer, Integer> customerQa = customerDao.queryBuilder();
customerQa.where().idEq(customer.getId());
sales = saleQa.join(customerQa).query();
Are you trying to use OrmLite to check if the customer id is the same as the sale id and get all of the matching result? If so the below code will do that
qb.where().eq("id", customer.id);
List<Sale> results = saleDAO.query(qb.prepare());
Update:
After rereading your question I realized what you're trying to do
qb.where().in(Sale.customer, id);
See this question for further details.
Ormlite Foreign Entity Searching
Using ORMLite for Android, I need to build a query that returns orders by order id or by customer name. Please consider the following class declarations:
#DatabaseTable(tableName = "order")
public class Order {
#DatabaseField(generatedId = true)
private Long id;
#DatabaseField(foreign = true, canBeNull = false, foreignAutoRefresh = true, columnName = "customer_id")
private Customer customer;
// default constructor, getters and setters...
}
#DatabaseTable(tableName = "customer")
public class Customer {
#DatabaseField(generatedId = true)
private Long id;
#DatabaseField
private String name;
// default constructor, getters and setters...
}
The raw SQL I'm looking for would be something like this:
SELECT
o.*
FROM
order o
JOIN customer c on
o.customer_id = c.id
WHERE
(o.id = ?) OR (c.name = ?)
What is the best way to do this using ORMLite?
ORMLite now supports simple join queries.
So your query would look something like:
QueryBuilder<Customer, Integer> customerQb = customerDao.queryBuilder();
SelectArg nameSelectArg = new SelectArg();
// this gives the c.name = ?
customerQb.where().eq("name", nameSelectArg);
QueryBuilder<Account, Integer> orderQb = orderDao.queryBuilder();
SelectArg idSelectArg = new SelectArg();
// this gives the o.id = ?
orderQb.where().eq("id", idSelectArg);
orderQb.join(customerQb);
// then you set the args and run the query
nameSelectArg.setValue("jim");
idSelectArg.setValue(1);
List<Order> results = orderQb.join(customerQb).query();
No, JOINs are supported in ORMLite https://stackoverflow.com/a/7320091/323128
However, this reference will give a vision how to complete your task