I have two observables:
Observable <Profile> profileObservable = briteDatabase.createQuery(UserMapper.Table.NAME, sql, String.valueOf(userId)).mapToOneOrDefault(UserMapper.MAPPER, null);
Observable <List<Car>> carObservable = briteDatabase.createQuery(CarMapper.Table.NAME, sql, String.valueOf(userId)).mapToOneOrDefault(CarMapper.MAPPER, null);
public class Profile {
int id;
String name;
ArrayList<Car> car;
...
}
public class Car {
int id;
String brand;
...
}
I need to get list of cars from carObservable and put it to profileObservable (put list of car to Profile), inside method like this:
#Override
public Observable<Profile> getProfile(String userId) {
String sql = String.format("SELECT %s FROM %s WHERE %s=?", TextUtils.join(",", UserMapper.PROJECTION), UserMapper.Table.NAME, UserMapper.Columns.ID);
Observable <Profile> profileObservable = briteDatabase.createQuery(UserMapper.Table.NAME, sql, String.valueOf(userId)).mapToOneOrDefault(UserMapper.MAPPER, null);
Observable <List<Car>> carsObservable = getCars(String userId);
/*
Some important method to concat and return Observable <Profile>. I'm only beginner at RxJava(
*/
}
Did you try the concat operator, I dont know if I understand quite well your use case, but in case you just need to go through the list of car and then profile, just concat one after the other
#Test
public void testContact() {
Observable.concat(Observable.just("Hello"),
Observable.just("reactive"),
Observable.just("world"))
.subscribe(System.out::println);
}
If you want to initiate in the RxJava world take a look here https://github.com/politrons/reactive
Related
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 have a problem getting timestamp(rowversion) from my SQL Azure database.
In my tables there is a column with datatype timestamp. This timestamp isn't similar to datetime, it's more like a rowversion.
I can get all other data in this table with the query from MobileServiceTable, there is no problem.
But this special datatype is a problem.
My class for this table looks like:
public class ArbeitsgangBezeichnung {
#com.google.gson.annotations.SerializedName("id")
private int ID;
#com.google.gson.annotations.SerializedName("ABZ_ArbeitsgangBezeichnungID")
private int ABZ_ArbeitsgangBezeichnungID;
#com.google.gson.annotations.SerializedName("ABZ_Bezeichnung")
private String ABZ_Bezeichnung;
#com.google.gson.annotations.SerializedName("ABZ_RowVersion")
private StringMap<Number> ABZ_RowVersion;
//constructor, getter, setter, etc....
}
If i login in Azure and look at the table, there are my example values and the automatic generated timestamp. The timestamp value looks like "AAAAAAAAB/M=". If i login in sql database and let me show the data, then for timestamp there is only "binarydata" (in pointed brackets) and not that value as it is shown in Azure.
The variable "ABZ_RowVersion" should include this timestamp, but the data in the StringMap doesn't look like the one in Azure. I tried String and Byte as datatype for the StringMap, but it doesn't helped.
I tried byte[] for ABZ_RowVersion, but then i got an exception in the callback method.
Then i tried Object for ABZ_RowVersion, that time i found out, that it is a StringMap, but nothing more.
Does anybody know, how to get the data from timestamp, i need it for comparison.
Thanks already
When you create a timestamp column in a table, it's essentially a varbinary(8) column. In the node SQL driver, it's mapped to a Buffer type (the usual node.js type used for binary data). The object which you see ({"0":0, "1":0, ..., "length":8}) is the way that a buffer is stringified into JSON. That representation doesn't map to the default byte array representation from the Gson serializer in Android (or to the byte[] in the managed code).
To be able to use timestamp columns, the first thing you need to do is to "teach" the serializer how to understand the format of the column returned by the server. You can do that with a JsonDeserializer<byte[]> class:
public class ByteArrayFromNodeBufferGsonSerializer
implements JsonDeserializer<byte[]> {
#Override
public byte[] deserialize(JsonElement element, Type type,
JsonDeserializationContext context) throws JsonParseException {
if (element == null || element.isJsonNull()) {
return null;
} else {
JsonObject jo = element.getAsJsonObject();
int len = jo.get("length").getAsInt();
byte[] result = new byte[len];
for (int i = 0; i < len; i++) {
String key = Integer.toString(i);
result[i] = jo.get(key).getAsByte();
}
return result;
}
}
}
Now you should be able to read data. There's still another problem, though. On insert and update operations, the value of the column is sent by the client, and SQL doesn't let you set them in them. So let's take this class:
public class Test {
#SerializedName("id")
private int mId;
#SerializedName("name")
private String mName;
#SerializedName("version")
private byte[] mVersion;
public int getId() { return mId; }
public void setId(int id) { this.mId = id; }
public String getName() { return mName; }
public void setName(String name) { this.mName = name; }
public byte[] getVersion() { return mVersion; }
public void setVersion(byte[] version) { this.mVersion = version; }
}
On the insert and update operations, the first thing we need to do in the server-side script is to remove that property from the object. And there's another issue: after the insert is done, the runtime doesn't return the rowversion property (i.e., it doesn't update the item variable. So we need to perform a lookup against the DB to retrieve that column as well:
function insert(item, user, request) {
delete item.version;
request.execute({
success: function() {
tables.current.lookup(item.id, {
success: function(inserted) {
request.respond(201, inserted);
}
});
}
});
}
And the same on update:
function update(item, user, request) {
delete item.version;
request.execute({
success: function() {
tables.current.lookup(item.id, {
success: function(updated) {
request.respond(200, updated);
}
});
}
});
}
Now, this definitely is a lot of work - the support for this type of column should be better. I've created a feature request in the UserVoice page at http://mobileservices.uservoice.com/forums/182281-feature-requests/suggestions/4670504-better-support-for-timestamp-columns, so feel free to vote it up to help the team prioritize it.
I have a SQLite table (on Android) that has numerous fields, but certain fields are repeated/denormalized. I would like to select a distinct set of this data and use them as actual objects.
Example
books table
title summary author
Little Johnny A funny kid Johnny Himself
Big Johnny A funny adult Johnny Himself
I would like to extract one author from this list ("Johnny Himself") and would expect I should be able to do this with ORMLite instead of manually with Java.
I would like to select a distinct set of this data and use them as actual objects.
ORMLite supports a distinct() method on the QueryBuilder that should do what you want. So your code would look something like:
List<Book> results = booksDao.queryBuilder()
.distinct().selectColumns("author").query();
In this case, the resulting Book objects would only have the author field set and not the id field or anything else. If you just wanted the author names instead of objects then you could do:
GenericRawResults<String[]> rawResults =
booksDao.queryRaw("SELECT DISTINCT author FROM books");
for (String[] resultColumns : rawResults) {
String author = resultColumns[0];
...
}
This is my application code
public class DbHelper<T> {
private Class<T> c;
private DatabaseHelper db;
public DbHelper(Class<T> c) {
this.c = c;
db = DatabaseHelper.getInstance();
}
This is a good idea
public List<T> queryForBuilderDistinct(int offset, int limit, String ColumnsName,
String orderName, boolean isAsc) {
try {
Dao<T, Integer> dao = db.getDao(c);
QueryBuilder<T, Integer> queryBuilder = dao.queryBuilder();
if (offset != 0) {
queryBuilder.offset((long) offset);
}
if (limit != 0) {
queryBuilder.limit((long) limit);
}
if (orderName != null) {
queryBuilder.orderBy(orderName, isAsc);
}
queryBuilder.distinct().selectColumns(ColumnsName);
return dao.query(queryBuilder.prepare());
} catch (SQLException e) {
LogUtil.e(TAG, "queryForBuilderDistinct", e);
}
return new ArrayList<T>();
}
I can't seem to wrap my head around how to setup my class hierarchy for JSON conversion using GSON.
My JSON looks like:
{
"Users": {
"id": 1,
"name": "Jim",
"location": "Huntsville"
}
}
My User List class looks like:
public class UserList {
public static List<User> Users;
#SuppressWarnings("static-access")
public void setUserList(List<User> userList){
this.Users = userList;
}
public List<User> getUserList(){
return Users;
}
}
and lastly a user class that looks like this:
public class User {
private int id;
private String name;
private String location;
public int getId(){
return id;
}
public String getName(){
return name;
}
public String getLocation(){
return location;
}
public String toString(){
return("User: [id=" + id + "], [name=" + name + "], [location=" + location + "]");
}
}
Anyone mind giving me a shove in the right direction? I'd appreciate it!
EDIT:
Forgot to show my parsing code.. (Just reading a sample JSON file from SDCard)
BufferedReader br = new BufferedReader(new FileReader(Environment.getExternalStorageDirectory() + "/user.json"));
UserList userList = gson.fromJson(br, UserList.class);
are you sure your example JSON is correct?
It does not seem to be a list of things, just one user is defined.
Furthermore, your getter and setters for Users, should be following the get/set pattern and be called
public List<User> getUsers()
public void setUsers(List<User> users)
Also, you can follow the Java convention of small case and instruct Gson to use a different casing.
Assuming that you only have one entry of Users in your JSON. This would let you parse the snippit you provided, if you change the Users property into User not a list.
#SerializedName("Users")
private User user;
So if you want a list of users you should find that in the json, this should let you parse it as a list, !note that you need to have objects, which are enclosed, like:
{"users" : [{id:"one"}, ...]}
As pointed out in the comments.
I've got this user class (this is a reduced version for the example, the real one has more parameters but they are implemented the same way):
public class User {
private int _userID;
private String _fullName;
public User(){
}
public User(int userID, String fullName){
this._userID = userID;
this._fullName = fullName;
}
int getUserID(){
return this._userID;
}
String getFullName(){
return this._fullName;
}
void setUserID(int userID){
this._userID = userID;
}
void setFullName(String fullName){
this._fullName = fullName;
}
}
And I want to retrieve a list from my MS SQL Server of this type of objects in Android, I'm using this method inside the connector helper class (the class in charge to make connection to the server using JDBC):
public List<User> getUsers(int ID){
java.sql.ResultSet result = null;
List<User> users = new ArrayList<User>();
User user = new User();
try {
connection = this.getConnection();
if (connection != null) {
//QUERY
String statement = "SELECT * Users WHERE groupID = "
+ ID;
Statement select = connection.createStatement();
//Calls Query
result = select.executeQuery(statement);
while (result.next()){
user.setUserID(result.getInt("UserID"));
user.setFullName(result.getString("FullName"));
System.out.println(result.getString("FullName"));
//Adds to the list
users.add(user);
}
result.close();
result = null;
closeConnection();
}
else {
System.out.println("Error: No active Connection");
}
} catch (Exception e) {
e.printStackTrace();
}
return users;
}
The data is retrieved well from the server according to the System.out.println I'm using in every iteration of the while, the problem is that the list is always filled with repeated information about the last user I retrieve, to clarify:
If I got users A, B and C, when I read user A, list has this structure:[A], when I read user B, list is:[B,B], when I read user C: [C,C,C], etc. So basically all the objects in the list are being overwritten by the last one read.
I've been struggling with this for hours, hope someone can spot the problem because I can't, thanks in advance for the help.
You instantiate a single User object before your loop, and then modify the same User object at each iteration. So you end up with N times the same User object added to your list. You must recreate a new User at each iteration:
while (result.next()){
User user = new User();
user.setUserID(result.getInt("UserID"));
...