0

SQLite 데이터베이스에서 레스토랑을 검색하는 Android 앱을 만들고 있습니다. 나는 현재 데이터베이스에서 커서를로드 한 다음 해당 커서를 가져 와서 SimpleCursorAdapter를 사용하여 목록보기를 채우는 사용자 정의 로더 (온라인에서 찾은 사용자 정의 로더)를 사용합니다. 모든 데이터가 표시되지만 레스토랑의 이름 만 표시되기를 원합니다 (목록 항목을 클릭 할 때 모든 데이터를 가져 와서 데이터를 표시하는 새 활동으로 보내려고하기 때문에). 심지어 내가 알고 생각, 내 SQLiteCursorLoader 클래스에원시 쿼리 실행시 Android SQLite 열을 찾을 수 없음 오류

"SELECT * FROM Restaurant WHERE name = " + name + " AND rType = " + restaurantType; 

나는 열이 RTYPE가 존재하지 않는 없다는 오류를 얻을 : 나는 검색 매개 변수로 레스토랑 이름과 레스토랑 유형을 지정하는 경우, 나는 원시 쿼리를 실행 열이 Restuarant 테이블에 있습니다. 내 쿼리에 WHERE 절이 두 개 있지만 WHERE 절이 하나있을 때이 오류가 발생하는 것 같습니다. 어떤 도움 이라든지 대단히 감사 할 것입니다!

RestuarantSearchResultsActivity :

package com.studentapplication; 
import android.app.Activity; 
import android.app.ListActivity; 
import android.app.LoaderManager; 
import android.content.Loader; 
import android.database.Cursor; 
import android.os.Bundle; 
import android.util.Log; 
import android.view.View; 
import android.widget.ListView; 
import android.widget.SimpleCursorAdapter; 

public class RestaurantSearchResultsActivity extends ListActivity implements 
LoaderManager.LoaderCallbacks<Cursor>{ 

DatabaseHelper databaseHelper; 
SimpleCursorAdapter mAdapter; 
Bundle searchParameters; 

@Override 
public void onCreate(Bundle savedInstanceState) 
{ 
    Log.w("CoolBeans", "Results Activity Created"); 
    super.onCreate(savedInstanceState); 

    databaseHelper = new DatabaseHelper(getApplicationContext()); 
    //setContentView(R.layout.restaurant_search_results); 

    Bundle searchParameters = getIntent().getExtras(); 
    String n = searchParameters.getString("name"); 
    Log.i("0)", n); 


    //first N columns should match toViews first N views 
    String[] fromColumns = {getString(R.string.database_column_name), 
          getString(R.string.database_column_restaurant_type), 
          getString(R.string.database_column_phone_number), 
          getString(R.string.database_column_address), 
       getString(R.string.database_column_csz), 
       getString(R.string.database_column_brief_description), 
       getString(R.string.database_column_url), 
       getString(R.string.database_column_price)}; 

    int[] toViews = {android.R.id.text1}; 

    mAdapter = new SimpleCursorAdapter(getApplicationContext(), 
         this.getListView().getId(), 
         null, 
          fromColumns, 
         toViews, 
         0); 
    setListAdapter(mAdapter); 
    getLoaderManager().initLoader(0, searchParameters, this);  
} 

@Override 
public Loader<Cursor> onCreateLoader(int id, Bundle searchParameters) { 
    Log.i("3)", "Correct Loader Being Built"); 
    return new SQLiteCursorLoader(getApplicationContext(), 
      databaseHelper, 
      searchParameters, 
      null); 

} 

@Override 
public void onLoadFinished(Loader<Cursor> loader, Cursor data) { 
    mAdapter.swapCursor(data); 

} 

@Override 
public void onLoaderReset(Loader<Cursor> loader) { 
    mAdapter.swapCursor(null); 

} 

@Override 
    public void onListItemClick(ListView l, View v, int position, long id) 
{ 
    Cursor myCursor = (Cursor)l.getItemAtPosition(position); 
    if(l.isItemChecked(position) == true) 
    { 
     l.setItemChecked(position, false); 
     //shut down previously selected item details 

    } 
    else 
    { 
     l.setItemChecked(position, true); 

     //start previously selected item details 

    } 
} 


} 

SQLiteCursorLoader :

package com.studentapplication; 

