How to populate a complex list with sublist from SQLite? - java

I have a structure of lists that I would like to populate from database. I've already mapped all tables and insertion methods. However I don't know what is the best approach to get all those data and populate my Java Objects. I have this structure:
public class DailySchedule {
private long id;
private List<Task> tasks;
private List<Plan> plans;
}
public class Task {
private long id;
private long duration;
private String description;
private Date date;
}
public class Plan {
private long id;
private String description;
private Date date;
private List<User> users;
}
public class User {
private long id;
private String name;
}
Should I create a huge INNERJOIN and get all the data (including repeated info) and try to populate the Java Objects or I should get all the Id's from each table and perform a loop in Java(using cursor) and perform Selects by ID's and populate the tables?

I assume you have below tables
daily_schedule
task
plan
user
Code
public List<DailySchedule> getDailySchedules(){
SQLiteDatabase db = getReadableDataBase();
Cursor dailyScheduleCursor = db.rawQuery(“Select * from daily_schedule ”);
List<DailySchedule> all = new ArrayList<>();
While(dailyScheduleCursor.next()){
DailySchedule dailySchedule = new DailySchedule();
dailySchedule.setId(dailyScheduleCursor.getLong(0));
dailySchedule.setTasks(getTasks(dailyScheduleCursor.getLong(0)));
dailySchedule.setPlans(getTasks(dailyScheduleCursor.getLong(0)));
all.add(dailySchedule);
}
db.close();
}
public List<Task> getTasks(int id ){
SQLiteDatabase db = getReadableDataBase();
Cursor taskCursor = db.rawQuery(“Select * from tasks where id =’”+id+”’ ”);
List<Task> all = new ArrayList<>();
While(taskCursor.next()){
Task task = new task();
task.setId(taskCursor.getLong(0));
// set other attributes
all.add(task);
}
db.close();
return all;
}
public List<Plan> getPlan(int id ){
getUser(id);// get all plans
// set user
return plans;
}
public User(int id){
//create user from data
return user;
}
Then call getDailySchedules() from somewhere.
Note If you want to see your SQLite databse content, use
AndroidDBvieweR

Related

Adding an object to a List of another type

