How to set primary key in SQLite database after the table have been already created? - android-sqlite

How to set primary key in SQLite after table have been already created?
I am creating a project using SQLite and I have forgetton to provide the primary key to user id,now how can I set it?
Below is my ContactContract class
public final class ContactContract {
private ContactContract(){}
public static class ContactEntry
{
public static final String TABLE_NAME="contact_info";
public static final String KEY_P = "KEY";
public static final String CONTACT_ID = "contact_id";
public static final String NAME="name";
public static final String EMAIL="email";
}
}
Below is my ContactDbHelper class
public class ContactDbHelper extends SQLiteOpenHelper {
public static final String DATABASE_NAME = "contact_db";
public static final int DATABASE_VERSION = 1;
public static final String CREATE_TABLE="create table "+ContactContract.ContactEntry.TABLE_NAME+
"(" + ContactContract.ContactEntry.KEY_P +"INTEGER PRIMARY KEY," +ContactContract.ContactEntry.CONTACT_ID+" number,"+ContactContract.ContactEntry.NAME+" text,"+
ContactContract.ContactEntry.EMAIL+" text);";

Using :-
public static final String CREATE_TABLE="create table "+ContactContract.ContactEntry.TABLE_NAME+
"(" + ContactContract.ContactEntry.KEY_P +"INTEGER PRIMARY KEY," +ContactContract.ContactEntry.CONTACT_ID+" number,"+ContactContract.ContactEntry.NAME+" text,"+
ContactContract.ContactEntry.EMAIL+" text);";
Will not work as expected because of :-
You have no space after the column name and INTEGER PRIMARY KEY,,
the column name would be KEYINTEGER rather than KEY and would very likely result in issues.
the column would not be a primary key and thus would not automatically generate a useful column if a column value is omitted (as is frequently the case), the value would be null.
You cant have a column named KEY (as would be the case when adding the space before INTEGER) as it's a keyword. Perhaps use public static final String KEY_P = "KEYP"; to overcome this.
As such use :-
public static final String KEY_P = "KEYP";
or something other than = "KEY" that suits that is not a keyword
along with :-
public static final String CREATE_TABLE="create table "+ContactContract.ContactEntry.TABLE_NAME+
"(" + ContactContract.ContactEntry.KEY_P +" INTEGER PRIMARY KEY," +ContactContract.ContactEntry.CONTACT_ID+" number,"+ContactContract.ContactEntry.NAME+" text,"+
ContactContract.ContactEntry.EMAIL+" text);";
With 1 and 2 corrected. Then if you can easily regenerate the data then you could re-install the App to apply the schema changes.
However, as you state that the database has been populated and if you are unable to easily regenerate the data then it can be done.
Assuming the database currently has data (e.g. for testing the following data is part) :-
The the following method could be used to change the schema to add the PRIMARY KEY column :-
private void addPrimaryKey() {
String TAG = "ADDPRMRYKEY";
Log.d(TAG,"Initiated adding the primary key.");
SQLiteDatabase db = this.getWritableDatabase();
Cursor csr = db.query(
"sqlite_master",
null,
"name =? AND instr(sql,'PRIMARY KEY') > 0",
new String[]{ContactContract.ContactEntry.TABLE_NAME},
null,null,null
);
if (csr.getCount() < 1) {
Log.d(TAG," PRIMARY KEY clause not found for table " + ContactContract.ContactEntry.TABLE_NAME);
if (CREATE_TABLE.indexOf("PRIMARY KEY") > 0) {
Log.d(TAG,"PRIMARY KEY clause located in CREATE TABLE SQL so !!!!ALTERING!!!! table " + ContactContract.ContactEntry.TABLE_NAME);
db.execSQL("ALTER TABLE " + ContactContract.ContactEntry.TABLE_NAME + " RENAME TO OLD" + ContactContract.ContactEntry.TABLE_NAME);
Log.d(TAG,"RENAMED TABLE " + ContactContract.ContactEntry.TABLE_NAME + " to OLD" + ContactContract.ContactEntry.TABLE_NAME);
db.execSQL(CREATE_TABLE);
Log.d(TAG,"CREATED new version of table " + ContactContract.ContactEntry.TABLE_NAME + " !!!!INSERTING DATA EXTRACTED!!!! from old version");
db.execSQL("INSERT INTO " + ContactContract.ContactEntry.TABLE_NAME + " SELECT null,* FROM OLD" + ContactContract.ContactEntry.TABLE_NAME);
} else {
Log.d(TAG,"PRIMARY KEY clause not found in the CREATE TABLE SQL so doing nothing.");
}
} else {
Log.d(TAG,"PRIMARY KEY clause found for table " + ContactContract.ContactEntry.TABLE_NAME + " - Nothing to do!!!!");
}
csr.close();
}
Note obviously the Log.d statements would be removed, they have been used for testing/explanation.
The above works by
interrogating the sqlite_master table to extract the SQL used to create the table, IF it includes the PRIMARY KEY clause.
If it does the method returns without doing anything as the PRIMARY KEY has already been defined.
The potentially new/replacement table create SQL is checked to see if it contains the PRIMARY KEY clause.
If it does not then nothing will be done.
The current table is RENAMED.
A new table with the original name is created according to the create table SQL.
The data is copied from the original table to the new table.
Note that you may wish to consider deleting the renamed original table. It has not been deleted as it is safer to have it available just in case.
Rather than increase the version number the addPrimaryKey method has been incorporated into the Database Helper's constructor as per :-
public ContactDbHelper(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
addPrimaryKey(); //<<<<<<<<<< ADDED to Convert
}
the addPrimaryKey method will run every time but it will only attempt to convert the data if
the table does not have a PRIMARY KEY clause and
the CREATE SQL includes the PRIMARY KEY clause
the assumption is made that the PRIMARY KEY column is the first defined column, if not then the line db.execSQL("INSERT INTO " + ContactContract.ContactEntry.TABLE_NAME + " SELECT null,* FROM OLD" + ContactContract.ContactEntry.TABLE_NAME); should be changed accordingly.
Testing
Setup
The App was run using (KEY_P commented out as is assumed the current status):-
public static final String CREATE_TABLE = "create table " + ContactContract.ContactEntry.TABLE_NAME +
"(" +
//ContactContract.ContactEntry.KEY_P + " INTEGER PRIMARY KEY," + //<<<<<<<<<< comment out this line for first run to generate data
ContactContract.ContactEntry.CONTACT_ID + " number," +
ContactContract.ContactEntry.NAME + " text," +
ContactContract.ContactEntry.EMAIL + " text" +
");";
The invoking activity used throughout was :-
public class MainActivity extends AppCompatActivity {
ContactDbHelper mDBHlpr;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mDBHlpr = new ContactDbHelper(this);
addSomeData();
Cursor csr = mDBHlpr.getWritableDatabase().query(ContactContract.ContactEntry.TABLE_NAME,null,null,null,null,null,null);
DatabaseUtils.dumpCursor(csr);
csr.close();
/*
DataBaseHelper mDBHlpr = DataBaseHelper.getInstance(this);
Cursor csr = mDBHlpr.getWritableDatabase().query("sqlite_master",null,null,null,null,null,null);
DatabaseUtils.dumpCursor(csr);
*/
}
/**
* Add some data
*/
private void addSomeData() {
if (DatabaseUtils.queryNumEntries(mDBHlpr.getWritableDatabase(), ContactContract.ContactEntry.TABLE_NAME) > 0 ) return;
Random rnd = new Random();
for (int i=0;i < 100; i++) {
mDBHlpr.insertContact(rnd.nextInt(),"Aname" + String.valueOf(i),"Aname" + String.valueOf(i) + "#email.com");
}
}
}
This :-
Instantiates the databasehelper
Adds some data BUT only if none already exists (100 rows with randomly generated contactID's), this just to demonstrate that it works.
Extract all the rows, dumping the cursor as per
:-
2019-07-04 15:52:03.813 7758-7758/aso.so56873021recopydb D/ADDPRMRYKEY: Initiated adding the primary key.
2019-07-04 15:52:03.830 7758-7758/aso.so56873021recopydb D/ADDPRMRYKEY: PRIMARY KEY clause not found for table contact_info
2019-07-04 15:52:03.830 7758-7758/aso.so56873021recopydb D/ADDPRMRYKEY: PRIMARY KEY clause not found in the CREATE TABLE SQL so doing nothing.
2019-07-04 15:52:03.888 7758-7758/aso.so56873021recopydb I/System.out: >>>>> Dumping cursor android.database.sqlite.SQLiteCursor#791f7af
2019-07-04 15:52:03.890 7758-7758/aso.so56873021recopydb I/System.out: 0 {
2019-07-04 15:52:03.890 7758-7758/aso.so56873021recopydb I/System.out: contact_id=-1179778271
2019-07-04 15:52:03.890 7758-7758/aso.so56873021recopydb I/System.out: name=Aname0
2019-07-04 15:52:03.890 7758-7758/aso.so56873021recopydb I/System.out: email=Aname0#email.com
2019-07-04 15:52:03.890 7758-7758/aso.so56873021recopydb I/System.out: }
2019-07-04 15:52:03.890 7758-7758/aso.so56873021recopydb I/System.out: 1 {
2019-07-04 15:52:03.890 7758-7758/aso.so56873021recopydb I/System.out: contact_id=1334348157
2019-07-04 15:52:03.890 7758-7758/aso.so56873021recopydb I/System.out: name=Aname1
2019-07-04 15:52:03.890 7758-7758/aso.so56873021recopydb I/System.out: email=Aname1#email.com
2019-07-04 15:52:03.890 7758-7758/aso.so56873021recopydb I/System.out: }
2019-07-04 15:52:03.890 7758-7758/aso.so56873021recopydb I/System.out: 2 {
2019-07-04 15:52:03.891 7758-7758/aso.so56873021recopydb I/System.out: contact_id=1123604651
2019-07-04 15:52:03.891 7758-7758/aso.so56873021recopydb I/System.out: name=Aname2
2019-07-04 15:52:03.891 7758-7758/aso.so56873021recopydb I/System.out: email=Aname2#email.com
Conversion
As can be seen from the output above the addPrimaryKey method has been called but it did nothing because of D/ADDPRMRYKEY: PRIMARY KEY clause not found in the CREATE TABLE SQL so doing nothing.
As such it's just a matter of changing the CREATE SQL to include the new column to be :-
public static final String CREATE_TABLE = "create table " + ContactContract.ContactEntry.TABLE_NAME +
"(" +
ContactContract.ContactEntry.KEY_P + " INTEGER PRIMARY KEY," + //<<<<<<<<<< comment out this line for first run to generate data
ContactContract.ContactEntry.CONTACT_ID + " number," +
ContactContract.ContactEntry.NAME + " text," +
ContactContract.ContactEntry.EMAIL + " text" +
");";
i.e. the KEY_P column is no longer commented out so the new/wanted SQL is brought into play.
And the result is as per :-
2019-07-04 15:56:47.170 7979-7979/aso.so56873021recopydb D/ADDPRMRYKEY: Initiated adding the primary key.
2019-07-04 15:56:47.175 7979-7979/aso.so56873021recopydb D/ADDPRMRYKEY: PRIMARY KEY clause not found for table contact_info
2019-07-04 15:56:47.176 7979-7979/aso.so56873021recopydb D/ADDPRMRYKEY: PRIMARY KEY clause located in CREATE TABLE SQL so !!!!ALTERING!!!! table contact_info
2019-07-04 15:56:47.176 7979-7979/aso.so56873021recopydb D/ADDPRMRYKEY: RENAMED TABLE contact_info to OLDcontact_info
2019-07-04 15:56:47.177 7979-7979/aso.so56873021recopydb D/ADDPRMRYKEY: CREATED new version of table contact_info !!!!INSERTING DATA EXTRACTED!!!! from old version
2019-07-04 15:56:47.179 7979-7979/aso.so56873021recopydb I/System.out: >>>>> Dumping cursor android.database.sqlite.SQLiteCursor#791f7af
2019-07-04 15:56:47.179 7979-7979/aso.so56873021recopydb I/System.out: 0 {
2019-07-04 15:56:47.179 7979-7979/aso.so56873021recopydb I/System.out: KEYP=1
2019-07-04 15:56:47.179 7979-7979/aso.so56873021recopydb I/System.out: contact_id=-1179778271
2019-07-04 15:56:47.180 7979-7979/aso.so56873021recopydb I/System.out: name=Aname0
2019-07-04 15:56:47.180 7979-7979/aso.so56873021recopydb I/System.out: email=Aname0#email.com
2019-07-04 15:56:47.180 7979-7979/aso.so56873021recopydb I/System.out: }
2019-07-04 15:56:47.180 7979-7979/aso.so56873021recopydb I/System.out: 1 {
2019-07-04 15:56:47.180 7979-7979/aso.so56873021recopydb I/System.out: KEYP=2
2019-07-04 15:56:47.180 7979-7979/aso.so56873021recopydb I/System.out: contact_id=1334348157
2019-07-04 15:56:47.180 7979-7979/aso.so56873021recopydb I/System.out: name=Aname1
2019-07-04 15:56:47.180 7979-7979/aso.so56873021recopydb I/System.out: email=Aname1#email.com
2019-07-04 15:56:47.180 7979-7979/aso.so56873021recopydb I/System.out: }
2019-07-04 15:56:47.180 7979-7979/aso.so56873021recopydb I/System.out: 2 {
2019-07-04 15:56:47.180 7979-7979/aso.so56873021recopydb I/System.out: KEYP=3
2019-07-04 15:56:47.180 7979-7979/aso.so56873021recopydb I/System.out: contact_id=1123604651
2019-07-04 15:56:47.181 7979-7979/aso.so56873021recopydb I/System.out: name=Aname2
2019-07-04 15:56:47.181 7979-7979/aso.so56873021recopydb I/System.out: email=Aname2#email.com
i.e. the data has been retained but the new column has been introduced and values assigned.

In SQLite there is no option to add the primary key for the existing table. So if you want to add the primary key to the existing table follow the below steps.
Create table with columns and mark the column as the primary key. For fresh installs of app, inside onCreate() method,
CREATE TABLE cities (
id INTEGER NOT NULL PRIMARY KEY,
name TEXT NOT NULL
);
For existing db, in onUpgrade() method
BEGIN TRANSACTION; //db.beginTransaction();
ALTER TABLE cities RENAME TO old_cities;
CREATE TABLE cities (
id INTEGER NOT NULL PRIMARY KEY,
name TEXT NOT NULL
);
INSERT INTO cities SELECT * FROM old_cities;
DROP TABLE old_cities;
COMMIT; //db.setTransactionSuccessful();
Code it inside try/catch, have finally block to end the transaction.
finally {
db.endTransaction();
}
Don't forget to increment the database version.

Related

GENERATE ALWAYS AS IDENTITY in h2 DDL

In our project we use postgres Database for dev to prod environment and for junit testing we use H2 in memory database.
want to know can we create DDL with GENERATE ALWAYS AS IDENTITY to insert each row with unique id in H2 database.
IDENTITY
In H2, use the IDENTITY type, for automatically generating an incrementing 64-bit long integer.
This single-word syntax used in H2 is an abbreviated variation of GENERATED … AS IDENTITY defined in the SQL:2003 standard. See summary in PDF document SQL:2003 Has Been Published. Other databases are implementing this, such as Postgres.
CREATE TABLE event_
(
pkey_ IDENTITY NOT NULL PRIMARY KEY , -- ⬅ `identity` = auto-incrementing long integer.
name_ VARCHAR NOT NULL ,
start_ TIMESTAMP WITH TIME ZONE NOT NULL ,
duration_ VARCHAR NOT NULL
)
;
Example usage. No need to pass a value for our pkey column value as it is being automatically generated by H2.
INSERT INTO event_ ( name_ , start_ , stop_ )
VALUES ( ? , ? , ? )
;
And in Java.
ZoneId z = ZoneId.of( "America/Montreal" ) ;
OffsetDateTime start = ZonedDateTime.of( 2021 , Month.JANUARY , 23 , 19 , 0 , 0 , 0 , z ).toOffsetDateTime() ;
Duration duration = Duration.ofHours( 2 ) ;
myPreparedStatement.setString( 1 , "Java User Group" ) ;
myPreparedStatement.setObject( 2 , start ) ;
myPreparedStatement.setString( 3 , duration.toString() ) ;
Returning generated keys
If you want to return the generated keys, see example code in this similar Answer of mine.

Unable to insert data in PostgreSQL 11.0 table

I would like to insert values into postgresql 11.0 table. However, when I am trying to do that I am getting following error:
TypeError: not all arguments converted during string formatting
I am running following code:
#CREATE TABLE
try:
connect_str = "dbname='xx' user='xx' host='xx' " "password='xx' port = xx"
conn = psycopg2.connect(connect_str)
except:
print("Unable to connect to the database")
cursor = conn.cursor()
cursor.execute("""DROP TABLE IF EXISTS tbl""")
try:
cursor.execute("""
CREATE TABLE IF NOT EXISTS tbl(
entry_id CHARACTER VARYING NOT NULL,
name CHARACTER VARYING NOT NULL,
class CHARACTER VARYING NOT NULL,
ko_id CHARACTER VARYING NOT NULL,
PRIMARY KEY (entry_id))
""")
except:
print("The table cannot be created!")
conn.commit()
conn.close()
cursor.close()
#INSERT DATA INTO TABLE
try:
connect_str = "dbname='xx' user='xx' host='xx' " "password='xx' port = xx"
conn = psycopg2.connect(connect_str)
except:
print("Unable to connect to the database")
cursor = conn.cursor()
with open ('file.txt') as f:
for line in f:
if re.match('^[A-Z]+',line) and line.startswith("ENTRY") or line.startswith("NAME") or line.startswith("CLASS") or line.startswith("KO_PATHWAY"):
key, value = line.split(" ", 1)
#print (key, value)
if key == "ENTRY":
cursor.execute("INSERT INTO tbl (entry_id) VALUES (%s)",('value'))
conn.commit()
conn.close()
cursor.close()
The key-value looks like this:
ENTRY map00010 Pathway
NAME Glycolysis / Gluconeogenesis
CLASS Metabolism; Carbohydrate metabolism
KO_PATHWAY ko00010
ENTRY map00011 Pathway
NAME Glycolysis
CLASS Metabolism; Carbohydrate
KO_PATHWAY ko00011
The value map00010 Pathway and map00011 Pathway should be inserted in the table and create two rows.
Any help is highly appreciated.

Unable to insert nested record in postgres

i had managed to create tables in postgres but encountered issues when trying to insert values.
comands = (
CREATE TYPE student AS (
name TEXT,
id INTEGER
)
CREATE TABLE studentclass(
date DATE NOT NULL,
time TIMESTAMPTZ NOT NULL,
PRIMARY KEY (date, time),
class student
)
)
And in psycog2
command = (
INSERT INTO studentclass (date, time, student) VALUES (%s,%s, ROW(%s,%s)::student)
)
student_rec = ("John", 1)
record_to_insert = ("2020-05-21", "2020-05-21 08:10:00", student_rec)
cursor.execute(commands, record_to_insert)
When executed, the errors are the incorrect argument and if i tried to hard coded the student value inside the INSERT statement, it will inform me about the unrecognized column for student.
Please advise.
One issue is the column name is class not student. Second is psycopg2 does tuple adaption as composite type
So you can do:
insert_sql = "INSERT INTO studentclass (date, time, class) VALUES (%s,%s,%s)"
student_rec = ("John", 1)
record_to_insert = ("2020-05-21", "2020-05-21 08:10:00", student_rec)
cur.execute(insert_sql, record_to_insert)
con.commit()
select * from studentclass ;
date | time | class
------------+-------------------------+----------
05/21/2020 | 05/21/2020 08:10:00 PDT | (John,1)

How to Concatenate rows linked to single ID using group by?

I'm writing a script to create a table that will concatenate the data from the table having the same ID. The output should be as follows: "IF DSW7841_gUDT.sOpState = 1 OR DSW7842_gUDT.sOpState = 1 OR DSW8841_gUDT.sOpState = 1 THEN GLB084.ModuleInOut.mDoorOpen := 1; ELSE GLB084.ModuleInOut.mDoorOpen := 0; END_IF;"
The script that i have written is like this:
begin
create table if not exists public.opstate_mappings (
id uuid primary key default gen_random_uuid(),
door_switch_opstate_id uuid references door_switch_opstate(id) on delete cascade,
opstate_mapping text not null unique
);
insert into opstate_mapping(door_switch_opstate_id, opstate_mapping)
select door_switch_opstate.software_instance_id,
GROUP_CONCAT('IF',door_switch_opstate.door_switches,'_gUDT.sOpState = 1 OR') AS opstate_mapping
FROM door_switch_opstate
GROUP BY software_instance_id;
end;
This is the table i am extracting data from EDIT: THIS PICTURE SHOWS ONLY ONE ID THAT IS LINKED WITH ALL THE DOOR_SWITCHES, THERE ARE OTHER MORE ID'S LINKED WITH OTHER ROWS
In Postgres the command you seek is STRING_AGG and would go something like this:
CONCAT('IF ',
STRING_AGG(door_switch_opstate.door_switches, '_gUDT.sOpState = 1 OR'),
'_gUDT.sOpState = 1 THEN GLB084.ModuleInOut.mDoorOpen := 1; ELSE GLB084.ModuleInOut.mDoorOpen := 0; END_IF;'
)

Ormlite query help for newbie

Having a few problems with Ormlite and Android/Sqlite so any help appreciated. The database structure is
"CREATE TABLE [jobTasks](" +
"[JobTaskID] varchar(50) NOT NULL PRIMARY KEY DEFAULT (newid())," +
"[JobID] varchar(50) NOT NULL," +
"[EnumTaskType] Real," +
"[TaskID] varchar(50)," +
"[TaskOrder] SmallInt," +
"[TaskDescription] NVarChar (50) ," +
"[EnumTaskStatus] Real," +
"[EnumTaskQualifier] Real," +
"[IsTaskQualifierForced] Bit," +
"[CompletedBy] NVarChar (50)," +
"[CompletedOn] DateTime," +
"[CompletedOnOffset] NVarChar (6)," +
"[JobAssetID] varchar(50),[wadtDeleted] Bit NOT NULL DEFAULT ((0))," +
"[WadtModifiedBy] NVarChar (15)," +
"[WadtModifiedOn] DateTime," +
"[WadtModifiedOnDTOffset] NVarChar (6)," +
"[WadtRowID] varchar(50) DEFAULT (newid())," +
"[ParentJobTaskID] varchar(50)," +
"[Rowguid] varchar(50) NOT NULL DEFAULT (newid())," +
"SyncDeleted Bit NOT NULL DEFAULT ((0))," +
"FOREIGN KEY(JobID) REFERENCES jobJob(jobID)," +
"FOREIGN KEY(enumTaskType) REFERENCES enumTaskType(enumTaskType)," +
"FOREIGN KEY(TaskID) REFERENCES cfgWorkFlowTasks(TaskID)," +
"FOREIGN KEY(enumTaskStatus) REFERENCES enumTaskStatus(enumTaskStatus))"
The query is
QueryBuilder<JobParentTask, String> qb =
_databaseContext.JobParentTasks().queryBuilder();
qb.orderBy(JobParentTask.TASKORDER, true);
qb.where().eq(JobParentTask.JOBID, id).and()
.isNull(JobParentTask.PARENTJOBTASKID);
PreparedQuery<JobParentTask> preparedQuery = queryBuilder.prepare();
CloseableIterator<JobParentTask> iterator
=_databaseContext.JobParentTasks().iterator(jobParentTaskPreparedQuery);
while (iterator.hasNext()) {
parentTasks.add(iterator.next());
}
The following error is thrown
unrecognized token: "6B582835": , while compiling:
SELECT * FROM `jobTasks` WHERE
`JobID` = 6B582835-5A79-E011-A5E4-005056980009 AND `ParentJobTaskID` IS NULL )
ORDER BY `TaskOrder`
If I am passing the id as a string value why does it not show as such in the query?
The final error thrown is
java.sql.SQLException: Could not build prepared-query iterator for class
conx.Entities.JobParentTask
I assume this is related to the original error?
Thanks in advance
Will hang my head in shame. The JOBID was associated as a column name annotation for the wrong column.
Huh. I suspect you have an existing database table that you are trying to match a Java class against? Any chance that the JobID field in your Java class is not a string but is, by accident, an integer?
The eq(JobParentTask.JOBID, id) method should look at the field inside of JobParentTask and see that it is a String that needs to be escaped. This is core code in ORMLite that has been working for some time.
Can you post the JobParentTask definition around the JobID field?
If you still are having problems an immediate workaround is to use the "Select Args":
http://ormlite.com/docs/select-arg
Something like:
SelectArg jobIdArg = new SelectArg(id);
queryBuilder.where().eq(JobParentTask.JOBID, jobIdArg).and()...
Then the query that is constructed used a ? and injects the argument using SQL.