【问题标题】:Code passing a "null" to DB where there should be a String value将“null”传递给应该有字符串值的数据库的代码
【发布时间】:2016-03-31 16:43:59
【问题描述】:

我正在编写一个从 SQLite 数据库中提取信息并将其传递给列表的应用程序。代码尚未最终确定,但我无法测试超过某个点。我收到的错误消息是我的表名在我的 SQL 查询中是“null”,但我不明白为什么会这样。我在应用程序中创建了一个 textview,它显示了我传入的字符串中包含的数据。那个 TextView 显示了正确的信息。因此,如果字符串正在传递给 TextView,为什么不能将它传递给基于字符串的 SQLQuery?

具体来说,来自 DBHelper 的 getBeerDrinkLabels() 显示来自 BarTableName 的“null”,它来自 Bar.testingBarSet,来自 MainActivity.upperCaseName。 Bar.testingBarSet 在加载到 setBarTester TextView 的 String 中显示正确的值,那么为什么不在 DB Query 中呢?

DBHelper 类(SQL 查询位于公共 List getBeerDrinkLabels() 方法中)

import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.List;

import android.content.Context;
import android.database.Cursor;
import android.database.SQLException;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteException;
import android.database.sqlite.SQLiteOpenHelper;

public class DBHelper extends SQLiteOpenHelper {

    private static String DB_PATH = "/data/data/com.example.sixth/databases/";
    private static String DB_NAME = "BarSample.db"; 
    private final Context myContext;    
    public static String tableName = "BARS";
    public static String barTableName = Bar.testingBarSet;//Pass in the specific bar from the spinner choice
    public static String drinkType = Bar.setDrinkType;//Use this to pass in selected drink type to SQL query    
    //public static final String KEY_ROWID = "_id";
    //public static final String BARNAME = "Bar Name";
    public static final String BARCITY = "Bar City";
    private SQLiteDatabase myDataBase;


    public DBHelper(Context context) {

        super(context, DB_NAME, null, 1);
        this.myContext = context;
    }

    /**
     * Creates a empty database on the system and rewrites it with your own
     * database.
     */
    public void createDataBase() throws IOException {

        boolean dbExist = checkDataBase();

        if (dbExist) {
            // do nothing - database already exist
        } else {

            // By calling this method and empty database will be created into
            // the default system path
            // of your application so we are gonna be able to overwrite that
            // database with our database.
            this.getReadableDatabase();

            try {
                this.close();
                copyDataBase();

            } catch (IOException e) {

                throw new Error("Error copying database");
            }
        }
    }

    /**
     * Check if the database already exist to avoid re-copying the file each
     * time you open the application.
     * 
     * @return true if it exists, false if it doesn't
     */
    private boolean checkDataBase() {

        SQLiteDatabase checkDB = null;

        try {
            String myPath = DB_PATH + DB_NAME;
            checkDB = SQLiteDatabase.openDatabase(myPath, null, SQLiteDatabase.OPEN_READONLY);

        } catch (SQLiteException e) {
            // database does't exist yet.
        }
        if (checkDB != null) {
            checkDB.close();
        }
        return checkDB != null ? true : false;
    }

    /**
     * Copies your database from your local assets-folder to the just created
     * empty database in the system folder, from where it can be accessed and
     * handled. This is done by transfering bytestream.
     */
    private void copyDataBase() throws IOException {

        // Open your local db as the input stream
        InputStream myInput = myContext.getAssets().open(DB_NAME);

        // Path to the just created empty db
        String outFileName = DB_PATH + DB_NAME;

        // Open the empty db as the output stream
        OutputStream myOutput = new FileOutputStream(outFileName);

        // transfer bytes from the inputfile to the outputfile
        byte[] buffer = new byte[1024];
        int length;
        while ((length = myInput.read(buffer)) > 0) {
            myOutput.write(buffer, 0, length);
        }

        // Close the streams
        myOutput.flush();
        myOutput.close();
        myInput.close();

    }

    public void openDataBase() throws SQLException {

        // Open the database
        String myPath = DB_PATH + DB_NAME;
        myDataBase = SQLiteDatabase.openDatabase(myPath, null, SQLiteDatabase.OPEN_READONLY);

    }

