ContentProvider.Query - How to select the table I want using URIs? - java

I'm currently facing a database query issue. I have two tables, items and details with the following schema definition:
items(_id, title, type) <--- _id is primary key
details(_id, _itemid, name, quantity, dosis) <--- _id is primary key. _itemid is foreign key
Furthermore I access my database via. my own contentProvider. In my activity I want to query the details table to get all tuples, however Im not sure how to "get" the table using URI's. My query is:
Uri subItems = Uri.parse("content://tod.dosetracker.provider.Food");
Cursor c = getContentResolver().query(
subItems,
new String[] {"*"},
"_itemid = " + _id,
null,
null);
In my ContentProvider class I have the following (extract):
public static final String PROVIDER_NAME = "tod.dosetracker.provider.Food";
public static final Uri CONTENT_URI_ITEMS = Uri.parse("content://" + PROVIDER_NAME + "/items");
public static final Uri CONTENT_URI_DETAILS = Uri.parse("content://" + PROVIDER_NAME + "/details");
public static final String _ID = "_id";
public static final String _ITEMID = "_itemid";
public static final String TITLE = "title";
public static final String TYPE = "type";
public static final String NAME = "name";
public static final String DOSIS = "dosis";
public static final String QUANTITY = "quantity";
private static final int ITEM = 1;
private static final int ITEM_ID = 2;
private static final int DETAILS = 3;
private static final int DETAILS_ID = 4;
// URI resource matchers
private static final UriMatcher uriMatcher;
static {
uriMatcher = new UriMatcher(UriMatcher.NO_MATCH);
uriMatcher.addURI(PROVIDER_NAME, "items", ITEM);
uriMatcher.addURI(PROVIDER_NAME, "items/#", ITEM_ID);
uriMatcher.addURI(PROVIDER_NAME, "details", DETAILS);
uriMatcher.addURI(PROVIDER_NAME, "details/#", DETAILS_ID);
}
// Database reference name
private SQLiteDatabase foodDB;

You are using the wrong content uri. Use the one you defined for your items instead(if you want items)
FoodContentProvider.CONTENT_URI_ITEMS
So your query would look like this (oh BTW just put null if you want all columns);
Uri subItems = Uri.parse("content://tod.dosetracker.provider.Food");
Cursor c = getContentResolver().query(
CONTENT_URI_ITEMS,
null,
"_itemid = " + _id,
null,
null);

Related

How to insert values with Foreign KEY in SQLite?