import java.io.FileDescriptor; 
import java.io.PrintWriter; 
import java.util.Arrays; 
import android.content.ContentValues; 
import android.content.Context; 
import android.content.res.Resources; 
import android.database.Cursor; 
import android.database.sqlite.SQLiteDatabase; 
import android.database.sqlite.SQLiteOpenHelper; 
import android.database.sqlite.SQLiteQueryBuilder; 
import android.os.Bundle; 
import android.util.Log; 

public class SQLiteCursorLoader extends AbstractCursorLoader 
{ 
SQLiteOpenHelper db=null; 
String rawQuery=null; 
String[] args=null; 

/** 
* Creates a fully-specified SQLiteCursorLoader. See 
* {@link SQLiteDatabase#rawQuery(SQLiteDatabase, String, String[]) 
* SQLiteDatabase.rawQuery()} for documentation on the 
* meaning of the parameters. These will be passed as-is 
* to that call. 
*/ 
public SQLiteCursorLoader(Context context, SQLiteOpenHelper db, Bundle 
    searchParameters, String[] args) 
{ 
    super(context); 
    this.db=db; 
    this.rawQuery=createQuery(searchParameters); 
    this.args=args; 
} 

private String createQuery(Bundle searchParameters) { 
    String name = "\'"; 
    name = name + searchParameters.getString("name"); 
    name = name + "\'"; 
    int price = searchParameters.getInt("price"); 
    String restaurantType = "\'"; 
    restaurantType = restaurantType + 
      searchParameters.getString("restaurant_type"); 
    restaurantType = restaurantType + "\'"; 

    //String dist = searchParameters.getString("dist"); 

    String theQuery = ""; 

    if(!name.equals("\'\'")) 
    { 
     if(!restaurantType.equals("\'_\'")) 
     { 
      theQuery = "SELECT * FROM Restaurant WHERE name 
= "+ name + " AND rType = " + restaurantType; 
     } 
     else if(price != 0) 
     { 
      theQuery = "SELECT * FROM Restaurant WHERE name = " + name 
+ " AND price = " + ((Integer)price).toString(); 
     } 
     else 
     { 
      theQuery="SELECT * FROM Restaurant WHERE name = " + name; 
     } 
    } 
    else if(!restaurantType.equals("\'\'")) 
    { 
     theQuery = "SELECT * FROM Restaurant WHERE type = " + 
restaurantType + " SORT BY name"; 
    } 
    else if(price != 0) 
    { 
     theQuery="SELECT * FROM Restaurant WHERE price=" + price + " SORT 
BY name"; 
    } 



    return theQuery; 
} 


/** 
* Runs on a worker thread and performs the actual 
* database query to retrieve the Cursor. 
*/ 
@Override 
protected Cursor buildCursor() 
{ 
    return(db.getReadableDatabase().rawQuery(rawQuery, args)); 
} 

/** 
* Writes a semi-user-readable roster of contents to 
* supplied output. 
*/ 
@Override 
public void dump(String prefix, FileDescriptor fd, PrintWriter writer, String[] 
    args) 
{ 
    super.dump(prefix, fd, writer, args); 
    writer.print(prefix); 
    writer.print("rawQuery="); 
    writer.println(rawQuery); 
    writer.print(prefix); 
    writer.print("args="); 
    writer.println(Arrays.toString(args)); 
} 

public void insert(String table, String nullColumnHack, ContentValues values) 
{ 
    new InsertTask(this).execute(db, table, nullColumnHack, values); 
} 

public void update(String table, ContentValues values, String whereClause, String[] 
    whereArgs) 
{ 
    new UpdateTask(this).execute(db, table, values, whereClause, whereArgs); 
} 

public void replace(String table, String nullColumnHack, ContentValues values) 
{ 
    new ReplaceTask(this).execute(db, table, nullColumnHack, values); 
} 

public void delete(String table, String whereClause, String[] whereArgs) 
{ 
    new DeleteTask(this).execute(db, table, whereClause, whereArgs); 
} 

public void execSQL(String sql, Object[] bindArgs) 
{ 
    new ExecSQLTask(this).execute(db, sql, bindArgs); 
} 

//Private Classes 

private class InsertTask extends ContentChangingTask<Object, Void, Void> 
{ 
    InsertTask(SQLiteCursorLoader loader) 
    { 
     super(loader); 
    } 