    @Override
    public synchronized void close() {

        if (myDataBase != null)
            myDataBase.close();

        super.close();

    }

    @Override
    public void onCreate(SQLiteDatabase db) {

    }

    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {

    }

    public List<String> getAllLabels(){
        List<String> labels = new ArrayList<String>();

        // Select All Query
        String selectQuery = "SELECT  * FROM " + tableName;

        SQLiteDatabase db = this.getReadableDatabase();
        Cursor cursor = db.rawQuery(selectQuery, null);

        // looping through all rows and adding to list
        if (cursor.moveToFirst()) {
            do {
                labels.add(cursor.getString(1) + " " + cursor.getString(2)+ ", " + cursor.getString(3));
            } while (cursor.moveToNext());
        }

        // closing connection
        cursor.close();
        db.close();

        // returning labels
        return labels;

    } // will returns all labels stored in database

    public List<String> getBeerDrinkLabels(){
        List<String> allBeerDrinkLabels = new ArrayList<String>();

        // Select All Query
        String sqlquery="SELECT * FROM "+barTableName + " WHERE DRINKTYPE='Beer';";
        String selectQuery = sqlquery;

        SQLiteDatabase db = this.getReadableDatabase();
        Cursor cursor = db.rawQuery(selectQuery, null);

        // looping through all rows and adding to list
        if (cursor.moveToFirst()) {
            do {
                allBeerDrinkLabels.add(cursor.getString(1) + ", " + cursor.getString(2));
            } while (cursor.moveToNext());
        }

        // closing connection
        cursor.close();
        db.close();

        // returning labels
        return allBeerDrinkLabels;

    } // will returns all labels stored in database
}

Main Activity.java(创建最终进入 Query 的字符串)

package com.example.sixth;
import java.io.IOException;
import java.util.List;
import android.app.Activity;
import android.content.Intent;
import android.database.SQLException;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemSelectedListener;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.Spinner;


public class MainActivity extends Activity implements
OnItemSelectedListener {
    DBHelper myDB;
    Button selectBar;   
    Spinner spinner;
    static String pullBar,setBar,name, cityState, upperCaseName;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Button selectBar = (Button)findViewById(R.id.btnSelectBar);
        myDB = new DBHelper(this);
         // Spinner element
        spinner = (Spinner) findViewById(R.id.spinner);
     // Spinner click listener
        spinner.setOnItemSelectedListener(this);

        try {
            myDB.createDataBase();
        } catch (IOException ioe) {
            throw new Error("Unable to create database");
        }
        try {
            myDB.openDataBase();
        } catch (SQLException sqle) {
            throw sqle;
        }


        // Loading spinner data from database
        loadSpinnerData();

        selectBar.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View v) {
                pullBar = String.valueOf(spinner.getSelectedItem());
                String[] parts = pullBar.split(" "); //returns an array with the 2 parts
                name = parts[0];

                String nlast = parts[parts.length-2];
                String last = parts[parts.length-1];

                cityState =  nlast+ " " + last;
                upperCaseName=name.toUpperCase();
                setBar = name.toLowerCase();
                Intent i = (new Intent(MainActivity.this, Bar.class));
                startActivity(i);           
            }

        }); 
    }


     private void loadSpinnerData() {
            // database handler
            DBHelper db = new DBHelper(getApplicationContext());

            // Spinner Drop down elements
            List<String> lables = db.getAllLabels();

            // Creating adapter for spinner
            ArrayAdapter<String> dataAdapter = new ArrayAdapter<String>(this,
                    android.R.layout.simple_spinner_item, lables);

            // Drop down layout style - list view with radio button
            dataAdapter
                    .setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);

            // attaching data adapter to spinner
            spinner.setAdapter(dataAdapter);
        }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.main, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        // Handle action bar item clicks here. The action bar will
        // automatically handle clicks on the Home/Up button, so long
        // as you specify a parent activity in AndroidManifest.xml.
        int id = item.getItemId();
        if (id == R.id.action_settings) {
            return true;
        }
        return super.onOptionsItemSelected(item);
    }


    @Override
    public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
        // TODO Auto-generated method stub

    }


    @Override
    public void onNothingSelected(AdapterView<?> parent) {
        // TODO Auto-generated method stub

    }

}