I am new with Android Sqlite Database.
I have created a database with SQLite in Android and I have a table Student_details which use a foreign key of the table: Student, I have made the id as AUTOINCREMENT.
And i tried to return the value of the AUTOINCREMENT Id from Student table.
But I am stuck to use the return values to insert into COLUMN_FR_KEY_USER_ID = "student_id"; as Foreign Key values.
How can I add value with a foreign key from another table using ContentValues into insetDataIntoStudentDetails method?
DatabaseHelper.java
public class DatabaseHelper extends SQLiteOpenHelper {
private static final String DATABASE_NAME = "finalStudent.db";
private static final int VERSION_NUMBER = 16;
private static final String TABLE_STUDENT = "Student";
private static final String TABLE_DETAILS_NAME = "Student_details";
private static final String COLUMN_STUDENT_ID = "id";
private static final String COLUMN_DETAILS_ID = "id";
private static final String COLUMN_FR_KEY_USER_ID = "student_id";
private static final String COLUMN_STUDENT_NAME = "name";
private static final String COLUMN_DETAILS_NAME = "name";
private static final String COLUMN_STUDENT_EMAIL = "email";
private static final String COLUMN_STUDENT_PASSWORD = "password";
private static final String CREATE_STUDENT_TABLE = "CREATE TABLE "+TABLE_STUDENT+"( "+COLUMN_STUDENT_ID+" INTEGER PRIMARY KEY AUTOINCREMENT, "+COLUMN_STUDENT_NAME+" TEXT, "+COLUMN_STUDENT_EMAIL+" TEXT, "+COLUMN_STUDENT_PASSWORD+" TEXT)";
private static final String CREATE_DETAILS_TABLE = "CREATE TABLE "+TABLE_DETAILS_NAME+"( "+COLUMN_DETAILS_ID+" INTEGER PRIMARY KEY AUTOINCREMENT, "+COLUMN_DETAILS_NAME+" TEXT, "+COLUMN_FR_KEY_USER_ID+" INTEGER, FOREIGN KEY("+COLUMN_FR_KEY_USER_ID+") REFERENCES "+TABLE_STUDENT+" ("+COLUMN_STUDENT_ID+") ON UPDATE CASCADE ON DELETE CASCADE)";
private Context context;
private static final String DROP_TABLE = "DROP TABLE IF EXISTS "+TABLE_STUDENT;
private static final String DROP_DETAILS_TABLE = "DROP TABLE IF EXISTS "+TABLE_DETAILS_NAME;
public DatabaseHelper(Context context) {
super(context, DATABASE_NAME, null, VERSION_NUMBER);
this.context = context;
}
#Override
public void onCreate(SQLiteDatabase db) {
try {
Toast.makeText(context,"Table created successfully and called onCreate method",Toast.LENGTH_SHORT).show();
db.execSQL(CREATE_STUDENT_TABLE);
db.execSQL(CREATE_DETAILS_TABLE);
}catch (Exception e){
Toast.makeText(context,"Exception : "+e,Toast.LENGTH_SHORT).show();
}
}
#Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
try {
Toast.makeText(context,"Table created successfully and called onCreate method",Toast.LENGTH_SHORT).show();
db.execSQL(DROP_TABLE);
db.execSQL(DROP_DETAILS_TABLE);
onCreate(db);
}catch (Exception e){
Toast.makeText(context,"Exception : "+e,Toast.LENGTH_SHORT).show();
}
}
public long insertDataIntoStudent( String name, String email, String password){
// to write or read data in database , we have to call getWritableDatabase
SQLiteDatabase sqLiteDatabase = this.getWritableDatabase();
// we have to call contentValues class to store data in the data
ContentValues contentValues = new ContentValues();
contentValues.put(COLUMN_STUDENT_NAME,name);
contentValues.put(COLUMN_STUDENT_EMAIL,email);
contentValues.put(COLUMN_STUDENT_PASSWORD,password);
// Insert the new row, returning the primary key value of the new row
long newRowId = sqLiteDatabase.insert(TABLE_STUDENT,null,contentValues);
return newRowId;
}
public void insetDataIntoStudentDetails(String name){
SQLiteDatabase sqLiteDatabase = this.getWritableDatabase();
ContentValues contentValues = new ContentValues();
// TODO: insert the foreign key's value
contentValues.put(name,name);
}
#Override
public void onOpen(SQLiteDatabase db) {
super.onOpen(db);
//enable foreign key constraints like ON UPDATE CASCADE, ON DELETE CASCADE
db.execSQL("PRAGMA foreign_keys=ON;");
}
}
MainActivity.java
public class MainActivity extends AppCompatActivity {
private final AppCompatActivity activity = MainActivity.this;
DatabaseHelper databaseHelper;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
databaseHelper = new DatabaseHelper(activity);
databaseHelper.insertDataIntoStudent("Bappy","abcd#gmail.com","145456");
}
}
I'll answer about databases in general, not specifically about Sqlite or it's usage in Android.
So you have student's name (which is not a primary key), but you need to save some additional data for this student to another table. The steps are:
Execute SELECT id FROM students WHERE name = ? to find the relevant identifier.
Execute INSERT INTO student_details for your secondary table using retrieved id as a key.
Extra tips:
Name is not a good unique identifier. It's good to have one more criteria - such as some group name, or group number or even date of birth.
When your database is large enough you may benefit from index for your search criteria to optimize execution of the first query. But usually it's not the case for client-side (in-app) databases.
Here we assume that name is not the data which could be updated by someone (or something) else between searching for id and executing INSERT. Otherwise it's wise to use transaction and "lock" your student until you complete the updates.

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!

Android - using variable from another activity