    @Override 
    protected Void doInBackground(Object... params) 
    { 
     SQLiteOpenHelper db=(SQLiteOpenHelper)params[0]; 
     String table=(String)params[1]; 
     String nullColumnHack=(String)params[2]; 
     ContentValues values=(ContentValues)params[3]; 

     db.getWritableDatabase().insert(table, nullColumnHack, values); 

     return(null); 
    } 
} 

private class UpdateTask extends ContentChangingTask<Object, Void, Void> 
{ 
    UpdateTask(SQLiteCursorLoader loader) 
    { 
     super(loader); 
    } 

    @Override 
    protected Void doInBackground(Object... params) 
    { 
     SQLiteOpenHelper db=(SQLiteOpenHelper)params[0]; 
     String table=(String)params[1]; 
     ContentValues values=(ContentValues)params[2]; 
     String where=(String)params[3]; 
     String[] whereParams=(String[])params[4]; 

     db.getWritableDatabase().update(table, values, where, whereParams); 

     return(null); 
    } 
} 

private class ReplaceTask extends ContentChangingTask<Object, Void, Void> 
{ 
    ReplaceTask(SQLiteCursorLoader loader) 
    { 
     super(loader); 
    } 

    @Override 
    protected Void doInBackground(Object... params) 
    { 
     SQLiteOpenHelper db=(SQLiteOpenHelper)params[0]; 
     String table=(String)params[1]; 
     String nullColumnHack=(String)params[2]; 
     ContentValues values=(ContentValues)params[3]; 

     db.getWritableDatabase().replace(table, nullColumnHack, values); 

     return(null); 
    } 
} 

private class DeleteTask extends ContentChangingTask<Object, Void, Void> 
{ 
    DeleteTask(SQLiteCursorLoader loader) 
    { 
     super(loader); 
    } 

    @Override 
    protected Void doInBackground(Object... params) 
    { 
     SQLiteOpenHelper db=(SQLiteOpenHelper)params[0]; 
     String table=(String)params[1]; 
     String where=(String)params[2]; 
     String[] whereParams=(String[])params[3]; 

     db.getWritableDatabase().delete(table, where, whereParams); 

     return(null); 
    } 
} 

private class ExecSQLTask extends ContentChangingTask<Object, Void, Void> 
{ 
    ExecSQLTask(SQLiteCursorLoader loader) 
    { 
     super(loader); 
    } 

    @Override 
    protected Void doInBackground(Object... params) 
    { 
     SQLiteOpenHelper db=(SQLiteOpenHelper)params[0]; 
     String sql=(String)params[1]; 
     Object[] bindParams=(Object[])params[2]; 

     db.getWritableDatabase().execSQL(sql, bindParams); 

    return(null); 
    } 
} 
} 

AbstractCursorLoader :

package com.studentapplication; 

import android.annotation.TargetApi; 
import android.content.AsyncTaskLoader; 
import android.content.Context; 
import android.database.Cursor; 
import android.os.Build; 

