persist bidirectional relationship ormlite - android

I have these classes:
public class AllegationContent {
#DatabaseField(generatedId = true)
protected long id;
#DatabaseField(canBeNull = true, foreign = true)
private AllegationItem allegationItem;
#DatabaseField()
protected String content;
...
}
And:
public class AllegationItem {
#DatabaseField(generatedId = true)
protected long id;
#ForeignCollectionField(eager = false)
protected ForeignCollection<AllegationContent> allegationContent;
...
}
How can I persist both?
I am trying this:
allegationContentDao = getAllegationContentDao();
AllegationContent allegationContent = new AllegationContent();
allegationContent.setContent("allegation content");
allegationContentDao.create(allegationContent);
allegationItemDao = getAllegationItemDao();
AllegationItem allegationItem = new AllegationItem();
AllegationContent allegationContent2 = allegationContentDao.queryForSameId(allegationContent); //is that wrong?
allegationItem.getAllegationContent().add(allegationContent2);
allegationItemDao.create(allegationItem);
but I got this error:
04-24 10:41:57.128: ERROR/AndroidRuntime(802): java.lang.RuntimeException: Unable to start activity ComponentInfo{br.com.project/br.com.project.DaoTestActivity}: java.lang.NullPointerException

I solved. The table can't create because don't have atributes, only id (what's another problem). The NPE happen because getAllegationContent return null, so first I need create a ForeignCollection list, set using setAllegationContent and then get.

Related

Problems with ArrayAdapter

When I trying to get item index by below code.
Company company = getDefaultCompany();
companyArrayAdapter.getPosition(company);
I always to get result of -1. I don't understand what's wrong?
Because
companyArrayAdapter also have type Company.
private ArrayAdapter<Company> companyArrayAdapter;
Next you can see Company class declaration.
#DatabaseTable(tableName=Company.TABLE_NAME)
public class Company {
public static final String TABLE_NAME = "company";
#DatabaseField(id = true, columnName = "id")
private UUID id;
#DatabaseField(canBeNull=false)
private String name;
#DatabaseField
private String address;
#DatabaseField
private String phone;
#ForeignCollectionField(eager = false)
private ForeignCollection<Contract> contracts;
public Company(){
}
}
ArrayAdapter uses List.indexOf() method which and it can't compare your custom Company class objects and always returns "Not Found" index (-1).
So you should override getPosition() method int your custom adapter which extends ArrayAdapter:
#Override
public int getPosition(#Nullable Company company) {
/* here write logic of finding your company in companies list and retur index*/
return index;
}
P.S
If you had snippet of your custom adapter I would give you more detailed answer.
you can iterate through the loop of the list
var list=adapter.your_list
var toMatch=yourObject
for((index,elem) in list.withIndex()){
if(elem.someUniqueProperty == toMatch.someUniqueProperty){
var needed_index=index
}
}

Ormlite foreign field giving me null on response and sometimes duplicate field

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();

OrmLite foreign key exists from Json

I've never used OrmLite before but I need to edit an existing project that uses it.
I have two classes : Person and Office.
I'm using gson to parse, with the person an office Id is provided, for example office_id: "4456".
I was hoping it would be possible to link the two together from my Person class so I can easily get a office for a person.
For example:
#SerializedName("id")
#DatabaseField(id = true, columnName = ID)
private int mId;
#SerializedName("full_name")
#DatabaseField(columnName = FULL_NAME)
private String mFullName = null;
#DatabaseField(columnName = POSITION)
private String mPosition = null;
#SerializedName("email")
#DatabaseField(columnName = EMAIL)
private String mEmail = null;
private Office office = null;
#SerializedName("office_id")
private String officeId = null;
So I have the officeId from Json which is stored in the Person table. I would like to automatically load the Office into the Person object whenever it is loaded.
To automatically fetch a referenced object upon querying you can use foreignAutoRefresh = true in your #DatabaseField. You reference the Object and not the id itself. In the table, the id of the referenced row will be stored.
To clarify for your project:
Office must look something like this:
#SerializedName("id")
#DatabaseField(id = true, columnName = ID)
private int mId;
...
And your Person (database-wise) like this:
#DatabaseField(id = true, columnName = ID)
private int mId;
#DatabaseField(columnName = FULL_NAME)
private String mFullName = null;
#DatabaseField(columnName = POSITION)
private String mPosition = null;
#DatabaseField(columnName = EMAIL)
private String mEmail = null;
#DatabaseField(foreign = true, foreignAutoRefresh = true)
private Office office = null;
The Office column in the Person table will hold the id of the Office.
foreignAutoRefresh tells ORMLite to fetch the full Office upon querying the Person
http://ormlite.com/javadoc/ormlite-core/com/j256/ormlite/field/DatabaseField.html#foreignAutoRefresh()
Hope this helps

Android Ormlite upgrade issue with ForeignCollectionField

While upgrading my database schema I have run into a problem with a ForeignCollectionField (ormlite 4.7) not returning rows. With a clean install of the app, rows can be added and displayed as expected.
When the app is updated to a new version, the schema is updated (see below), but when rows are added to the database the collection is not returning the added rows. (I can see the rows exist in the database)
The parent row existed before the update. What do I need to do to fix it?
Parent class with Foreign Collection defined
#DatabaseTable(tableName = "setting")
public class SettingEntity {
#DatabaseField(generatedId = true)
private long id;
…
//New field added
#ForeignCollectionField
private ForeignCollection<DistributionEntity> distribution;
public SettingEntity() {
// Required for ORMLite
}
public ForeignCollection<DistributionEntity> getDistribution() {
return distribution;
}
public void setDistribution(ForeignCollection<DistributionEntity> distribution) {
this.distribution = distribution;
}
}
Child class
#DatabaseTable(tableName = "distribution")
public class DistributionEntity {
#DatabaseField(generatedId = true)
private long id;
…
//New field added
#DatabaseField(canBeNull = true, foreign = true, index = true, foreignAutoRefresh = true, columnDefinition = "integer references setting(id) on delete cascade")
private SettingEntity setting;
public void setSetting(SettingEntity setting) {
this.setting = setting;
}
}
onUpgrade code
RuntimeExceptionDao<DistributionEntity, Integer> distributionDao = helper.getDistributionDao();
distributionDao.executeRaw("ALTER TABLE distribution ADD setting_id");
distributionDao.executeRaw("CREATE INDEX distribution_setting_idx ON distribution (setting_id)");
Debug info of the ForeignCollectionField call distribution
The code that iterates over the collection
public ArrayList<Distribution> getDistribution() {
getEntity().getDistribution().size();
final ArrayList<Distribution> items = new ArrayList<Distribution>();
final ForeignCollection<DistributionEntity> collection = getEntity().getDistribution();
for (final DistributionEntity item : collection) {
final Distribution dist = new Distribution(item, mContext);
items.add(dist);
}
return items;
}
NB getEntity() returns an instance of SettingEntity
Thanks for spending the time
More of a workaround than answer but had to get around this problem. Replicated behavior by writing code.
public List<DistributionEntity> getDistribution() {
List<DistributionEntity> distributionEntities = new ArrayList<DistributionEntity>();
try {
DatabaseHelper helper = DatabaseHelper.getInstance();
RuntimeExceptionDao<DistributionEntity, Integer> dao = helper.getDistributionDao();
QueryBuilder<DistributionEntity, Integer> queryBuilder = dao.queryBuilder();
queryBuilder.where().eq(DistributionEntity.SETTING_FIELD_NAME, Long.toString(this.getId()));
PreparedQuery<DistributionEntity> preparedQuery = queryBuilder.prepare();
distributionEntities = dao.query(preparedQuery);
} catch (SQLException e) {
e.printStackTrace();
}
return distributionEntities;
//return distribution;
}
Love to know what the true answer is

Using JodaTime (DateTime, Duration) with ORMLite on Android

I am looking for a way to hold a DateTime object and a Duration as part of my value object.
Here is my value object:
#DatabaseTable(tableName = DrivingRecord.TableName)
public class DrivingRecord {
public final static String TableName = "drivingRecord";
public final static String DRIVING_TASK_COLUMN_NAME = "drivingTask";
#DatabaseField(foreign = true, columnName = DRIVING_TASK_COLUMN_NAME)
private DrivingTask drivingTask;
#DatabaseField(generatedId = true)
private int id;
#DatabaseField(dataType = DataType.LONG)
private DateTime startTime;
#DatabaseField
private Duration durationOfDriving;
}
I get the following exception:
java.lang.IllegalArgumentException: Field class org.joda.time.Duration for field FieldType:name=durationOfDriving,class=DrivingRecord is not valid for type com.j256.ormlite.field.types.LongType#41223060, maybe should be long
I also getting the same exception when trying to create an entry for the DateTime
java.lang.IllegalArgumentException: Field class org.joda.time.Duration for
field FieldType:name=durationOfDriving,class=DrivingRecord is not valid for
type com.j256.ormlite.field.types.LongType#41223060, maybe should be long
This message is trying to tell you that your Duration field durationOfDriving is not compatible with the date-type DataType.LONG. I'm not sure if the code you've posted isn't correct but I would have thought that you would be trying to do:
#DatabaseField(dataType = DataType.LONG)
private Duration durationOfDriving;
ORMLite natively supports DateTime but does not support persisting a Duration. Just trying to force it to be a long will not work. You are going to have to define a customer persister for Duration.
Check out the documentation on custom persisters for how to start your own persister.
You can also check out this answer for another example: Is there any way to disable ORMLite's check that a field declared with DataType.SERIALIZABLE implements Serializable?
Here is show I was able to solve the problem. Making the timestamp a long, and save the timezone. Now I am able to search on the timestamp if I needed to.
#DatabaseTable(tableName = DrivingRecord.TableName)
public class DrivingRecord {
public final static String TableName = "drivingRecord";
public final static String DRIVING_TASK_COLUMN_NAME = "drivingTask";
#DatabaseField(foreign = true, columnName = DRIVING_TASK_COLUMN_NAME)
private DrivingTask drivingTask;
#DatabaseField(generatedId = true)
private int id;
#DatabaseField(dataType = DataType.LONG)
private long startTime;
#DatabaseField
private Duration durationOfDriving;
#DatabaseField(canBeNull = false, dataType= DataType.SERIALIZABLE)
private DateTimeZone timeZone;
public void setDateTime(DateTime dateTime){
this.startTime = startTime.getMillis();
this.timeZone = startTime.getZone();
}
public DateTime getDateTime(){
return new DateTime(startTime, timeZone);
}
}
While JodaTime does not work with ORMLite, you can use Java Date which works with ORMLite.
There are also many ways you can convert in between JodaTime and Date.
#DatabaseField
protected Date createdAt;
public static String formatDateTime(DateTime dateTime1) {
if (dateTime1 == null || dateTime1.getYear() == 0) {
return "";
}
DateFormat df = DateFormat.getDateInstance(DateFormat.SHORT, ApplicationBase.AppContext.getResources().getConfiguration().locale);
Calendar calendar02 = new GregorianCalendar(dateTime1.getYear(), dateTime1.getMonthOfYear() - 1, dateTime1.getDayOfMonth());
Date date3 = calendar02.getTime();
String date3str = DataItemBase.formatDate(date3);
return date3str;
}

Categories

Resources