I'm quite new to Android and I guess it's a stupid question but i'll be glad to recieve help. I've got a code in one activity which set a database to SQLite. In another activity I want to refer to this SQLite code in order to enter it into a json and send it to a remote server.
The problem is that it's not recognizing the variable from the other activity. here is the code which creates the data from the db into a string.
In this example I want to create an ArrayList from the db, but it couldnt find the set functions I developed or the table name. Am I missed something ? Here is the code of the ArrayList :
GpsPage.java
public class PersonsDatabaseHandler extends SQLiteOpenHelper {
//Database Name
private static final String DATABASE_NAME = "RecordsDB";
//Table names
private static final TABLE_RECORD = "record";
//Get all Persons
public ArrayList<Record> getAllPersons() {
ArrayList<Record> localList = new ArrayList<Record>();
String selectQuery = "SELECT * FROM " + TABLE_RECORD;
SQLiteDatabase db = this.getReadableDatabase();
Cursor cursor = db.rawQuery(selectQuery, null);
//Loops through all rows and adds them to the local list
if(cursor.moveToFirst())
{
do {
//Get person information
Record record = new Record();
Record.setpLong(cursor.getString(0));
Record.setpLat(cursor.getString(1));
Record.setpAcc(cursor.getString(2));
Record.setpTime(cursor.getString(3));
//Add person to list
localList.add(record);
} while (cursor.moveToNext());
}
return localList;
}
}
And here are the codes from the two other java pages (activities), the first one define the get and set of the records :
Record.Java
package com.program.android.taskir;
public class Record {
//private variables
private int id;
private double pLong;
private double pLat;
private float pAcc;
private long pTime;
public Record(){}
// Empty constructor
// constructor
public Record( double pLong, double pLat, float pAcc, long pTime){
super();
this.pLong = pLong;
this.pLat= pLat;
this.pAcc= pAcc;
this.pTime= pTime;
}
#Override
public String toString() {
return "Record [id=" + id + ", Longtitude=" + pLong + ", Latitude=" + pLat + ", Accuracy" + pAcc + ", Time" +pTime
+ "]";
}
// getting ID
public int getID(){
return this.id;
}
// setting id
public void setID(int id){
this.id = id;
}
// getting pLong
public double getpLong(){
return this.pLong;
}
// setting pLong
public void setpLong(double pLong){
this.pLong = pLong;
}
// getting pLat
public double getpLat(){
return this.pLat;
}
// setting pLat
public void setpLat(double pLat){
this.pLat = pLat;
}
// getting pAcc
public float getpAcc(){
return this.pAcc;
}
// setting pAcc
public void setpAcc(float pAcc){
this.pAcc = pAcc;
}
// getting pTime
public long getpTime(){
return this.pTime;
}
// setting pTime
public void setpTime(long pTime){
this.pTime = pTime;
}
}
and the activity which creates the db :
MySQLiteHelper.java
package com.program.android.taskir;
import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.util.Log;
import java.util.LinkedList;
import java.util.List;
public class MySQLiteHelper extends SQLiteOpenHelper {
// Database Version
private static final int DATABASE_VERSION = 1;
// Database Name
private static final String DATABASE_NAME = "RecordsDB";
public MySQLiteHelper(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
}
#Override
public void onCreate(SQLiteDatabase db) {
// SQL statement to create record table
String CREATE_RECORD_TABLE = "CREATE TABLE RECORD ( " +
"id INTEGER PRIMARY KEY AUTOINCREMENT, " +
"latitude TEXT NOT NULL, " +
"longtitude TEXT NOT NULL, " +
"accuracy TEXT NOT NULL, " +
"time TEXT NOT NULL )";
// create books table
db.execSQL(CREATE_RECORD_TABLE);
}
#Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
// Drop older books table if existed
db.execSQL("DROP TABLE IF EXISTS Records");
// create fresh record table
this.onCreate(db);
}
// Books table name
private static final String TABLE_RECORD = "record";
// Books Table Columns names
private static final String KEY_ID = "id";
private static final String KEY_LONG = "longtitude";
private static final String KEY_LAT = "latitude";
private static final String KEY_ACC = "accuracy";
private static final String KEY_TIME = "time";
private static final String[] COLUMNS = {KEY_ID, KEY_LONG, KEY_LAT, KEY_ACC, KEY_TIME};
public void addRecord(Record record) {
//for logging
Log.d("addBook", record.toString());
// 1. get reference to writable DB
SQLiteDatabase db = this.getWritableDatabase();
// 2. create ContentValues to add key "column"/value
ContentValues values = new ContentValues();
values.put(KEY_LONG, record.getpLong());
values.put(KEY_LAT, record.getpLat());
values.put(KEY_ACC, record.getpAcc());
values.put(KEY_TIME, record.getpTime());
// 3. insert
db.insert(TABLE_RECORD, // table
null, //nullColumnHack
values); // key/value -> keys = column names/ values = column values
// 4. close
db.close();
}
public Record getRecord(int id) {
// 1. get reference to readable DB
SQLiteDatabase db = this.getReadableDatabase();
// 2. build query
Cursor cursor =
db.query(TABLE_RECORD, // a. table
COLUMNS, // b. column names
" id = ?", // c. selections
new String[]{String.valueOf(id)}, // d. selections args
null, // e. group by
null, // f. having
null, // g. order by
null); // h. limit
// 3. if we got results get the first one
if (cursor != null)
cursor.moveToFirst();
// 4. build book object
Record record = new Record();
record.setID(Integer.parseInt(cursor.getString(0)));
record.setpLat(cursor.getDouble(1));
record.setpLong(cursor.getDouble(2));
record.setpAcc(cursor.getFloat(2));
record.setpTime(cursor.getLong(2));
//log
Log.d("getBook(" + id + ")", record.toString());
// 5. return book
return record;
}
public List<Record> getAllRecords() {
List<Record> records = new LinkedList<Record>();
// 1. build the query
String query = "SELECT * FROM " + TABLE_RECORD;
// 2. get reference to writable DB
SQLiteDatabase db = this.getWritableDatabase();
Cursor cursor = db.rawQuery(query, null);
// 3. go over each row, build book and add it to list
Record record = null;
if (cursor.moveToFirst()) {
do {
record = new Record();
record.setID(Integer.parseInt(cursor.getString(0)));
record.setpLat(cursor.getDouble(1));
record.setpLong(cursor.getDouble(2));
record.setpAcc(cursor.getFloat(2));
record.setpTime(cursor.getLong(2));
// Add book to books
records.add(record);
} while (cursor.moveToNext());
}
Log.d("getAllRecords()", record.toString());
// return books
return records;
}
public int UpdateRecords(Record record) {
// 1. get reference to writable DB
SQLiteDatabase db = this.getWritableDatabase();
// 2. create ContentValues to add key "column"/value
ContentValues values = new ContentValues();
values.put("Latitude", record.getpLat()); //
values.put("Longtitude", record.getpLong());
values.put("Accuracy", record.getpAcc());
values.put("Time", record.getpTime());
// 3. updating row
int i = db.update(TABLE_RECORD, //table
values, // column/value
KEY_ID + " = ?", // selections
new String[]{String.valueOf(record.getID())}); //selection args
// 4. close
db.close();
return i;
}
public void deleteRecords(Record record) {
// 1. get reference to writable DB
SQLiteDatabase db = this.getWritableDatabase();
// 2. delete
db.delete(TABLE_RECORD, //table name
KEY_ID + " = ?", // selections
new String[]{String.valueOf(record.getID())}); //selections args
// 3. close
db.close();
//log
Log.d("deleteBook", record.toString());
}
}
Thank you!
What you are looking for is a Bundle. It's used to pass data between activities. Take a look at What is a "bundle" in an Android application and you can understand how it's done.

