Null pointer exception when inserting data into Android SQLite Database - database

I'm just starting an Android Studio project and Ive created a small player database and I have been trying to add player details into the database. However each time the program crashes with a null pointer exception. A quick debgug suggests the problem is with the call to the OnClickListener in the OnCreate method. What changes need to be made to the code? Thanks
public class DatabaseHelper {
// Declare instance of DBHelper class, context and SQLiteDatabase
private DBHelper ourDbHelper;
private final Context ourContext;
private SQLiteDatabase myDb;
// Initialise the database and table names and version
private static final String DATABASE_NAME = "Club";
private static final String PLAYER_TABLE_NAME = "Players";
//Initialise the PLAYER_TABLE_NAME field names
private static final String PLAYER_ID = "player_id";
private static final String PLAYER_SURNAME = "player_surname";
private static final String PLAYER_FORENAME = "player_forename";
private static final String PLAYER_AGE = "player_age";
private static final String PLAYER_DOB = "player_dob";
private static class DBHelper extends SQLiteOpenHelper {
// This constructor takes the context, db name and db version as
parameters
// and applies them to the DBHelper class
public DBHelper(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
}
// This constructor takes context as parameter and assigns it to
variable
#Override
public void onCreate(SQLiteDatabase db) {
//Executes the following queries to create the Player Table
db.execSQL("CREATE TABLE " + PLAYER_TABLE_NAME + " (" + PLAYER_ID
+ " INTEGER PRIMARY KEY AUTOINCREMENT, "
+ PLAYER_FORENAME + "TEXT NOT NULL, " + PLAYER_SURNAME +
"TEXT NOT NULL, " +
PLAYER_AGE + " INTEGER NOT NULL, " + PLAYER_DOB + "DATE
NOT NULL );");
}//OnCreate
#Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int
newVersion) {
// if table is upgraded or already exists
db.execSQL("DROP TABLE IF EXISTS " + PLAYER_TABLE_NAME);
onCreate(db);
}//OnUpgrade
}//DBHelperClass
// Constructor takes a context as a parameter and assigns it to
ourContext
public DatabaseHelper (Context c){
ourContext = c;
}//constructor
// Open writable database and allow to be modified
public DatabaseHelper open() throws SQLException {
ourDbHelper = new DBHelper(ourContext);
myDb = ourDbHelper.getWritableDatabase();
return this;
}//open
//method to close the db to modification
public void close() {
ourDbHelper.close();
}//close
// method to create an entry to the Player table with player attributes as parameters
public long createEntry (String forename, String surname, String age, String dob){
//contentValues will hold the information to be added to the database
ContentValues contentValues = new ContentValues();
//Using put method, insert the parameters into the fields in the table
contentValues.put(PLAYER_FORENAME, forename);
contentValues.put(PLAYER_SURNAME, surname);
contentValues.put(PLAYER_AGE,age);
contentValues.put(PLAYER_DOB, String.valueOf(dob));
//insert the values into the player table
//assign to variable result to check if data added correctly
return myDb.insert(PLAYER_TABLE_NAME,null,contentValues);
}//createEntry
Here is the AddPlayer activity class
public class AddPlayer extends Activity implements View.OnClickListener {
//declare variables
Button confirmAdd;
EditText editSurname, editForename, editAge, editDOB;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.add_player_activity);
//Initialise variables
editForename = (EditText) findViewById(R.id.editPlayerForename);
editSurname = (EditText) findViewById(R.id.editPlayerSurname);
editAge = (EditText) findViewById(R.id.editPlayerAge);
editDOB = (EditText) findViewById(R.id.editPlayerDOB);
confirmAdd = (Button) findViewById(R.id.addPlayerBtn);
//set onclicklisteners
confirmAdd.setOnClickListener(this);
}
#Override
public void onClick(View v) {
String forename = editForename.getText().toString();
String surname = editSurname.getText().toString();
String age = editAge.getText().toString();
String dob = editDOB.getText().toString();
DatabaseHelper myDb = new DatabaseHelper(AddPlayer.this);
myDb.open();
myDb.createEntry(forename, surname, age, dob);
Toast.makeText(AddPlayer.this, "Data Inserted", Toast.LENGTH_LONG).show();
}

