I am trying to run my code but every time it throws me this exception
no such column: codigo
This is my code, and the place where it happens.
PolideportivoDAO.java
if (init){
//CategoriaSocial categoria = null;
List<CategoriaSocial> listaDeCategorias = new Vector<CategoriaSocial>();
//Categoria Social
if (CategoriaDAO.getInstance(context).obtenerTodosLasCategorias().size() == 0){
listaDeCategorias.add(CategoriaDAO.getInstance(context).crearCategoriaNueva("1", "Miembro A",
"Miembro con todos los privilegios, pase diario y uso de la piscina"));
listaDeCategorias.add(CategoriaDAO.getInstance(context).crearCategoriaNueva("2", "Miembro B",
"Permiso para uso de las instalaciones tres veces a la semana"));
listaDeCategorias.add(CategoriaDAO.getInstance(context).crearCategoriaNueva("3", "Miembro C",
"Permiso para uso de las instalaciones solo fin de semana de 8 am a 16 pm"));
}
CategoriaDAO.java
public List<CategoriaSocial> obtenerTodosLasCategorias() {
List<CategoriaSocial> categorias = new Vector<CategoriaSocial>();
Cursor cursor = db.query(ICategoriaSQLiteHelper.TABLA_CATEGORIA_SOCIAL,
ICategoriaSQLiteHelper.columnasCategoria, null, null, null, null, null);
cursor.moveToFirst();
while (!cursor.isAfterLast()){
CategoriaSocial categoria = crearCategoriaDesdeCursor(cursor);
categorias.add(categoria);
cursor.moveToNext();
}
cursor.close();
return categorias;
}
ICategoriaSQLiteHelper.java
package com.example.polideportivo1;
public class ICategoriaSQLiteHelper{
public static final String TABLA_CATEGORIA_SOCIAL = "Categoria";
public static final String COLUMNA_ID = "id";
public static final String COLUMNA_CODIGO = "codigo";
public static final String COLUMNA_CATEGORIA = "nombre";
public static final String COLUMNA_DESCRIPCION = "descripcion";
public static final String[] columnasCategoria =
{ ICategoriaSQLiteHelper.COLUMNA_ID,
ICategoriaSQLiteHelper.COLUMNA_CODIGO,
ICategoriaSQLiteHelper.COLUMNA_CATEGORIA,
ICategoriaSQLiteHelper.COLUMNA_DESCRIPCION,
};
public static String TABLA_CATEGORIA_SOCIAL_CREACION = "CREATE TABLE "
+ TABLA_CATEGORIA_SOCIAL + "(" + COLUMNA_ID + " INTEGER primary key autoincrement, "
+ COLUMNA_CODIGO + " TEXT not null unique,"
+ COLUMNA_CATEGORIA + " TEXT not null,"
+ COLUMNA_DESCRIPCION + " TEXT"
+ ");";
}
The code samples you posted are not sufficient to see where the exception occurs, so I suppose it happens here:
Cursor cursor = db.query(ICategoriaSQLiteHelper.TABLA_CATEGORIA_SOCIAL ...
and that 1) the table exists 2) it doesn't contain a column named "codigo" (the value of ICategoriaSQLiteHelper.COLUMNA_CODIGO).
Aren't you trying to run your code an old table Categoria that was created a while ago, and that was not containing a column codigoat that time?
If this is so, removing that old table, and creating a new one - this time using TABLA_CATEGORIA_SOCIAL_CREACION as in your above samples - should solve the issue.
The error message says it quite clearly.
You are attempting to access a field in your database that is not there.
Related
I have an inherited project, a BMC Remedy application and never worked with this Remedy stuff. This project modifies Incidents and Work Orders from remedy through the Remedy API. I have literally no idea on this.
There's a process that closes incidents that are in resolved state and have not been modified in the last 36 hours. Sometimes, those incidents have the 'categorization' field empty, and the client wants to fill this categorization before closing it.
This is part of the code:
Connection to Remedy:
public static void main(String args[]) {
// Inicializamos el logger
java.util.logging.LogManager.getLogManager().reset();
try {
// Nos conectamos a Remedy y a MySQL
LOGGER.info("Conectando a bases de datos");
if (!connect()) {
throw new Exception("Fallo al conectar a Remedy o a MySQL");
}
// Metodo para cerrar incidecias resueltas
remedy.cerrarIncidencias(sql.queryResueltas36h());
// Desconectamos de Remedy y MySQL
disconnect();
} catch (Exception e) {
LOGGER.error("Error critico: ", e);
try {
remedy.desconectar();
} catch (Exception e1) {
}
try {
sql.desconectar();
} catch (Exception e1) {
}
}
}
Function to closing incidents:
public void cerrarIncidencias(List<String> incs) throws Exception {
int contador = 1;
for (String inc : incs) {
try {
// Obtenemos la incidencia
QualifierInfo qual = server.parseQualification("HPD:Help Desk", "'Incident Number' = \"" + inc + "\"");
List<Entry> entries = server.getListEntryObjects("HPD:Help Desk", qual, 0, 0, null,
Constantes.CAMPOS_HPD_HELP_DESK_CERRAR_INCIDENCIA, false, null);
// Rellenamos un comentario generico
Entry comment = new Entry();
comment.put(Constantes.HPD_WORKLOG_DETAILED_DESCRIPTION, new Value("Cierre automatico tras 36 horas en resuelto."));
comment.put(Constantes.HPD_WORKLOG_INCIDENT_NUMBER, new Value(inc));
comment.put(Constantes.HPD_WORKLOG_DESCRIPTION, new Value("----"));
comment.put(Constantes.HPD_WORKLOG_WORKLOG_TYPE, new Value(8000));
for (Entry entry : entries) {
entry.put(Constantes.HPD_HELP_DESK_STATUS, new Value(5)); // Estado a cerrado
if (entry.get(Constantes.HPD_HELP_DESK_ASSIGNEE_LOGIN_ID).getValue() == null) {
entry.put(Constantes.HPD_HELP_DESK_ASSIGNEE_LOGIN_ID, new Value("lmoren70"));
entry.put(Constantes.HPD_HELP_DESK_ASSIGNEE, new Value("Luis Manuel Moreno Rodriguez")); // Usuario asignado
}
server.setEntry("HPD:Help Desk", entry.getEntryId(), entry, null, 0);
server.createEntry("HPD:WorkLog", comment);
LOGGER.info("Incidencia " + inc + " cerrada con exito - " + contador + " de " + incs.size());
}
} catch (Exception e) {
LOGGER.error("Incidencia " + inc + " NO se ha podido cerrar - " + contador + " de " + incs.size() + "\n"
+ e.getMessage());
}
contador++;
}
}
Query:
I thought to do an update directly to the database BUT this database reads from Remedy, so I have to update Remedy.
public List<String> queryResueltas36h() {
String query = "SELECT inc FROM vdf_tickets, vdf_groups WHERE status = 'Resuelto' AND LENGTH(inc) > 9 "
+ "AND vdf_groups.group = creator_group AND (vdf_groups.categorization = 'TES' OR vdf_groups.group IN ('TES', 'ARCA', 'NetOps TES Assurance')) "
+ "AND last_resolved_date < DATE_ADD(NOW(), INTERVAL -36 HOUR) ORDER BY inc DESC";
List<String> incs = new ArrayList<String>();
try {
stmt = conn.createStatement();
ResultSet rs = stmt.executeQuery(query);
while (rs.next()) {
String inc = rs.getString("inc");
incs.add(inc);
}
stmt.close();
} catch (Exception e) {
LOGGER.error("Error al obtener lista de incidencias de la base de datos", e);
try {
stmt.close();
} catch (Exception e1) {
}
}
return incs;
}
What I want is to put the categorization to 'TES', in case there's no categorization.
One option I thought is to do an automation with Selenium and Python and not touching this code, but is far better to have all in the same project.
Any ideas? Thanks in advance!
You need to update your cerrarIncidencias function. But first you need to ask what categorisation you need to update.
There are three levels of categorisation.
Operational Categorisation
Product Categorisation
Resolution Categorisation
So decide which one you want to populate and get the field id for that field. For this example, I will say
Categorisation Tier 1 which is 1000000063
You'll need to add to CAMPOS_HPD_HELP_DESK_CATEGORISATION_TIER1=1000000063 to your Constantes file.
Then in your block
for (Entry entry : entries)
You need something like:
if (entry.get(Constantes.CAMPOS_HPD_HELP_DESK_CATEGORISATION_TIER1).getValue() == null) {
entry.put(Constantes.CAMPOS_HPD_HELP_DESK_CATEGORISATION_TIER1, new Value("Your Value for Categorisation Tier 1"));
}
I have a Room database which is stored in assets/database with its preloaded data. I am creating an updated version with more contents in the database for the next update.
Currently, if I add new contents to the database with no schema changes and reinstall the app, these new contents do not show up. The only way I can see the changes is if I uninstall and reinstall the app. However, I need to merge the user's data with the database with the new contents since I need to get the "favorites" of the user which is an integer column of a table with the item contents.
Is this possible?
This is how I create my database.
public static AppDatabase getInMemoryDatabase(Context context) {
if (INSTANCE == null) {
synchronized (AppDatabase.class) {
if (INSTANCE == null) {
INSTANCE = Room.databaseBuilder(context.getApplicationContext(), AppDatabase.class, "app_database.db")
.createFromAsset("database/QuotesDB.db")
.addMigrations(MIGRATION_1_2)
.build();
}
}
}
return INSTANCE;
}
I tried to migrate with the following code but it still doesn't update the contents.
/**
* Migrate from:
* version 1 - initial contents.
* to
* version 2 - updated database contents (no schema changes)
*/
#VisibleForTesting
static final Migration MIGRATION_1_2 = new Migration(1, 2) {
#Override
public void migrate(SupportSQLiteDatabase database) {
// I need to tell Room that it should use the data
// from version 1 ( with the user's favorites ) to version 2.
}
};
Is this possible?
Yes. However it is a little complex.
In short, you can actually do it the other way round. Rather than use the new database from the asset and try to retrive the previous data (is complicated if using Room Migration as you have to effectiviely swap to the newly created/copied database which is further complicated as you're inside a transaction when migrating).
If however you do the schema changes to the database in use rather than the asset database, you can then get the asset database and copy the new non-user data (would be greatly complicated if the user's data were intermingled with the non-user data).
Even this isn't that simple. However, here's a simple exmaple/scanario based upon a slight expansion of your code to :-
static final Migration MIGRATION_1_2 = new Migration(1, 2) {
#Override
public void migrate(SupportSQLiteDatabase db) {
final String TAG = "MIGRATE_1_2";
Log.d(TAG,"Database Version when called is " + db.getVersion());
// I need to tell Room that it should use the data
// from version 1 ( with the user's favorites ) to version 2.
// "CREATE TABLE IF NOT EXISTS `userdata` (`userId` INTEGER DEFAULT uid, `name` TEXT, PRIMARY KEY(`userId`))"
//db.execSQL("CREATE TABLE IF NOT EXISTS `userdata_saveuserdata` (`userId` INTEGER, `name` TEXT, PRIMARY KEY(`userId`))");
//db.execSQL("INSERT INTO `userdata_saveuserdata` SELECT * FROM `userdata`");
db.execSQL("ALTER TABLE `otherdata` ADD COLUMN `column2` TEXT");
Log.d(TAG,"Checking Context");
if (sContext != null) {
applyAssetDB(db);
} else {
Log.d(TAG,"Context is null!!!!");
}
}
};
As you can see this changes the otherdata table (not the users table) by adding a new column.
It then checks to see if sContext isn't null.
A valid Context is used rather then hard coding paths.
Then the applyAssetDB is invoked, which is :-
private static void applyAssetDB(SupportSQLiteDatabase sdb) {
String TAG = "APPLYASSETDB";
String mainDatabaseName = (new File(sdb.getPath()).getName());
String assetDatabaseName = mainDatabaseName + "_asset";
String asset_schema = "asset_schema";
Log.d(TAG,"Attempting application of asset data to database."
+ "\n\tActual Database = " + mainDatabaseName
+ "\n\tAsset Database will be " + assetDatabaseName
+ "\n\tSchema for attached database will be " + asset_schema
);
copyDatabaseFromAssets(AppDatabase.sContext,MainActivity.ASSETNAME,assetDatabaseName);
/*
if (sdb.isWriteAheadLoggingEnabled()) {
setAssetDBToWALMode(sContext.getDatabasePath(assetDatabaseName).getPath());
}
Log.d(TAG,"Attempting to ATTACH asset database " + sContext.getDatabasePath(assetDatabaseName).getPath() + "." + asset_schema);
sdb.execSQL("ATTACH DATABASE '" + sContext.getDatabasePath(assetDatabaseName).getPath() + "' AS " + asset_schema);
Log.d(TAG,"Attempting INSERTING NEW DATA using\n\t" + "INSERT OR IGNORE INTO `otherdata` SELECT * FROM `otherdata`." + asset_schema);
sdb.execSQL("INSERT OR IGNORE INTO `otherdata` SELECT * FROM `otherdata`." + asset_schema);
Log.d(TAG,"Attempting to DETACH " + sContext.getDatabasePath(assetDatabaseName).getPath() + "." + asset_schema);
sdb.execSQL("DETACH DATABASE '" + sContext.getDatabasePath(assetDatabaseName).getPath() + "." + asset_schema);
*/
int insertRows = 0;
SQLiteDatabase assetdb = SQLiteDatabase.openDatabase(sContext.getDatabasePath(assetDatabaseName).getPath(),null,SQLiteDatabase.OPEN_READONLY);
Cursor assetCursor = assetdb.query("`otherdata`",null,null,null,null,null,null);
ContentValues cv = new ContentValues();
while (assetCursor.moveToNext()) {
cv.clear();
for (String c: assetCursor.getColumnNames()) {
if (assetCursor.getType(assetCursor.getColumnIndex(c)) == Cursor.FIELD_TYPE_BLOB) {
cv.put(c,assetCursor.getBlob(assetCursor.getColumnIndex(c)));
} else {
cv.put(c,assetCursor.getString(assetCursor.getColumnIndex(c)));
}
}
if (sdb.insert("`otherdata`", OnConflictStrategy.IGNORE,cv) > 0 ) insertRows++;
}
Log.d(TAG,"Inserted " + insertRows + " from the Asset Database");
assetCursor.close();
Log.d(TAG,"Deleting " + sContext.getDatabasePath(assetDatabaseName).getPath());
if ((new File(sContext.getDatabasePath(assetDatabaseName).getPath())).delete()) {
Log.d(TAG,"Copied AssetDatabase successfully deleted.");
} else {
Log.d(TAG,"Copied Asset Database file not deleted????");
}
Log.d(TAG,"Finished");
}
commented out code left in intentionally as issue were encountered when trying to ATTACH the database copied from the assets, so reverted to using seperate connetions.
This copies the database from the asset to the defauly database location via the copyDatabaseFromAssets method (as below). It the extracts all of the non user's data from the asset database and inserts it into the original (but altered according to the changed schema) database relying upon the OnConflictStrategy.IGNORE to only insert new rows. The userdata table is untouched, so the user's data is retianed.
Obviously this would not cater for changed rows.
Here's copyDatabaseFromAssets
private static void copyDatabaseFromAssets(Context context, String assetName, String databaseName) {
String TAG = "COPYDBFROMASSET";
int bufferSize = 1024 * 4, length = 0, read = 0, written = 0, chunks = 0;
byte[] buffer = new byte[bufferSize];
try {
Log.d(TAG,"Attempting opening asset " + assetName + " as an InputFileStream.");
InputStream is = context.getAssets().open(assetName);
Log.d(TAG,"Attempting opening FileOutputStream " + context.getDatabasePath(databaseName).getPath());
OutputStream os = new FileOutputStream(context.getDatabasePath(databaseName));
Log.d(TAG,"Initiating copy.");
while((length = is.read(buffer)) > 0) {
read += length;
os.write(buffer,0,length);
written += length;
chunks++;
}
Log.d(TAG,"Read " + read + "bytes; Wrote " + written + " bytes; in " + chunks);
Log.d(TAG,"Finalising (Flush and Close output and close input)");
os.flush();
os.close();
is.close();
Log.d(TAG,"Finalised");
} catch (IOException e) {
throw new RuntimeException("Error copying Database from Asset " + e.getMessage());
}
}
Here's an example Activity MainActivity that puts this all together (noting that for convenience I've used allowMainThreadQueries ) :-
public class MainActivity extends AppCompatActivity {
//public static final int DBVERSION = 1; //!!!!! ORIGINAL
public static final int DBVERSION = 2;
public static final String DBNAME = "app_database.db";
public static final String ASSETNAME = "database/QuotesDB.db";
AppDatabase appDB;
AllDao adao;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
appDB.setContext(this);
appDB = Room.databaseBuilder(this,AppDatabase.class,DBNAME)
.allowMainThreadQueries()
.createFromAsset(ASSETNAME)
.addCallback(AppDatabase.CALLBACK)
.addMigrations(AppDatabase.MIGRATION_1_2)
.build();
adao = appDB.allDao();
appDB.logDBInfo();
if (adao.getUserDataRowCount() == 3) {
adao.insertOneUserData(new UserData("ADDEDU100"));
adao.insertOneUserData(new UserData("ADDEDU200"));
adao.insertOneUserData(new UserData("ADDEDU300"));
}
appDB.logDBInfo();
}
}
When run (after changing the relevant code for the new schema and increasing the version) the result in the log is :-
2019-11-30 10:56:38.768 12944-12944/a.roommigrationwithassets D/MIGRATE_1_2: Database Version when called is 1
2019-11-30 10:56:38.771 12944-12944/a.roommigrationwithassets D/MIGRATE_1_2: Checking Context
2019-11-30 10:56:38.771 12944-12944/a.roommigrationwithassets D/APPLYASSETDB: Attempting application of asset data to database.
Actual Database = app_database.db
Asset Database will be app_database.db_asset
Schema for attached database will be asset_schema
2019-11-30 10:56:38.771 12944-12944/a.roommigrationwithassets D/COPYDBFROMASSET: Attempting opening asset database/QuotesDB.db as an InputFileStream.
2019-11-30 10:56:38.771 12944-12944/a.roommigrationwithassets D/COPYDBFROMASSET: Attempting opening FileOutputStream /data/user/0/a.roommigrationwithassets/databases/app_database.db_asset
2019-11-30 10:56:38.771 12944-12944/a.roommigrationwithassets D/COPYDBFROMASSET: Initiating copy.
2019-11-30 10:56:38.771 12944-12944/a.roommigrationwithassets D/COPYDBFROMASSET: Read 12288bytes; Wrote 12288 bytes; in 3
2019-11-30 10:56:38.771 12944-12944/a.roommigrationwithassets D/COPYDBFROMASSET: Finalising (Flush and Close output and close input)
2019-11-30 10:56:38.772 12944-12944/a.roommigrationwithassets D/COPYDBFROMASSET: Finalised
2019-11-30 10:56:38.780 12944-12944/a.roommigrationwithassets D/APPLYASSETDB: Inserted 3 from the Asset Database
2019-11-30 10:56:38.780 12944-12944/a.roommigrationwithassets D/APPLYASSETDB: Deleting /data/user/0/a.roommigrationwithassets/databases/app_database.db_asset
2019-11-30 10:56:38.780 12944-12944/a.roommigrationwithassets D/APPLYASSETDB: Copied AssetDatabase successfully deleted.
2019-11-30 10:56:38.780 12944-12944/a.roommigrationwithassets D/APPLYASSETDB: Finished
2019-11-30 10:56:38.815 12944-12944/a.roommigrationwithassets D/ONOPEN: Database Version when called is 2
2019-11-30 10:56:38.816 12944-12944/a.roommigrationwithassets D/ONOPEN: Database Version after Super call is 2
2019-11-30 10:56:38.819 12944-12944/a.roommigrationwithassets D/DBINFO: UserData rowcount = 6
ID = 1 NAME = OU1
ID = 2 NAME = OU2
ID = 3 NAME = OU3
ID = 4 NAME = ADDEDU100
ID = 5 NAME = ADDEDU200
ID = 6 NAME = ADDEDU300
OtherData rowcount = 3
ID = 1Column1 = OD1
ID = 2Column1 = OD2
ID = 3Column1 = OD3
2019-11-30 10:56:38.821 12944-12944/a.roommigrationwithassets D/DBINFO: UserData rowcount = 6
ID = 1 NAME = OU1
ID = 2 NAME = OU2
ID = 3 NAME = OU3
ID = 4 NAME = ADDEDU100
ID = 5 NAME = ADDEDU200
ID = 6 NAME = ADDEDU300
OtherData rowcount = 3
ID = 1Column1 = OD1
ID = 2Column1 = OD2
ID = 3Column1 = OD3
The complete code for the AppDatabase class (noting that this includes some redundant code) is :-
#Database(version = MainActivity.DBVERSION, exportSchema = false,entities = {UserData.class,OtherData.class})
abstract class AppDatabase extends RoomDatabase {
abstract AllDao allDao();
static Context sContext;
static final Migration MIGRATION_1_2 = new Migration(1, 2) {
#Override
public void migrate(SupportSQLiteDatabase db) {
final String TAG = "MIGRATE_1_2";
Log.d(TAG,"Database Version when called is " + db.getVersion());
// I need to tell Room that it should use the data
// from version 1 ( with the user's favorites ) to version 2.
// "CREATE TABLE IF NOT EXISTS `userdata` (`userId` INTEGER DEFAULT uid, `name` TEXT, PRIMARY KEY(`userId`))"
//db.execSQL("CREATE TABLE IF NOT EXISTS `userdata_saveuserdata` (`userId` INTEGER, `name` TEXT, PRIMARY KEY(`userId`))");
//db.execSQL("INSERT INTO `userdata_saveuserdata` SELECT * FROM `userdata`");
db.execSQL("ALTER TABLE `otherdata` ADD COLUMN `column2` TEXT");
Log.d(TAG,"Checking Context");
if (sContext != null) {
applyAssetDB(db);
} else {
Log.d(TAG,"Context is null!!!!");
}
}
};
static final RoomDatabase.Callback CALLBACK = new RoomDatabase.Callback() {
#Override
public void onCreate(#NonNull SupportSQLiteDatabase db) {
Log.d("ONCREATE","Database Version when called is " + db.getVersion());
super.onCreate(db);
Log.d("ONCREATE","Database Version after Super call is " + db.getVersion());
}
#Override
public void onOpen(#NonNull SupportSQLiteDatabase db) {
Log.d("ONOPEN","Database Version when called is " + db.getVersion());
super.onOpen(db);
Log.d("ONOPEN","Database Version after Super call is " + db.getVersion());
}
#Override
public void onDestructiveMigration(#NonNull SupportSQLiteDatabase db) {
Log.d("ONDESTRMIG","Database Version when called is " + db.getVersion());
super.onDestructiveMigration(db);
Log.d("ONDESTRMIG","Database Version after Super call is " + db.getVersion());
}
};
public void logDBInfo() {
AllDao adao = this.allDao();
List<UserData> allUserDataRows = adao.getAllUserDataRows();
StringBuilder sb = new StringBuilder().append("UserData rowcount = ").append(allUserDataRows.size());
for (UserData u: allUserDataRows) {
sb.append("\n\tID = ").append(u.getId()).append(" NAME = " + u.getName());
}
List<OtherData> allOtherDataRows = adao.getAllOtherDataRows();
sb.append("\n\nOtherData rowcount = ").append(allOtherDataRows.size());
for (OtherData o: allOtherDataRows) {
sb.append("\n\tID = ").append(o.getOtherDataId()).append("Column1 = ").append(o.getColumn1());
}
Log.d("DBINFO",sb.toString());
}
static void setContext(Context context) {
sContext = context;
}
private static void applyAssetDB(SupportSQLiteDatabase sdb) {
String TAG = "APPLYASSETDB";
String mainDatabaseName = (new File(sdb.getPath()).getName());
String assetDatabaseName = mainDatabaseName + "_asset";
String asset_schema = "asset_schema";
Log.d(TAG,"Attempting application of asset data to database."
+ "\n\tActual Database = " + mainDatabaseName
+ "\n\tAsset Database will be " + assetDatabaseName
+ "\n\tSchema for attached database will be " + asset_schema
);
copyDatabaseFromAssets(AppDatabase.sContext,MainActivity.ASSETNAME,assetDatabaseName);
/*
if (sdb.isWriteAheadLoggingEnabled()) {
setAssetDBToWALMode(sContext.getDatabasePath(assetDatabaseName).getPath());
}
Log.d(TAG,"Attempting to ATTACH asset database " + sContext.getDatabasePath(assetDatabaseName).getPath() + "." + asset_schema);
sdb.execSQL("ATTACH DATABASE '" + sContext.getDatabasePath(assetDatabaseName).getPath() + "' AS " + asset_schema);
Log.d(TAG,"Attempting INSERTING NEW DATA using\n\t" + "INSERT OR IGNORE INTO `otherdata` SELECT * FROM `otherdata`." + asset_schema);
sdb.execSQL("INSERT OR IGNORE INTO `otherdata` SELECT * FROM `otherdata`." + asset_schema);
Log.d(TAG,"Attempting to DETACH " + sContext.getDatabasePath(assetDatabaseName).getPath() + "." + asset_schema);
sdb.execSQL("DETACH DATABASE '" + sContext.getDatabasePath(assetDatabaseName).getPath() + "." + asset_schema);
*/
int insertRows = 0;
SQLiteDatabase assetdb = SQLiteDatabase.openDatabase(sContext.getDatabasePath(assetDatabaseName).getPath(),null,SQLiteDatabase.OPEN_READONLY);
Cursor assetCursor = assetdb.query("`otherdata`",null,null,null,null,null,null);
ContentValues cv = new ContentValues();
while (assetCursor.moveToNext()) {
cv.clear();
for (String c: assetCursor.getColumnNames()) {
if (assetCursor.getType(assetCursor.getColumnIndex(c)) == Cursor.FIELD_TYPE_BLOB) {
cv.put(c,assetCursor.getBlob(assetCursor.getColumnIndex(c)));
} else {
cv.put(c,assetCursor.getString(assetCursor.getColumnIndex(c)));
}
}
if (sdb.insert("`otherdata`", OnConflictStrategy.IGNORE,cv) > 0 ) insertRows++;
}
Log.d(TAG,"Inserted " + insertRows + " from the Asset Database");
assetCursor.close();
Log.d(TAG,"Deleting " + sContext.getDatabasePath(assetDatabaseName).getPath());
if ((new File(sContext.getDatabasePath(assetDatabaseName).getPath())).delete()) {
Log.d(TAG,"Copied AssetDatabase successfully deleted.");
} else {
Log.d(TAG,"Copied Asset Database file not deleted????");
}
Log.d(TAG,"Finished");
}
private static void copyDatabaseFromAssets(Context context, String assetName, String databaseName) {
String TAG = "COPYDBFROMASSET";
int bufferSize = 1024 * 4, length = 0, read = 0, written = 0, chunks = 0;
byte[] buffer = new byte[bufferSize];
try {
Log.d(TAG,"Attempting opening asset " + assetName + " as an InputFileStream.");
InputStream is = context.getAssets().open(assetName);
Log.d(TAG,"Attempting opening FileOutputStream " + context.getDatabasePath(databaseName).getPath());
OutputStream os = new FileOutputStream(context.getDatabasePath(databaseName));
Log.d(TAG,"Initiating copy.");
while((length = is.read(buffer)) > 0) {
read += length;
os.write(buffer,0,length);
written += length;
chunks++;
}
Log.d(TAG,"Read " + read + "bytes; Wrote " + written + " bytes; in " + chunks);
Log.d(TAG,"Finalising (Flush and Close output and close input)");
os.flush();
os.close();
is.close();
Log.d(TAG,"Finalised");
} catch (IOException e) {
throw new RuntimeException("Error copying Database from Asset " + e.getMessage());
}
}
private static void setAssetDBToWALMode(String assetDBPath) {
SQLiteDatabase db = SQLiteDatabase.openDatabase(assetDBPath,null,SQLiteDatabase.OPEN_READWRITE);
db.enableWriteAheadLogging();
db.close();
}
}
Yes, It is possible.
The one precondition is your pre-shipped database and app database version must be the same. For example, your first release will have both databases as version 1. Now for the second release with new data update the pre-shipped and app database version to 2 and your database builder code will look like this:
Room.databaseBuilder(context.getApplicationContext(), AppDatabase.class, "app_database.db")
.createFromAsset("database/QuotesDB.db")
.fallbackToDestructiveMigration()
.build();
Prepopulate your Room database Docs
This medium article explains this nicely
Yes it is possible!
increase your SQLite VERSION and add .fallbackToDestructiveMigration() in your Room.databaseBuilder()
Room.databaseBuilder(context.getApplicationContext(), AppDatabase.class, "app_database.db")
.createFromAsset("database/QuotesDB.db")
.fallbackToDestructiveMigration()
.build();
I have an application with a list of people and you can change the info of one certain person when you click on a button. So I am trying to update my database but it says that I do not have a value for the 7th parameter, however I do have 7 values. When I print it, it does give me 7 values. It doesn't have a problem with the null (in my if else) because I already tried it without that.
This is my msql
CREATE TABLE Persoon(
persoonId int(3) NOT NULL AUTO_INCREMENT,
leeftijd int(3),
voornaam varchar(40) NOT NULL,
achternaam varchar (40) NOT NULL,
datum date,
locatieId int(3),
filmId int(3) NOT NULL,
PRIMARY KEY (persoonId),
FOREIGN KEY (filmId) references Film(filmId),
FOREIGN KEY (locatieId) references Locatie(locatieId));
My java code
private void btnWijzigenActionPerformed(java.awt.event.ActionEvent evt) {
Object geselecteerdeObject = lstPersonen.getSelectedValue();
Persoon geselecteerdePersoon = (Persoon) geselecteerdeObject;
if(txtLeeftijd.getText() != ""){
try {
String string = txtDatum.getText();
DateFormat format = new SimpleDateFormat("yyyy-MM-dd", Locale.ENGLISH);
Date datumString = format.parse(string);
Persoon nieuwePersoon = new Persoon(geselecteerdePersoon.getPersoonId(),Integer.parseInt(txtLeeftijd.getText()), txtVoornaam.getText(), txtAchternaam.getText(),datumString,geselecteerdePersoon.getLocatieId(),geselecteerdePersoon.getFilmId());
System.out.println("1p "+geselecteerdePersoon.getPersoonId() + " 2p " +Integer.parseInt(txtLeeftijd.getText()) + " 3p "+txtVoornaam.getText() + " 4p " + txtAchternaam.getText() + " 5p " + datumString + " 6p "+ geselecteerdePersoon.getLocatieId()+ " 7p " +geselecteerdePersoon.getFilmId());;
PersoonDao.updatePersoon(nieuwePersoon);
} catch (ParseException ex) {
Logger.getLogger(HoofdGUI.class.getName()).log(Level.SEVERE, null, ex);
}
}
else{
Persoon nieuwePersoon = new Persoon(geselecteerdePersoon.getPersoonId(),0, txtVoornaam.getText(), txtAchternaam.getText(),null,geselecteerdePersoon.getLocatieId(),geselecteerdePersoon.getFilmId());
PersoonDao.updatePersoon(nieuwePersoon);
}
updatePersoonsLijst();
}
My method updatePersoonsLijst
public void updatePersoonsLijst() {
mijnModel.clear();
ArrayList<Persoon> lijstVanPersonen = PersoonDao.getPersonen();
for (Persoon huidigePersoon : lijstVanPersonen) {
mijnModel.addElement(huidigePersoon);
}
}
And my updatePersoon
public static int updatePersoon(Persoon nieuwePersoon) {
int aantalAangepasteRijen = 0;
try {
aantalAangepasteRijen = Database.voerSqlUitEnHaalAantalAangepasteRijenOp("UPDATE Persoon SET leeftijd=?,voornaam=?,achternaam=?,datum=?,locatieId=?,filmId=? WHERE persoonId=?", new Object[] { nieuwePersoon.getLeeftijd(),nieuwePersoon.getVoornaam(), nieuwePersoon.getAchternaam(), nieuwePersoon.getDatum(), nieuwePersoon.getLocatieId(),nieuwePersoon.getFilmId() });
} catch (SQLException ex) {
ex.printStackTrace();
// Foutafhandeling naar keuze
}
return aantalAangepasteRijen;
}
Your update statement is missing last parameter personid - your last is filmid currently.
aantalAangepasteRijen = Database.voerSqlUitEnHaalAantalAangepasteRijenOp("UPDATE Persoon
SET leeftijd=?,voornaam=?,achternaam=?,datum=?,locatieId=?,filmId=?
WHERE persoonId=?", new Object[]
{ nieuwePersoon.getLeeftijd(),
nieuwePersoon.getVoornaam(),
nieuwePersoon.getAchternaam(),
nieuwePersoon.getDatum(),
nieuwePersoon.getLocatieId(),
nieuwePersoon.getFilmId()
// persoonId missing!!
});
This question already has answers here:
What is a NullPointerException, and how do I fix it?
(12 answers)
Closed 7 years ago.
My app craches when i try to update my database it gives me the following problem
attempt to invoke virtual method 'android.database.cursor com.leoni.bd.Gestion_db.FindDate(java.lang.String)' on a null object reference
i couldn't find the null object i tried many things but it didn't work ! i need help please !
this is my Gestion_db.java class
private SQLiteDatabase _myDbm;
public Gestion_db(Context pContext) {
SqliteCreator s = new SqliteCreator(pContext, Stat.DB_NAME, null, 1);
_myDbm = s.getWritableDatabase();
}
public void close() {
_myDbm.close();
}
public Cursor FindDate(String Attribute) {
String query = "SELECT * FROM " +Stat.TABLE_NAME +" WHERE ? LIKE '%?%' ";
return _myDbm.rawQuery(query, new String[] {Stat.COL_DATE,Attribute});
}
this is the method from my Controle.java activity wich contain the cursor
//header of the activity
private Gestion_db _myGestionDB;
private String _myRecognizedText = null;
// Mise à jour de la base de données quelque soit l'action
private void MiseAJour() {
String dateCourante = new SimpleDateFormat("yyyy:MM:dd",Locale.getDefault()).format(new Date());
Boolean existe=false;
Cursor c = _myGestionDB.FindDate(dateCourante);
if (c.getCount() != 0) {
c.moveToFirst();
while (!c.isAfterLast()) {
String ldate = c.getString(c.getColumnIndex(Stat.COL_DATE));
String lMatricule = c.getString(c.getColumnIndex(Stat.COL_TEXTE_OCR));
if (ldate.equals(dateCourante)&& lMatricule.equals(_myRecognizedText)) {
existe=true;
break;
}
c.moveToNext();
}
}
if (existe){
UpdateHeure(_myHeure);
}else{
AddVoyage();
}
}
this ic Stat.java class wich contains some Strings
public class Stat {
public static final String DB_NAME = "leoni.db";
public static final String URL_CHECK = "http://192.168.1.6/check.php";
public static final String GET_URL = "http://192.168.1.6/getChauffeurs.php";
public static final String COL_ID = "_id";
// Gestion des déplacements
public static final String TABLE_NAME = "gestion_des_deplacements";
public static final String COL_TEXTE_OCR = "texte_ocr";
public static final String COL_DATE = "date";
public static final String COL_HEURE_DEPART = "heure_depart";
public static final String COL_HEURE_ARRIVEE = "heure_arrive";
public static final String CREATE_TABLE_DEPLACEMENTS = "CREATE TABLE "
+ Stat.TABLE_NAME + " (" + Stat.COL_ID
+ " INTEGER PRIMARY KEY autoincrement," + Stat.COL_TEXTE_OCR
+ " VARCHAR(40)" + "," + Stat.COL_CHAUFFEUR + " VARCHAR(50)" + ","
+ Stat.COL_DATE + " VARCHAR(50)" + "," + Stat.COL_HEURE_DEPART
+ " VARCHAR(30)" + "," + Stat.COL_HEURE_ARRIVEE + " VARCHAR(30));";
// Gestion des chauffeurs
public static final String COL_MATRICULE = "matricule";
public static final String COL_CHAUFFEUR = "chauffeur";
}
Your stacktrace gives you all the needed information:
com.leoni.bd.Gestion_db.FindDate(java.lang.String)' on a null object reference
What is says is that object of type Gestion_db is null. So you look in your code for this object, and you have only one instance of it _myGestionDB, as noted by #ρяσѕρєя.
The error message identifies the method that is the subject of the problematic invocation as com.leoni.bd.Gestion_db.FindDate(java.lang.String). It follows, therefore, that the type of the expression on which the invocation is performed must be com.leoni.bd.Gestion_db or one of its subtypes.
The only candidate in the code you posted is instance variable _myGestionDB. The code you posted does not give any particular reason to think the value would be non-null. Instance variables of reference type are initialized to null by default if they have no initializer. If you fail to set its value to something else prior to invoking the method you show, then it will still be null when the method invocation attempt occurs.
i need to display multiple database tables to seperate textviews.
So i need to pull all 'appointments' from a table and sort them to display in separate textviews on the mainActivity such as txtMonday, txtTuesday, txtWednesday
The database is designed to store the day along with the other details:
private static final String DATABASE_CREATE =
"create table " + TABLE_AP + "(" + COLUMN_ID + " integer primary key autoincrement, "
+ COLUMN_DAY + " text not null, "
+ COLUMN_TIME + " text not null, "
+ COLUMN_DURATION + " text not null, "
+ COLUMN_DESCRIPTION + " text not null);";
This is how i attempt to call it through MainActivity:
(I also will be calling it with onCreate)
public void onResume (){
APData = new AppointmentDataSource(this);
APData.open();
List<Appointment> appointments = APData.retrieveAllAppointments();
APData.close();
AppointmentDataSource:
public List<Appointment> retrieveAllAppointments () {
List<Appointment> appointments = new ArrayList<Appointment>();
Cursor cursor = database.query(MySQLiteHelper.TABLE_AP, , null, null, null, null, null);
cursor.moveToFirst();
while (!cursor.isAfterLast()) {
Appointment ap = cursorToBk(cursor);
appointments.add(ap);
cursor.moveToNext();
}
cursor.close();
return appointments;
}
Also for the days, i used radio buttons to choose between monday / tue / wed / thur / fri
so i store the day with :
createButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
findRadioGroup = (RadioGroup) findViewById(R.id.radioDay);
int selectedId = findRadioGroup.getCheckedRadioButtonId();
radioButton = (RadioButton) findViewById(selectedId);
String day=radioButton.getText().toString();
String time=txtTime.getText().toString();
String duration=txtDuration.getText().toString();
String description=txtDescription.getText().toString();
APData.insert(day, time, duration, description);
APData.close();
finish();
}
});
and the XML/strings for them:
<string name="RadioMon">Mon</string>
<string name="RadioTue">Tue</string>
<string name="RadioWed">Wed</string>
<string name="RadioThu">Thur</string>
<string name="RadioFri">Fri</string>
In your datamodel you should have a class that manipulates the Appointments, so when you retrieve all your appointments from the database just filter them by appointments[i].Day, or something like that, based on how your Appointment class is created. You don't need to explicitly create different DB selects for each of them.
public void onResume (){
APData = new AppointmentDataSource(this);
APData.open();
List<Appointment> appointments = APData.retrieveAllAppointments();
APData.close();
TextView tvMonday = (TextView)findViewById(R.id.tvMonday);
TextView tvTuesday = (TextView)findViewById(R.id.tvTuesday);
... (all your days textViews).
for(Iterator<Appointment> i = appointments.iterator(); i.hasNext();){
Appointment item = i.next();
if(item.Day.equals("Monday") tvMonday.append(item.ToString());
//same for the rest of your textViews
}
Should be something like this.