Bar.java(进入 Query 的字符串最终确定的地方)

public class Bar extends Activity{
    String setBarTest = MainActivity.setBar;
    static String testingBarSet = MainActivity.upperCaseName;
    String barNameHolder, picHolder, barContactHolder, barPhoneHolder; 
    int imageInt, textInt1,textInt2, textInt3, textInt4;
    TextView setBarName, setBarContact,setBarPhone, setBarHours;
    static TextView setBarTester;
    ImageView barPic;
    Button viewAll, beer, wine, mixedDrinks, other, specials, getTaxi;
    static String setDrinkType;

    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_bar);

        Button viewAll = (Button)findViewById(R.id.btnviewAll); 
        Button specials = (Button)findViewById(R.id.btnSpecials);   
        Button getTaxi = (Button)findViewById(R.id.btnTaxi);

        barPic = (ImageView) findViewById(R.id.barPic);
        String picHolder = "drawable/"+setBarTest;      
        imageInt = getResources().getIdentifier(picHolder, null, getPackageName());
        barPic.setImageResource(imageInt);

        setBarName = (TextView)findViewById(R.id.barName);
        String barNameHolder = "@string/"+setBarTest;
        textInt1 = getResources().getIdentifier(barNameHolder, null, getPackageName());
        setBarName.setText(textInt1);

        setBarContact = (TextView)findViewById(R.id.barContact);
        String barContactHolder = "@string/"+setBarTest+"Contact";
        textInt2 = getResources().getIdentifier(barContactHolder, null, getPackageName());
        setBarContact.setText(textInt2);

        setBarPhone = (TextView)findViewById(R.id.barPhone);
        String barPhoneHolder = "@string/"+setBarTest+"Phone";
        textInt3 = getResources().getIdentifier(barPhoneHolder, null, getPackageName());
        setBarPhone.setText(textInt3);

        setBarHours = (TextView)findViewById(R.id.barHours);
        String barHoursHolder = "@string/"+setBarTest+"Hours";
        textInt4 = getResources().getIdentifier(barHoursHolder, null, getPackageName());
        setBarHours.setText(textInt4);

        setBarTester = (TextView)findViewById(R.id.setBarTester);
        String barTesterHolder = testingBarSet ;
        //int textInt5 = getResources().getIdentifier(barTesterHolder, null, getPackageName());
        setBarTester.setText(barTesterHolder);

        viewAll.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View v) {
                Intent i = (new Intent(Bar.this, Drinks.class));
                startActivity(i);           
            }

        });

        specials.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View v) {
                Intent i = (new Intent(Bar.this, NoResult.class));
                startActivity(i);           
            }

        });

        getTaxi.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View v) {
                Intent i = (new Intent(Bar.this, Taxi.class));
                startActivity(i);           
            }

        });


    }
}

Drinks.java(在 DB 调用中给出 Null 值)

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import android.app.Activity;
import android.os.Bundle;
import android.widget.ArrayAdapter;
import android.widget.ExpandableListView;
import android.widget.ExpandableListView.OnChildClickListener;
import android.widget.ExpandableListView.OnGroupClickListener;
import android.widget.ExpandableListView.OnGroupCollapseListener;
import android.widget.ExpandableListView.OnGroupExpandListener;
import android.widget.ListView;
import android.widget.Toast;