@TargetApi(Build.VERSION_CODES.HONEYCOMB) 
abstract public class AbstractCursorLoader extends AsyncTaskLoader<Cursor> { 

abstract protected Cursor buildCursor(); 
Cursor lastCursor=null; 

public AbstractCursorLoader(Context context) { 
    super(context); 
} 

/** 
* Runs on a worker thread, loading in our data. Delegates 
* the real work to concrete subclass' buildCursor() method. 
*/ 
@Override 
public Cursor loadInBackground() { 
    Cursor cursor=buildCursor(); 

    if (cursor!=null) { 
    // Ensure the cursor window is filled 
    cursor.getCount(); 
    } 

    return(cursor); 
} 

/** 
* Runs on the UI thread, routing the results from the 
* background thread to whatever is using the Cursor 
* (e.g., a CursorAdapter). 
*/ 
@Override 
public void deliverResult(Cursor cursor) { 
    if (isReset()) { 
    // An async query came in while the loader is stopped 
    if (cursor!=null) { 
     cursor.close(); 
    } 

    return; 
    } 

    Cursor oldCursor=lastCursor; 
    lastCursor=cursor; 

    if (isStarted()) { 
    super.deliverResult(cursor); 
    } 

    if (oldCursor!=null && oldCursor!=cursor && !oldCursor.isClosed()) { 
    oldCursor.close(); 
    } 
} 

/** 
* Starts an asynchronous load of the list data. 
* When the result is ready the callbacks will be called 
* on the UI thread. If a previous load has been completed 
* and is still valid the result may be passed to the 
* callbacks immediately. 
* 
* Must be called from the UI thread. 
*/ 
@Override 
protected void onStartLoading() { 
    if (lastCursor!=null) { 
    deliverResult(lastCursor); 
    } 

    if (takeContentChanged() || lastCursor==null) { 
    forceLoad(); 
    } 
} 

/** 
* Must be called from the UI thread, triggered by a 
* call to stopLoading(). 
*/ 
@Override 
protected void onStopLoading() { 
    // Attempt to cancel the current load task if possible. 
    cancelLoad(); 
} 

/** 
* Must be called from the UI thread, triggered by a 
* call to cancel(). Here, we make sure our Cursor 
* is closed, if it still exists and is not already closed. 
*/ 
@Override 
public void onCanceled(Cursor cursor) { 
    if (cursor!=null && !cursor.isClosed()) { 
    cursor.close(); 
    } 
} 

/** 
* Must be called from the UI thread, triggered by a 
* call to reset(). Here, we make sure our Cursor 
* is closed, if it still exists and is not already closed. 
*/ 
@Override 
protected void onReset() { 
    super.onReset(); 

    // Ensure the loader is stopped 
    onStopLoading(); 

    if (lastCursor!=null && !lastCursor.isClosed()) { 
    lastCursor.close(); 
    } 

    lastCursor=null; 
    } 
    } 

DatabaseHelper :

012,317,748,913,957,943,549,143 여기 내 코드입니다 33,210

스택 추적이 : 당신이 당신의 데이터베이스의 스키마를 수정

생산에서
04-23 13:47:29.691: E/SQLiteLog(2600): (1) no such column: rType 
04-23 13:47:29.691: W/dalvikvm(2600): threadid=11: thread exiting with uncaught 
    exception (group=0x40a13300) 
04-23 13:47:29.852: E/AndroidRuntime(2600): FATAL EXCEPTION: AsyncTask #1 
04-23 13:47:29.852: E/AndroidRuntime(2600): java.lang.RuntimeException: An error 
    occured while executing doInBackground() 
04-23 13:47:29.852: E/AndroidRuntime(2600):  at 
    android.os.AsyncTask$3.done(AsyncTask.java:299) 
04-23 13:47:29.852: E/AndroidRuntime(2600):  at 
    java.util.concurrent.FutureTask$Sync.innerSetException(FutureTask.java:273) 
04-23 13:47:29.852: E/AndroidRuntime(2600):  at 
    java.util.concurrent.FutureTask.setException(FutureTask.java:124) 
04-23 13:47:29.852: E/AndroidRuntime(2600):  at 
    java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:307) 
04-23 13:47:29.852: E/AndroidRuntime(2600):  at 
    java.util.concurrent.FutureTask.run(FutureTask.java:137) 
04-23 13:47:29.852: E/AndroidRuntime(2600):  at 
    java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1076) 
04-23 13:47:29.852: E/AndroidRuntime(2600):  at 
    java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:569) 
04-23 13:47:29.852: E/AndroidRuntime(2600):  at 
    java.lang.Thread.run(Thread.java:856) 
04-23 13:47:29.852: E/AndroidRuntime(2600): Caused by: 
    android.database.sqlite.SQLiteException: no such column: rType (code 1): , while 
    compiling: SELECT * FROM Restaurant WHERE name = 'RName' AND rType = 'Fancy' 
04-23 13:47:29.852: E/AndroidRuntime(2600):  at 
    android.database.sqlite.SQLiteConnection.nativePrepareStatement(Native Method) 
04-23 13:47:29.852: E/AndroidRuntime(2600):  at 
    android.database.sqlite.SQLiteConnection.acquirePreparedStatement 
    (SQLiteConnection.java:882) 
04-23 13:47:29.852: E/AndroidRuntime(2600):  at 
    android.database.sqlite.SQLiteConnection.prepare(SQLiteConnection.java:493) 
04-23 13:47:29.852: E/AndroidRuntime(2600):  at 
    android.database.sqlite.SQLiteSession.prepare(SQLiteSession.java:588) 