Change this
DatabaseHelper myDb = new DatabaseHelper(AddPlayer.this);
myDb.open()
To
DatabaseHelper myDb = new DatabaseHelper(this.getContext());
myDb.open();

Related

How to fix 'database.CursorIndexOutOfBoundsException: Index 0 requested, with a size of 0'?

I am setting up a database with Android SQLite for my weight_activity with a dialog. In that Activity I save the current weight and I want to request the saved value for the current weight when starting the activity to display it.
The Error I get is:
java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example.thisfit/com.example.thisfit.Weight_Activity}: android.database.CursorIndexOutOfBoundsException: Index 0 requested, with a size of 0
Caused by: android.database.CursorIndexOutOfBoundsException: Index 0 requested, with a size of 0
at android.database.AbstractCursor.checkPosition(AbstractCursor.java:460)
This is the code that requests the current weight in my activity class
public void getCurrentWeightAsFloat() {
textView_currentWeight.setText(String.valueOf(weight_dbHandler.getCurrentWeight()));
} //public void getCurrentWeightAsFloat()
This is the whole database code. I post this because I don't know, if the problem could be in another section of the code and not just the method getCurrentWeight():
public class Weight_Database extends SQLiteOpenHelper {
//region Attributes
private static final String TAG = "weight_database";
private static final int DATABASE_VERSION = 1;
private static final String DATABASE_NAME = "weight_database.db";
private static final String TABLE_NAME = "weight_table";
private static final String COL1 = "ID";
private static final String COL2 = "Weight";
private static final String COL3 = "Date";
//endregion
//region Constructors
public Weight_Database(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
// SQLiteDatabase db = this.getWritableDatabase();
}
//endregion
//region Methods
#Override
public void onCreate(SQLiteDatabase db) {
String createTable = "CREATE TABLE " + TABLE_NAME
+ " (ID INTEGER PRIMARY KEY AUTOINCREMENT, "
+ COL2 + " FLOAT, "
+ COL3 + " DATE )";
db.execSQL(createTable);
}
#Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
db.execSQL("DROP TABLE IF EXISTS " + TABLE_NAME);
onCreate(db);
}
public boolean addNewCurrentWeightAsFloat(float newCurrentWeightAsFloat){
SQLiteDatabase db = this.getWritableDatabase();
ContentValues contentValues = new ContentValues();
contentValues.put(COL2, newCurrentWeightAsFloat);
Log.d(TAG, "addWeight: Adding " + newCurrentWeightAsFloat + " to " + TABLE_NAME);
long result = db.insert(TABLE_NAME, null, contentValues);
//if date as inserted incorrectly it will return -1
if (result == -1){
return false;
} else {
return true;
}
} //public boolean addNewCurrentWeightAsFloat(String newCurrentWeightAsFloat)
public float getCurrentWeight(){
SQLiteDatabase db = this.getWritableDatabase();
String query = "SELECT Weight FROM " + TABLE_NAME + " ORDER BY ID DESC LIMIT 1";
Cursor data = db.rawQuery(query, null);
data.moveToFirst();
float currentWeightAsFloat = data.getFloat(data.getColumnIndex("content"));
return currentWeightAsFloat;
} //public float getCurrentWeight()
//Returns the whole table as a raw query
public Cursor getData(){
SQLiteDatabase db = this.getWritableDatabase();
String query = "SELECT * FROM " + TABLE_NAME;
Cursor data = db.rawQuery(query, null);
return data;
} //public Cursor getData()
//endregion
} //class Weight_Database
I expect to get the latest weight entered by selecting the ID DESCending with a Limit of 1.
I want to get this float of my current weight and display it in a textView afterwards.
Have a nice day and thanks in advance :)
Your table has no data.
You should check the return values of data.moveToFirst() and only try to call getFloat() on the cursor in case it returned true.

android.database.sqlite.SQLiteException: no such column: user_id (code 1 SQLITE_ERROR):