public class Drinks extends Activity {
    // TextView drinkHolder;
    public static String drinkType = DBHelper.drinkType;
    String drinkTestHolder = "";
    ExpandableListAdapter listAdapter;
    ExpandableListView expListView;
    List<String> listDataHeader;
    HashMap<String, List<String>> listDataChild;


    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_drinks);
        Bundle bundle = getIntent().getExtras();
        if (bundle != null) {
            drinkType = bundle.getString("sample_name");
        }
        // get the listview
        expListView = (ExpandableListView) findViewById(R.id.lvExp);

        // preparing list data
        prepareListData();

        listAdapter = new ExpandableListAdapter(this, listDataHeader, listDataChild);

        // setting list adapter
        expListView.setAdapter(listAdapter);

    }

    private void prepareListData() {
        listDataHeader = new ArrayList<String>();
        listDataChild = new HashMap<String, List<String>>();


        // Adding child data

         listDataHeader.add("Beer"); 
         listDataHeader.add("Mixed Drinks");
         listDataHeader.add("Other Drinks"); 
         listDataHeader.add("Shots");
         listDataHeader.add("Wine");

         //Get Beer entries
         DBHelper db = new DBHelper(getApplicationContext());
         List<String> beerLables = db.getBeerDrinkLabels();


        // Adding child data
        List<String> beer = new ArrayList<String>();

        //beer.add("The Shawshank Redemption");
        for (int i = 0; i < beerLables.size(); i++) {
            beer.add(beerLables.get(i));
        }

        /*
           beer.add("The Godfather");
         * beer.add("The Godfather: Part II"); beer.add("Pulp Fiction");
         * beer.add("The Good, the Bad and the Ugly"); beer.add(
         * "The Dark Knight"); beer.add("12 Angry Men");
         */

        List<String> wine = new ArrayList<String>();
        /*
         * wine.add("The Conjuring"); wine.add("Despicable Me 2");
         * wine.add("Turbo"); wine.add("Grown Ups 2"); wine.add("Red 2");
         * wine.add("The Wolverine");
         */

        List<String> shots = new ArrayList<String>();
        /*
         * shots.add("2 Guns"); shots.add("The Smurfs 2"); shots.add(
         * "The Spectacular Now"); shots.add("The Canyons"); shots.add(
         * "Europa Report");
         */

        List<String> mixedDrinks = new ArrayList<String>();
        /*
         * mixedDrinks.add("2 Guns"); mixedDrinks.add("The Smurfs 2");
         * mixedDrinks.add("The Spectacular Now"); mixedDrinks.add("The Canyons"
         * ); mixedDrinks.add("Europa Report");
         */

        List<String> otherDrinks = new ArrayList<String>();
        /*
         * otherDrinks.add("2 Guns"); otherDrinks.add("The Smurfs 2");
         * otherDrinks.add("The Spectacular Now"); otherDrinks.add("The Canyons"
         * ); otherDrinks.add("Europa Report");
         */

        listDataChild.put(listDataHeader.get(0), beer); // Header, Child data
        listDataChild.put(listDataHeader.get(1), wine);
        listDataChild.put(listDataHeader.get(2), shots);
        listDataChild.put(listDataHeader.get(3), mixedDrinks);
        listDataChild.put(listDataHeader.get(4), otherDrinks);
    }
}

我最初让 DBHelper 从 MainActivity 中拉出字符串,但无论我把它放在哪里都得到 Null 值。

LogCat

 FATAL EXCEPTION: main
 java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example.sixth/com.example.sixth.Drinks}: android.database.sqlite.SQLiteException: near "null": syntax error (code 1): , while compiling: SELECT * FROM null WHERE DRINKTYPE='Beer';
    at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2211)
    at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2261)
    at android.app.ActivityThread.access$600(ActivityThread.java:141)
    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1256)
    at android.os.Handler.dispatchMessage(Handler.java:99)
    at android.os.Looper.loop(Looper.java:137)
    at android.app.ActivityThread.main(ActivityThread.java:5103)
    at java.lang.reflect.Method.invokeNative(Native Method)
    at java.lang.reflect.Method.invoke(Method.java:525)
    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:737)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:553)
    at dalvik.system.NativeStart.main(Native Method)
    Caused by: android.database.sqlite.SQLiteException: near "null": syntax error (code 1): , while compiling: SELECT * FROM null WHERE DRINKTYPE='Beer';
    at android.database.sqlite.SQLiteConnection.nativePrepareStatement(Native Method)
    at android.database.sqlite.SQLiteConnection.acquirePreparedStatement(SQLiteConnection.java:889)
    at android.database.sqlite.SQLiteConnection.prepare(SQLiteConnection.java:500)
    at android.database.sqlite.SQLiteSession.prepare(SQLiteSession.java:588)
    at android.database.sqlite.SQLiteProgram.<init>(SQLiteProgram.java:58)
    at android.database.sqlite.SQLiteQuery.<init>(SQLiteQuery.java:37)
    at android.database.sqlite.SQLiteDirectCursorDriver.query(SQLiteDirectCursorDriver.java:44)
    at android.database.sqlite.SQLiteDatabase.rawQueryWithFactory(SQLiteDatabase.java:1314)
    at android.database.sqlite.SQLiteDatabase.rawQuery(SQLiteDatabase.java:1253)
    at com.example.sixth.DBHelper.getBeerDrinkLabels(DBHelper.java:180)
    at com.example.sixth.Drinks.prepareListData(Drinks.java:62)
    at com.example.sixth.Drinks.onCreate(Drinks.java:38)
    at android.app.Activity.performCreate(Activity.java:5133)
    at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1087)
    at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2175) 