I'm trying to return the record that I got from my database. But I'm having a problem on how I can do that because the data than I retrieved from the database is in a different class from the return parameter.
public List<Record> getRecord(List<Request> requests) {
List<Record> records = new ArrayList<>();
for (Request request : requests) {
Billing billing = billingRepository
.findByBillingCycleAndStartDateAndEndDate(
request.getBillingCycle()
, request.getStartDate()
, request.getEndDate());
if (billing != null) {
// Need to add "billing" to "records" list here
}
}
return records;
}
Record.class
public class Record {
private int billingCycle;
private LocalDate startDate;
private LocalDate endDate;
private String accountName;
private String firstName;
private String lastname;
private double amount;
public Record() {
}
//Getters and setters
Billing.class
public class Billing {
private int billingId;
private int billingCycle;
private String billingMonth;
private Double amount;
private LocalDate startDate;
private LocalDate endDate;
private String lastEdited;
private Account accountId;
public Billing() {
}
//Getters and setters
What can I do? and please explain the answer so I can understand it. I really want to learn
You can use DozerMapper. It will map the object to another object having same name properties or you have to write the mapping in the dozer-mapping xml.
Lets come to your question. Here you are trying to convert your entity to another object.
For that you have to write mapping code. It will be something like this and it is very common practice to convert entity objects to another object before using them.
Record toRecord(Billing billing) {
if(billing == null) {
return null;
}
Record record = new Record();
record.setBillingCycle = billing.getBillingCycle();
...
...
// other properties
...
return record;
}

Android Room Test Delete Not Working (Java)

I'm trying to unit-test my DAO using android-room. I have written an insert test that works properly. Unfortunately, the delete method doesn't seem to be working.
I've tried a few different setups for the test. None have worked.
Here is the DAO:
#Dao
public interface MonthlyDao {
#Insert(onConflict = OnConflictStrategy.REPLACE)
void saveAll(List<Monthly> goals);
#Insert(onConflict = OnConflictStrategy.REPLACE)
void save(Monthly goal);
#Update
void update(Monthly goal);
#Delete
void delete(Monthly goal);
#Query("SELECT * FROM Monthly")
LiveData<List<Monthly>> findAll();
#Query("SELECT * FROM monthly")
List<Monthly> findAllList();
}
Here is the Monthly entity:
#Entity
public class Monthly {
#PrimaryKey(autoGenerate = true)
private int monthlyId;
#TypeConverters(CalendarTypeConverter.class)
#ColumnInfo(name = "date")
private Calendar date = Calendar.getInstance();
#ColumnInfo(name = "title")
private String title;
#ColumnInfo(name = "description")
private String description;
#ColumnInfo(name = "completed")
private boolean completed;
...
public int getMonthlyId() {
return monthlyId;
}
public void setMonthlyId(int monthlyId) {
this.monthlyId = monthlyId;
}
And here is the test I am running:
#RunWith(AndroidJUnit4.class)
public class MonthlyTest {
private MonthlyDao monthlyDao;
private MonthlyGoalsDatabase db;
#Before
public void createDb() {
Context context = ApplicationProvider.getApplicationContext();
db = Room.inMemoryDatabaseBuilder(context, MonthlyGoalsDatabase.class).build();
monthlyDao = db.getMonthlyDao();
}
#After
public void closeDb() throws IOException {
db.close();
}
#Test
public void deleteGoal() throws Exception {
String title = "test delete title";
Calendar date = Calendar.getInstance();
date.set(Calendar.HOUR_OF_DAY, 0);
String desc = "test delete desc";
Monthly goal = new Monthly(title, date, desc);
monthlyDao.save(goal);
List<Monthly> goals = monthlyDao.findAllList();
Assert.assertThat(goals.get(0).getTitle(), equalTo(goal.getTitle()));
monthlyDao.delete(goal);
List<Monthly> updatedGoals = monthlyDao.findAllList();
Assert.assertTrue(updatedGoals.isEmpty());
}
I except the updatedGoals list to be empty, but it isn't. There is still the goal that I inserted during the test.
The method annotated with #Delete uses the primary key on the entity to know which row to delete from the database (because there could be multiple rows with the same data but different keys).
However, you're using the initial goal object that you created, which has no primary key, and thus cannot be used to indicate which row to remove.
Try doing this:
monthlyDao.save(goal);
List<Monthly> goals = monthlyDao.findAllList();
Assert.assertThat(goals.get(0).getTitle(), equalTo(goal.getTitle()));
monthlyDao.delete(goals.get(0)); // <-- Delete the goal returned from the find, which will have an ID
List<Monthly> updatedGoals = monthlyDao.findAllList();
Assert.assertTrue(updatedGoals.isEmpty());
That could easily be cleaned up a bit, but the above example only changes one line, to make it clear where the issue is.
See here for the relevant documentation.

Hot to add a list of parameters of another object in jpa Criteria

I have a class Director
public class Director {
private Long id;
#OneToOne(cascade = CascadeType.ALL)
#JoinColumn(name="transacao_id")
private Company company;
private Date registrationDate;
...
}
I have a class Company
public class Company {
private Long id;
private String cnpj;
private String description;
...
}
I need to add another filter in predicates...
I need to fetch a list from Director, filtering through a list of cnpj using jpa predicates, for example:
private Predicate[] criarRestricoes(FilterDTO filter, CriteriaBuilder builder, Root<Director> root) {
List<Predicate> predicates = new ArrayList<>();
Date today = new Date();
if (filter.getRegistrationDate() != null) {
predicates.add(builder.between(root.get("registrationDate").as(Date.class), today, filter.dateParam));
}
if (!StringUtils.isEmpty(filter.getCnpj())) {
predicates.add(builder.equal(???????????, ???????????????);
}
return predicates.toArray(new Predicate[predicates.size()]);
}
builder.equal(root.join("company").get("cnpj"), filter.getCnpj());

Joining multiple tables in list item with cursor

I have one problem. I have a note that contains text data, and user can add multiple photos related to that note. Notes and photos are stored in separated tables, and both of data models for notes and photos extends abstract object with data that is relevant for both objects. Beside that, "note" table is foreign key for "photo" object.
Abstract class that both objects extends:
public abstract class SyncObject implements Parcelable {
public static final String ID = "_id";
public static final String DATE = "date";
public static final String IS_SAVED_TO_CLOUD = "isSavedToCloud";
public static final String TIME_STAMP = "timeStamp";
public static final String IS_DELETED = "isDeleted";
#DatabaseField(id = true, index = true, canBeNull = false, columnName = ID)
public String id;
#DatabaseField(columnName = DATE)
public String date;
#DatabaseField(columnName = IS_SAVED_TO_CLOUD)
public boolean isSavedToCloud;
#DatabaseField(columnName = TIME_STAMP)
public String timeStamp;
#DatabaseField(columnName = IS_DELETED)
public boolean isDeleted; }
Here's note class:
public class Note extends SyncObject implements Parcelable {
public static final String TITLE = "title";
public static final String DESCRIPTION = "description";
#DatabaseField(columnName = TITLE)
public String title;
#DatabaseField(columnName = DESCRIPTION)
public String description; }
And photo class:
public class Photo extends SyncObject{
public static final String FIELD_REF = "note";
public static final String PHOTO = "photo";
public static final String THUMBNAIL = "thumbnail";
#DatabaseField(columnName = PHOTO)
public String photoUrl;
#DatabaseField(columnName = THUMBNAIL)
public String thumbnailUrl;
#DatabaseField(columnName = FIELD_REF, canBeNull = false, foreign = true, foreignAutoRefresh = true)
public Note note;
So, here it begins.
I want to show photo related to note in list, but getting cursor with joining tables produced data with same fields, and querying by those fields doesn't make any sense. Basically, i want to show one note with one photo inside list.
I tried to do this with 2 cursors, but without any success. Am I making mistake in joining cursors or creating cursor in a first place?
I have Content Provider that creates 2 cursors, one for note and one for photo data. I'm able to show data in list from one at the time. Is there any way to show data from multiple(note & photo) tables with one cursor?
Creating cursor with rawQuerry created table with same fields, and i don't need fields from SyncObject for photos while showing notes in list.
Query I used:Cursor c = db.rawQuery("SELECT * FROM note INNER JOIN photos ON note = photos.note WHERE photos.note = note", null);
Thanks in advance, if someone needs more info, ill update this post, thanks!

Objectify not returns new data

I'm using Ojectify to store datastore, I have an entity that when I keep it if the changes are saved, but in the browser to display it sometimes shows me the previous data and sometimes the new data.
#Entity
public class BrandDto {
#Id
private Long id;
#Index
private String name;
#Index
private List<Ref<UserDto>> users;
#Index
private Integer numeroFollowers;
getters and setters .....
}
It happens in users and numeroFollowers fields.
I update this data as follows:
UserDto user = ofy().load().type(UserDto.class).id(p_userId).now();
if (user != null) {
BrandDto brand = ofy().load().type(BrandDto.class).id(p_brandId).now(); //get(p_brandId);
List<UserDto> users = brand.getUsers() != null ? brand.getUsers() : new ArrayList<UserDto>();
if (!users.contains(user)) {
users.add(user);
}
brand.setUsers(users);
brand.setNumeroFollowers(users.size());
ofy().save().entity(brand).now();
return true;
} else {
return false;
}
And I read as follows:
List<BrandDto> brands = ofy().load().type(BrandDto.class).list();
Other query that I use:
UserDto user = ofy().load().type(UserDto.class).id(p_userId).now();
Ref<UserDto> ref = Ref.create(user);
List<BrandDto> brands = ofy().load().type(BrandDto.class).filter("users", ref).list();
While get-by-key operations (like load().type(...).id(...)) are strongly consistent by default, queries are eventually consistent.
Here's more information: https://cloud.google.com/developers/articles/balancing-strong-and-eventual-consistency-with-google-cloud-datastore/

Categories