04-23 13:47:29.852: E/AndroidRuntime(2600):  at 
    android.database.sqlite.SQLiteProgram.<init>(SQLiteProgram.java:58) 
04-23 13:47:29.852: E/AndroidRuntime(2600):  at 
    android.database.sqlite.SQLiteQuery.<init>(SQLiteQuery.java:37) 
04-23 13:47:29.852: E/AndroidRuntime(2600):  at 
    android.database.sqlite.SQLiteDirectCursorDriver.query 
    (SQLiteDirectCursorDriver.java:44) 
04-23 13:47:29.852: E/AndroidRuntime(2600):  at 
    android.database.sqlite.SQLiteDatabase.rawQueryWithFactory(SQLiteDatabase.java:1314) 
04-23 13:47:29.852: E/AndroidRuntime(2600):  at 
    android.database.sqlite.SQLiteDatabase.rawQuery(SQLiteDatabase.java:1253) 
04-23 13:47:29.852: E/AndroidRuntime(2600):  at 
    com.studentapplication.SQLiteCursorLoader.buildCursor(SQLiteCursorLoader.java:88) 
04-23 13:47:29.852: E/AndroidRuntime(2600):  at 
    com.studentapplication.AbstractCursorLoader.loadInBackground 
    (AbstractCursorLoader.java:24) 
04-23 13:47:29.852: E/AndroidRuntime(2600):  at 
    com.studentapplication.AbstractCursorLoader.loadInBackground 
    (AbstractCursorLoader.java:1) 
04-23 13:47:29.852: E/AndroidRuntime(2600):  at 
    android.content.AsyncTaskLoader.onLoadInBackground(AsyncTaskLoader.java:301) 
04-23 13:47:29.852: E/AndroidRuntime(2600):  at 
    android.content.AsyncTaskLoader$LoadTask.doInBackground(AsyncTaskLoader.java:68) 
04-23 13:47:29.852: E/AndroidRuntime(2600):  at 
    android.content.AsyncTaskLoader$LoadTask.doInBackground(AsyncTaskLoader.java:56) 
04-23 13:47:29.852: E/AndroidRuntime(2600):  at 
    android.os.AsyncTask$2.call(AsyncTask.java:287) 
04-23 13:47:29.852: E/AndroidRuntime(2600):  at 
    java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:305) 
04-23 13:47:29.852: E/AndroidRuntime(2600):  ... 4 more 
04-23 13:47:29.902: W/ActivityManager(161): Force finishing activity 
    com.studentapplication/.RestaurantSearchResultsActivity 
04-23 13:47:29.902: W/WindowManager(161): Failure taking screenshot for (266x425) to 
    layer 21020 
+1

하여 오류의 전체 스택 추적을 게시하시기 바랍니다. 또한,''* FROM Restaurant WHERE name = "+ name +"AND rType = "+ restaurantType; '는'name'과'restaurantType'이 따옴표가 없기 때문에 숫자가 아닌 한 유효한 쿼리가 될 수 없습니다. 그리고 "[당신의] 질의에 두 개의 WHERE 절이 있으면"유효한 SQL 구문이 될 수 없습니다. – CommonsWare

+0

안녕하세요. 내 질문을 살펴 줘서 고마워. 나는 그들을 인용했다. createQuery 메서드에서 SQLiteCursorLoader 클래스를 보면, 'and end with'로 시작하는 String을 설정합니다. 순간적으로 스택 추적을 게시합니다. – user2312185

+0

또한 WHERE 절이 유효한 구문이 아니라고 말하면 "WHERE name ="+ name + "AND rType ="+ restaurantType; 유효하지 않습니까? – user2312185

답변

0

이, 당신이 SQLiteOpenHelper 생성자에 전달 스키마 버전 번호를 범프, 그래서 SQLiteOpenHelperonUpgrade()를 호출하고 변화에 영향을 미칠 것입니다.

개발 중에 원하는대로 할 수 있습니다. 그러나 그것을 잊기 쉽습니다. 따라서 데이터베이스 구조는 기대와 일치하는 것으로 하나 보이지 않는 경우 : 버전 번호를 스키마

  • 범프를 onUpgrade() 전화를 강제로, 또는

  • 는 제거를 통해 기존 데이터베이스를 닦아 등의 설정에서 앱의 항목에서 "데이터 지우기"는의 onCreate()에 전화를 강제로 SQLiteOpenHelper

관련 문제