QueryDSL joins and subqueries with native SQL

I use Spring Data and QueryDSL 3.2.4 and I want to implement the following SQL query with QueryDSLs native SQL API:
WITH ORDER_GROUP AS ( -- TODO have to merge this subquery into the main query
SELECT
ordergroup
,count(ID) AS nofOrdersPerGroup
,MIN(priority) as minPriority
,MIN(requesteddeliverytime) as minRequestedDeliveryTime
,MIN(creationtime) as minCreationTime
FROM ORDERHEADER hh
group by orderGroup
),
ALL_ORDERS AS ( -- TODO have to merge this subquery into the main query
SELECT h.ordercode
, h.ordergroup
, h.priority
, h.requesteddeliverytime
, h.creationtime
, h.statecode
, (SELECT COUNT(ID)
FROM orderposition p
WHERE p.orderheaderid = h.ID
) AS nof_positions_per_order
, CASE
WHEN h.ordergroup IS NOT NULL
THEN g.nofOrdersPerGroup
ELSE 1
END AS nof_orders_per_group
, CASE
WHEN h.ordergroup IS NOT NULL
THEN g.minPriority
ELSE h.priority
END AS most_important_prio
, CASE
WHEN h.ordergroup IS NOT NULL
THEN g.minRequestedDeliveryTime
ELSE h.requesteddeliverytime
END AS earliest_del_time
, CASE
WHEN h.ordergroup IS NOT NULL
THEN g.minCreationTime
ELSE h.creationtime
END AS earliest_cre_time
FROM ORDERHEADER h left outer join ORDER_GROUP g on h.ordergroup = g.ordergroup
WHERE 1=1 -- TODO have to add filter clauses here
)
SELECT ordercode
, ordergroup
, priority
, requesteddeliverytime
, creationtime
, statecode
, nof_positions_per_order
, nof_orders_per_group
, most_important_prio
, earliest_del_time
, earliest_cre_time
FROM ALL_ORDERS
ORDER BY most_important_prio
, earliest_del_time
, earliest_cre_time
, priority
, requesteddeliverytime
, creationtime;
The join is not on a FK column but on some arbitrary attribute of the subquery ORDER_GROUP. This subquery aggregates some min / max valuse on on OrderHeader for later use in sorting.
The query types are:
package com.stoecklin.wms.entity;
import static com.mysema.query.types.PathMetadataFactory.*;
import com.mysema.query.types.path.*;
import com.mysema.query.types.PathMetadata;
import javax.annotation.Generated;
import com.mysema.query.types.Path;
import com.mysema.query.types.path.PathInits;
/**
* QOrderHeader is a Querydsl query type for OrderHeader
*/
#Generated("com.mysema.query.codegen.EntitySerializer")
public class QOrderHeader extends EntityPathBase<OrderHeader> {
private static final long serialVersionUID = 2006939562;
public static final QOrderHeader orderHeader = new QOrderHeader("orderHeader");
public final com.stoecklin.utility.database.QBaseEntity _super = new com.stoecklin.utility.database.QBaseEntity(this);
public final DateTimePath<java.util.Date> actualDeliveryTime = createDateTime("actualDeliveryTime", java.util.Date.class);
public final StringPath creationMode = createString("creationMode");
//inherited
public final DateTimePath<java.util.Date> creationTime = _super.creationTime;
public final StringPath customerCode = createString("customerCode");
public final StringPath customerOrderCode = createString("customerOrderCode");
public final StringPath deliveryCode = createString("deliveryCode");
public final StringPath deliveryNote = createString("deliveryNote");
public final StringPath headerText = createString("headerText");
public final NumberPath<Integer> hostId = createNumber("hostId", Integer.class);
public final NumberPath<Long> id = createNumber("id", Long.class);
//inherited
public final DateTimePath<java.util.Date> lastUpdateTime = _super.lastUpdateTime;
public final StringPath orderCode = createString("orderCode");
public final StringPath orderGroup = createString("orderGroup");
public final ListPath<OrderPosition, QOrderPosition> orderPositions = this.<OrderPosition, QOrderPosition>createList("orderPositions", OrderPosition.class, QOrderPosition.class, PathInits.DIRECT2);
public final StringPath orderTypeCode = createString("orderTypeCode");
public final StringPath priority = createString("priority");
public final DateTimePath<java.util.Date> requestedDeliveryTime = createDateTime("requestedDeliveryTime", java.util.Date.class);
public final StringPath setupType = createString("setupType");
public final StringPath shippingMode = createString("shippingMode");
public final StringPath stagingArea = createString("stagingArea");
public final EnumPath<com.stoecklin.wms.enums.OrderHeaderState> stateCode = createEnum("stateCode", com.stoecklin.wms.enums.OrderHeaderState.class);
public final StringPath stateReason = createString("stateReason");
public final DateTimePath<java.util.Date> stateTime = createDateTime("stateTime", java.util.Date.class);
//inherited
public final NumberPath<Long> version = _super.version;
public QOrderHeader(String variable) {
super(OrderHeader.class, forVariable(variable));
}
public QOrderHeader(Path<? extends OrderHeader> path) {
super(path.getType(), path.getMetadata());
}
public QOrderHeader(PathMetadata<?> metadata) {
super(OrderHeader.class, metadata);
}
}
and
package com.stoecklin.wms.entity;
import static com.mysema.query.types.PathMetadataFactory.*;
import com.mysema.query.types.path.*;
import com.mysema.query.types.PathMetadata;
import javax.annotation.Generated;
import com.mysema.query.types.Path;
import com.mysema.query.types.path.PathInits;
/**
* QOrderPosition is a Querydsl query type for OrderPosition
*/
#Generated("com.mysema.query.codegen.EntitySerializer")
public class QOrderPosition extends EntityPathBase<OrderPosition> {
private static final long serialVersionUID = 2091670278;
private static final PathInits INITS = PathInits.DIRECT2;
public static final QOrderPosition orderPosition = new QOrderPosition("orderPosition");
public final com.stoecklin.utility.database.QBaseEntity _super = new com.stoecklin.utility.database.QBaseEntity(this);
public final StringPath articleCode = createString("articleCode");
//inherited
public final DateTimePath<java.util.Date> creationTime = _super.creationTime;
public final NumberPath<Integer> customerOrderPos = createNumber("customerOrderPos", Integer.class);
public final NumberPath<Float> deliveredQuantity = createNumber("deliveredQuantity", Float.class);
public final StringPath fromWarehouseCode = createString("fromWarehouseCode");
public final StringPath hostData = createString("hostData");
public final StringPath hostRef = createString("hostRef");
public final NumberPath<Long> id = createNumber("id", Long.class);
//inherited
public final DateTimePath<java.util.Date> lastUpdateTime = _super.lastUpdateTime;
public final StringPath lotCode = createString("lotCode");
public final NumberPath<Float> missingQuantity = createNumber("missingQuantity", Float.class);
public final QOrderHeader orderHeader;
public final NumberPath<Integer> orderPos = createNumber("orderPos", Integer.class);
public final StringPath ownerCode = createString("ownerCode");
public final StringPath posText = createString("posText");
public final NumberPath<Float> requestedQuantity = createNumber("requestedQuantity", Float.class);
public final EnumPath<com.stoecklin.wms.enums.OrderPositionState> stateCode = createEnum("stateCode", com.stoecklin.wms.enums.OrderPositionState.class);
public final StringPath stateReason = createString("stateReason");
public final DateTimePath<java.util.Date> stateTime = createDateTime("stateTime", java.util.Date.class);
public final StringPath toBePicked = createString("toBePicked");
public final StringPath toLocation = createString("toLocation");
//inherited
public final NumberPath<Long> version = _super.version;
public QOrderPosition(String variable) {
this(OrderPosition.class, forVariable(variable), INITS);
}
public QOrderPosition(Path<? extends OrderPosition> path) {
this(path.getType(), path.getMetadata(), path.getMetadata().isRoot() ? INITS : PathInits.DEFAULT);
}
public QOrderPosition(PathMetadata<?> metadata) {
this(metadata, metadata.isRoot() ? INITS : PathInits.DEFAULT);
}
public QOrderPosition(PathMetadata<?> metadata, PathInits inits) {
this(OrderPosition.class, metadata, inits);
}
public QOrderPosition(Class<? extends OrderPosition> type, PathMetadata<?> metadata, PathInits inits) {
super(type, metadata, inits);
this.orderHeader = inits.isInitialized("orderHeader") ? new QOrderHeader(forProperty("orderHeader")) : null;
}
}
Now the questions:
How do I have to do the join at the bottom of the ALL_ORDERS subquery? I already tried the following:
QOrderHeader orderHeader = QOrderHeader.orderHeader;
QOrderHeader orderHeaderGroup = new QOrderHeader("orderHeaderGroup");
QOrderPosition orderPosition = QOrderPosition.orderPosition;
List<Tuple> tuples = query.from(orderHeader)
.leftJoin(orderHeader, orderHeaderGroup).on(orderHeader.orderGroup.eq(orderHeaderGroup.orderGroup))
.list(
orderHeader.orderGroup,
orderHeader.id
);
but this even won't compile because there is no matching method leftJoin available.
The join is not on a FK column but on some arbitrary attribute. The subquery ORDER_GROUP
How is the correlated subquery implemented which computes the nof_orders_per_group (7th item in SELECT list)? (I have no clue how tho do this :-))
The SQL shown on the top is somewhat optimized for efficiency. For that reason I decided to use native SQL because we have subqueries all around.
Any help is appreciated.
If you want to use Querydsl with SQL then you need to create the metamodel in a different way, which is described here http://www.querydsl.com/static/querydsl/3.2.4/reference/html/ch02s03.html
And to your more specific questions:
1) FROM ORDERHEADER h left outer join ORDER_GROUP g on h.ordergroup = g.ordergroup
from(h).leftJoin(g).on(h.ordergroup.eq(g.ordergroup))
2) CASE
WHEN h.ordergroup IS NOT NULL
THEN g.nofOrdersPerGroup
ELSE 1
END AS nof_orders_per_group
new CaseBuilder()
.when(h.ordergroup.isNotNull()).then(g.nofOrderPerGroup)
.otherwise(1)
Concerning query construction, joins work different from JPA
Querydsl JPA
query.join(entity.property, reference)
Querydsl SQL
query.join(table).on(condition)
or alternatively
query.join(table.fk, otherTable)