【问题讨论】:

  • 因为您的barTableName 为空。你应该检查一下。
  • 您正在到处传递静态变量。你应该停止这样做。在您单击按钮之前,MainActivity.upperCaseName 为空,因此 barTableName 将为空。
  • 我知道我有一些不需要的静态参数。我只是还没有机会清理它们。至于另一件事,它仅在 SQL Query 中显示为 null,并且是在按下 MainActivity 上的按钮之后,所以那里有一个值。那么它不应该为空

标签: android database sqlite null


【解决方案1】:

我认为你需要改变:

String sqlquery="SELECT * FROM "+barTableName + " WHERE DRINKTYPE='Beer';";

到:

String sqlquery="SELECT * FROM "+tableName + " WHERE DRINKTYPE='Beer';";

在您的DB Helper 班级中

【讨论】:

  • 不,这会传入 BARS 这个词,我不想这样做。该 tableName 变量(在 getAllLabels() 中确实有效)不是同一个变量。我需要 barTableName 才能工作,因为它与 tableName 的值不同
  • @Inessaria "public static String barTableName = Bar.testingBarSet" 你初始化 Bar.testingBarSet 了吗?
  • 静态字符串 testingBarSet = MainActivity.upperCaseName;然后在MainActivity中,String[] parts = pullBar.split(" ");名称=零件[0]; upperCaseName=name.toUpperCase();
  • 我知道 Bar.testingBarSet = 正确的变量,因为它在我传递 testingBarSet 的 TextView 中显示了正确的变量。但它没有传入查询,错误显示“null”而不是正确的字符串
  • Bar 类在 MainActivity 类之后。因此,他们从 MainActivity 中选择一个项目。选择的项目会更改 Bar 页面上的内容。然后从 Bar 页面转到 Drink 页面,我正在调用由于 Null 值而导致应用程序崩溃的数据库。
【解决方案2】:

显然问题在于我在 DBHelper.java 类中将变量声明为静态。当 DBHelper 第一次启动时(在 Bar.java 启动之前),它要求变量 Bar.barTableName。由于该变量尚不存在,因此将其设为空。所以我做了一些改变,现在它工作得很好。

在 DBHelper 中,我将变量声明更改为:

public String barTableName = Bar.barTableName;

在Bar.java中,我改了

static String testingBarSet = MainActivity.upperCaseName; 

static String barTableName; 

然后在我添加的 OnCreate 方法中

barTableName = setBarTest.toUpperCase(); 

setBarTest 变量来自

Bundle bundle = getIntent().getExtras();
        if (bundle != null) {
            setBarTest = bundle.getString("bar");
            // barName =barNameHolder;
        }

在 Bar.java onCreate 和 MainActivity.java 中我添加了

Intent i = (new Intent(MainActivity.this, Bar.class));
                 i.putExtra("bar",setBar);
                startActivity(i);   

在selectBar.onClickListener中

现在一切正常,我很高兴。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-07-28
    • 2011-05-12
    • 2019-10-22
    • 2011-06-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多