being an Android Studio beginner i tend to get lots and lots of tiny errors i cannot find out, please let me know what I am doing wrong because I've tried all the other answers somehow and it doesn't get better :)
public class DatabaseHelper extends SQLiteOpenHelper{
private static final int DATABASE_VERSION = 1;
private static final String DATABASE_NAME = "UserManager.db";
private static final String TABLE_USER = "user";
private static final String COLUMN_USER_ID= "user_id";
private static final String COLUMN_USER_NAME= "user_name";
private static final String COLUMN_USER_EMAIL= "user_email";
private static final String COLUMN_USER_PASSWORD= "user_password";
private String CREATE_USER_TABLE = "CREATE TABLE " + TABLE_USER + "(" +
COLUMN_USER_ID + " INTEGER PRIMARY KEY AUTOINCREMENT, "
+ COLUMN_USER_NAME + " TEXT," + COLUMN_USER_EMAIL + " TEXT," +
COLUMN_USER_PASSWORD + " TEXT" + ")";
private String DROP_USER_TABLE = " DROP TABLE IF EXISTS " + TABLE_USER;
public DatabaseHelper(Context context){
super(context, DATABASE_NAME,null, DATABASE_VERSION);
}
#Override
public void onCreate(SQLiteDatabase db){
db.execSQL(CREATE_USER_TABLE);
}
#Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion){
db.execSQL(DROP_USER_TABLE);
onCreate(db);
}
public void addUser(User user){
SQLiteDatabase db= this.getWritableDatabase();
ContentValues values = new ContentValues();
values.put(COLUMN_USER_NAME, user.getName());
values.put(COLUMN_USER_EMAIL, user.getEmail());
values.put(COLUMN_USER_PASSWORD, user.getPassword());
db.insert(TABLE_USER,null, values);
db.close();
}
public boolean checkUser(String password, String email){
String[] columns = {
COLUMN_USER_ID
};
SQLiteDatabase db= this.getWritableDatabase();
String selection = COLUMN_USER_EMAIL + " = ? " + "AND "+ COLUMN_USER_PASSWORD+" =? ";
String[] selectionArgs = { email,password };
Cursor cursor = db.query(TABLE_USER,
columns,
selection,
selectionArgs,
null,
null,
null);
int cursorCount = cursor.getCount();
cursor.close();
db.close();
if(cursorCount > 0){
return true;
}
return false;
}
}
I know the logcat let me know this:
07-11 22:08:29.072 9071-9071/com.example.lavinia.sqllogin E/AndroidRuntime:
FATAL EXCEPTION: main
Process: com.example.lavinia.sqllogin, PID: 9071
android.database.sqlite.SQLiteException: no such column: user_id (code 1
SQLITE_ERROR): , while compiling: SELECT user_id FROM user WHERE user_email =
?AND user_password =?
And I can't find the wrong usage of user_id, I think I used it fine and the app will stop working after I Login myself. (the app has login and registration activities- and the registration works ok, but pressing the Login button in the Login.activity will make the app crash)
Thank you very much for you support :) If needed, I will provide with further code.
This issue is probably due to i tend to get lots and lots of tiny errors in conjunction with a common misconception regarding the onCreate method.
The onCreate method automatically runs only once when the database is and has actually been created. It does not run every time the App is run.
As such any changes (corrections included) to the structure (tables and columns) will not be applied if they are coded/actioned within the onCreate method.
When developing the easiest fix is to do one of the following 3:-
delete the App's data (deletes the database so onCreate will be called).
uninstall the App (deletes the database so onCreate will be called).
if the onUpgrade method will drop the table(s) and then call onCreate , to increase the database version number as passed as the 4th parameter to the SQLIteOpenHelper sub-class (aka the DatabaseHelper class).
After doing one of the above, rerun the App.
NOTE any existing data will be lost.
If data has to be retained then a fix is more complicated but would be based upon using ALTER TABLE statements.

Switching from local database to SQL server