Android Database SQLite Average

I am making an app for android with a SQLite Database that have only one table and two columns: one for names and the other for marks. Also, I can see the information of the database in a listview and I can add more elements to it. How can I make the average of the marks which are in the database? And how can I delete a row?
I paste my database helper
public class PersonDatabaseHelper {
private static final String TAG = PersonDatabaseHelper.class.getSimpleName();
// database configuration
// if you want the onUpgrade to run then change the database_version
private static final int DATABASE_VERSION = 1;
private static final String DATABASE_NAME = "mydatabase.db";
// table configuration
private static final String TABLE_NAME = "person_table"; // Table name
private static final String PERSON_TABLE_COLUMN_ID = "_id"; // a column named "_id" is required for cursor
private static final String PERSON_TABLE_COLUMN_NAME = "person_name";
private static final String PERSON_TABLE_COLUMN_PIN = "person_pin";
private DatabaseOpenHelper openHelper;
private SQLiteDatabase database;
// this is a wrapper class. that means, from outside world, anyone will communicate with PersonDatabaseHelper,
// but under the hood actually DatabaseOpenHelper class will perform database CRUD operations
public PersonDatabaseHelper(Context aContext) {
openHelper = new DatabaseOpenHelper(aContext);
database = openHelper.getWritableDatabase();
}
public void insertData (String aPersonName, String aPersonPin) {
// we are using ContentValues to avoid sql format errors
ContentValues contentValues = new ContentValues();
contentValues.put(PERSON_TABLE_COLUMN_NAME, aPersonName);
contentValues.put(PERSON_TABLE_COLUMN_PIN, aPersonPin);
database.insert(TABLE_NAME, null, contentValues);
}
public Cursor getAllData () {
String buildSQL = "SELECT * FROM " + TABLE_NAME;
Log.d(TAG, "getAllData SQL: " + buildSQL);
return database.rawQuery(buildSQL, null);
}
// this DatabaseOpenHelper class will actually be used to perform database related operation
private class DatabaseOpenHelper extends SQLiteOpenHelper {
public DatabaseOpenHelper(Context aContext) {
super(aContext, DATABASE_NAME, null, DATABASE_VERSION);
}
#Override
public void onCreate(SQLiteDatabase sqLiteDatabase) {
// Create your tables here
String buildSQL = "CREATE TABLE " + TABLE_NAME + "( " + PERSON_TABLE_COLUMN_ID + " INTEGER PRIMARY KEY, " +
PERSON_TABLE_COLUMN_NAME + " TEXT, " + PERSON_TABLE_COLUMN_PIN + " TEXT )";
Log.d(TAG, "onCreate SQL: " + buildSQL);
sqLiteDatabase.execSQL(buildSQL);
}
#Override
public void onUpgrade(SQLiteDatabase sqLiteDatabase, int oldVersion, int newVersion) {
// Database schema upgrade code goes here
String buildSQL = "DROP TABLE IF EXISTS " + TABLE_NAME;
Log.d(TAG, "onUpgrade SQL: " + buildSQL);
sqLiteDatabase.execSQL(buildSQL); // drop previous table
onCreate(sqLiteDatabase); // create the table from the beginning
}
}
}
Use the avarage (avg) aggregate function:
String query = "SELECT AVG("+PERSON_TABLE_COLUMN_PIN +") FROM "+TABLE_NAME;
and then use SQLiteDatabase.rawQuery(String sql, String[] selectionArgs) for executing the query. Something like:
database.rawQuery(query, null);
Here you can find a sample fiddle.
While, for deleting a row, you can use SQLiteDatabase.delete(String table, String whereClause, String[] whereArgs). For example:
String where = PERSON_TABLE_COLUMN_ID+"=?";
String[] whereArgs = new String[]{String.valueOf(59)};
database.delete(TABLE_NAME, where, whereArgs);
the above code delete the row with id 59.

Categories