So our current code loaded a csv file into a local jdbcTemplate in which then I do some querying. The issue was always performance, and we finally got access to a SQL server that could load the data. Naturally the company gets the guy with basically no database skills to set this up :P
#Autowired
DataSource dataSource;
#RequestMapping("/queryService")
public void queryService(#RequestParam("id")String id)
{
log.info("Creating tables");
jdbcTemplate.execute("DROP TABLE accounts IF EXISTS");
jdbcTemplate.execute("CREATE TABLE accounts(id VARCHAR(255), name VARCHAR(255), Organization__c VARCHAR(255)";
insertBatch(accounts,dataSource);
ArrayList<Account2> filteredaccs = filterAccount(jdbcTemplate);
.
public void insertBatch(ArrayList<Account2> accs, DataSource dataSource) {
List<Map<String, Object>> batchValues = new ArrayList<>(accs.size());
for (Account2 a : accs) {
Map<String, Object> map = new HashMap<>();
map.put("id", a.getId());
map.put("name", a.getName());
map.put("Organization__c", a.getOrganization__c());
batchValues.add(map);
}
SimpleJdbcInsert simpleJdbcInsert = new SimpleJdbcInsert(dataSource).withTableName("accounts");
int[] ints = simpleJdbcInsert.executeBatch(batchValues.toArray(new Map[accs.size()]));
}
.
public ArrayList<Account2> filterAccount(JdbcTemplate jdbcTemplate)
{
String sql= "query string";
ArrayList<Account2> searchresults = (ArrayList<Account2>) jdbcTemplate.query(sql,
new RowMapperResultSetExtractor<Account2>(new AccountRowMapper(), 130000));
return searchresults;
}
.
public class AccountRowMapper implements RowMapper<Account2> {
public Account2 mapRow(ResultSet rs, int rowNum) throws SQLException {
Account2 a = new Account2();
a.setId(rs.getString("id"));
a.setName(rs.getString("name"));
a.setOrganization__c(rs.getString("Organization__c"));
return a;
}
}
The question here is what is the quickest way for me to 'switch' over to using a SQL server to pull the data down, with the same table and rows, without changing too much of my current code?

stored procedure 'auto_pk_for_table' not found

I don't know why I received the error :
org.apache.cayenne.CayenneRuntimeException: [v.4.0.M5 Feb 24 2017 07:47:55] Commit Exception
[...]
Caused by: java.sql.SQLException: Procédure stockée 'auto_pk_for_table' introuvable.
[...]
I'm using Cayenne :
<dependency>
<groupId>org.apache.cayenne</groupId>
<artifactId>cayenne-server</artifactId>
<version>4.0.M5</version>
</dependency>
and JDTS for sql server :
<dependency>
<groupId>net.sourceforge.jtds</groupId>
<artifactId>jtds</artifactId>
<version>1.3.1</version>
</dependency>
The connexion is ok :
avr. 10, 2017 2:36:30 PM org.apache.cayenne.datasource.DriverDataSource getConnection
INFOS: +++ Connecting: SUCCESS.
I'm trying to create a new user (I'm starting by bascis!) so my code is :
(I cut a little bit, it's too long:!)
public abstract class _UserInfo extends CayenneDataObject {
public static final String ADDRESS_PROPERTY = "address";
public void setAddress(String address) {
writeProperty(ADDRESS_PROPERTY, address);
}
public String getAddress() {
return (String)readProperty(ADDRESS_PROPERTY);
}
}
public class UserInfo extends _UserInfo implements Serializable {
private static final long serialVersionUID = 1L;
public String address;
public String getAdress() {
return address;
}
public void setAddress(String address) {
super.setAddress(address);
}
//I have the hashcode and equals too
}
Then, I used vaadin to create my form :
public class UserAddView extends CustomComponent implements View {
private static final long serialVersionUID = 1L;
private TextField address;
private Button save;
public static final String USERVIEW = "user";
public boolean checkValidation() {
if (!checkTextFieldValid(address))
return false;
return true;
}
public boolean checkTextFieldValid(TextField element) {
if (element == null || element.isEmpty()) {
Notification.show(
"You should register a " + element.getDescription(),
Type.WARNING_MESSAGE);
return false;
}
return true;
}
public UserAddView() {
VerticalLayout mainLayout = new VerticalLayout();
mainLayout.setSizeFull();
setCompositionRoot(mainLayout);
final VerticalLayout vlayout = new VerticalLayout();
address = new TextField("Address:");
address.setDescription("Address");
vlayout.addComponent(address);
save = new Button("Save");
vlayout.addComponent(save);
mainLayout.addComponent(new HeaderMenu());
mainLayout.addComponent(vlayout);
addListeners();
}
private void addListeners() {
save.addClickListener(new ClickListener() {
private static final long serialVersionUID = 1L;
#Override
public void buttonClick(ClickEvent event) {
if (checkValidation() == true) {
ServerRuntime cayenneRuntime = ServerRuntime.builder()
.addConfig("cayenne-myapplication.xml").build();
ObjectContext context = cayenneRuntime.newContext();
UserInfo user = context.newObject(UserInfo.class);
user.setAddress(address.getValue());
user.getObjectContext().commitChanges();
Notification.show(
"Has been saved, We will send you your password by email. Your user login is: "
+ email.getValue(), Type.TRAY_NOTIFICATION);
getUI().getNavigator().navigateTo(HomepageView.MAINVIEW);
}
}
});
}
#Override
public void enter(ViewChangeEvent event) {
// TODO Auto-generated method stub
}
}
EDIT, add information : In my user object, I have a userid (primary key), in cayenne I wrote it as primary key too and in smallint. This error seems to be link... https://cayenne.apache.org/docs/3.1/api/org/apache/cayenne/dba/sybase/SybasePkGenerator.html
The error happens when you insert a new object. For each new object Cayenne needs to generate a value of the primary key. There are various strategies to do this. The default strategy depends on the DB that you are using. For SQLServer (and for Sybase, as you've discovered :)) that strategy is to use a special stored procedure.
To create this stored procedure (and other supporting DB objects), go to CayenneModeler, open your project, and select "Tools > Generate Database Schema". In "SQL Options" tab, uncheck all checkboxes except for "Create Primary Key Support". The SQL you will see in the window below the checkboxes is what you need to run on SQL server. Either do it from Cayenne modeler or copy/paste to your favorite DB management tool.
There's also an alternative that does not require a stored procedure - using DB auto-increment feature. For this you will need to go to each DbEntity in the Modeler and under the "Entity" tab select "Database-Generated" in the "Pk Generation Strategy" dropdown. This of course implies that your PK column is indeed an auto-increment in the DB (meaning you may need to adjust your DB schema accordingly).

SQLite Database is not working after standalone build in Unity3D

I am trying to make a Standalone Application using SQLite in Unity3D,
I am getting a strange problem.
I created a database using sqliteadmin, and created a Table named Admin, having field: id, email, password.
I am able to Login using email and password but in Unity Edit Mode.
Its working fine but when i build it and then run it, its not working, I have no idea why?
Reference
Here is my code:
using UnityEngine;
using System.Collections;
using Mono.Data.Sqlite;
using System.Data;
using System;
using UnityEngine.UI;
public class DatabaseConnection : MonoBehaviour {
public Text em;
public Text pas;
public static int id;
public static string email ="";
public static string password="";
public static string wrong="Wrong Email/Password !!!";
public Text Wrong;
public GameObject loading;
private ButtonsController bc;
public GameObject loginPanel;
void Start () {
string conn = "URI=file:" + Application.dataPath + "/Database/TMDB.s3db";
IDbConnection dbconn;
dbconn = (IDbConnection)new SqliteConnection (conn);
dbconn.Open ();
IDbCommand dbcmd = dbconn.CreateCommand ();
string sqlQuery = "SELECT id, email, password " + "FROM Admin";
dbcmd.CommandText = sqlQuery;
IDataReader reader = dbcmd.ExecuteReader ();
while (reader.Read()) {
id = reader.GetInt32 (0);
email = reader.GetString(1);
password = reader.GetString(2);
}
reader.Close ();
reader = null;
dbcmd.Dispose ();
dbcmd = null;
dbconn.Close ();
dbconn = null;
loading.SetActive (false);
}
public void login()
{
if ((em.text == email) && (pas.text == password)) {
Debug.Log ("Success");
loading.SetActive (true);
loginPanel.SetActive(false);
Application.LoadLevel(1);
} else {
Debug.Log ("Error");
Wrong.text = wrong.ToString ();
}
}
}
Application.datapath is readonly.
What you need is Application.persistentDataPath
Checkout this link
http://answers.unity3d.com/questions/209108/when-to-use-persistentdatapath-versus-datapath.html
Create StreamingAssets folder into your Assets, and use this connection string:
string conn = "URI=file:" +
System.IO.Path.Combine(Application.streamingAssetsPath, "Database/TMDB.s3db");
Using streaming asset is necessary, it places files into the normal filesystem on the target machine to make them accessible via a pathname.
More info:
https://docs.unity3d.com/Manual/StreamingAssets.html
dude ,,, just check the files bro,,, after building the database is empty so go and replace the database file with the one u been working on with the same database name .

Resources