Android Studio - SQLite数据库(getWritableDatabase函数)在项目副本之后不起作用

时间:2016-06-15 22:45:08

标签: android sqlite getwritabledatabase

在将目录从旧计算机复制到新计算机之前,我的项目正在运行。

这是我的logcat:

06-15 22:28:03.169 3205-3205/com.example.moric.pronostic W/System: ClassLoader referenced unknown path: /data/app/com.example.moric.pronostic-2/lib/x86
06-15 22:28:03.674 3205-3205/com.example.moric.pronostic W/System: ClassLoader referenced unknown path: /data/app/com.example.moric.pronostic-2/lib/x86
06-15 22:28:03.830 3205-3205/com.example.moric.pronostic W/art: Before Android 4.1, method android.graphics.PorterDuffColorFilter android.support.graphics.drawable.VectorDrawableCompat.updateTintFilter(android.graphics.PorterDuffColorFilter, android.content.res.ColorStateList, android.graphics.PorterDuff$Mode) would have incorrectly overridden the package-private method in android.graphics.drawable.Drawable
06-15 22:28:03.860 3205-3205/com.example.moric.pronostic E/SQLiteLog: (1) unknown column "betUser" in foreign key definition
06-15 22:28:03.872 3205-3205/com.example.moric.pronostic D/AndroidRuntime: Shutting down VM
--------- beginning of crash
06-15 22:28:03.872 3205-3205/com.example.moric.pronostic E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.example.moric.pronostic, PID: 3205
java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example.moric.pronostic/com.example.moric.pronostic.MainActivity}: android.database.sqlite.SQLiteException: unknown column "betUser" in foreign key definition (code 1): , while compiling: CREATE TABLE betsTable (betId INTEGER PRIMARY KEY AUTOINCREMENT, betScore TEXT, FOREIGN KEY(betUser) REFERENCES userTable(userId), FOREIGN KEY(betMatch) REFERENCES matchTable(id));
    at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2416)
    at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2476)
    at android.app.ActivityThread.-wrap11(ActivityThread.java)
    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1344)
    at android.os.Handler.dispatchMessage(Handler.java:102)
    at android.os.Looper.loop(Looper.java:148)
    at android.app.ActivityThread.main(ActivityThread.java:5417)
    at java.lang.reflect.Method.invoke(Native Method)
    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)
Caused by: android.database.sqlite.SQLiteException: unknown column "betUser" in foreign key definition (code 1): , while compiling: CREATE TABLE betsTable (betId INTEGER PRIMARY KEY AUTOINCREMENT, betScore TEXT, FOREIGN KEY(betUser) REFERENCES userTable(userId), FOREIGN KEY(betMatch) REFERENCES matchTable(id));
    at android.database.sqlite.SQLiteConnection.nativePrepareStatement(Native Method)
    at android.database.sqlite.SQLiteConnection.acquirePreparedStatement(SQLiteConnection.java:887)
    at android.database.sqlite.SQLiteConnection.prepare(SQLiteConnection.java:498)
    at android.database.sqlite.SQLiteSession.prepare(SQLiteSession.java:588)
    at android.database.sqlite.SQLiteProgram.<init>(SQLiteProgram.java:58)
    at android.database.sqlite.SQLiteStatement.<init>(SQLiteStatement.java:31)
    at android.database.sqlite.SQLiteDatabase.executeSql(SQLiteDatabase.java:1674)
    at android.database.sqlite.SQLiteDatabase.execSQL(SQLiteDatabase.java:1605)
    at com.example.moric.pronostic.DataBaseHandler.onCreate(DataBaseHandler.java:17)
    at android.database.sqlite.SQLiteOpenHelper.getDatabaseLocked(SQLiteOpenHelper.java:251)
    at android.database.sqlite.SQLiteOpenHelper.getWritableDatabase(SQLiteOpenHelper.java:163)
    at com.example.moric.pronostic.MatchDataBase.openDb(MatchDataBase.java:33)
    at com.example.moric.pronostic.MainActivity.onCreate(MainActivity.java:29)
    at android.app.Activity.performCreate(Activity.java:6237)
    at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1107)
    at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2369)
    at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2476) 
    at android.app.ActivityThread.-wrap11(ActivityThread.java) 
    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1344) 
    at android.os.Handler.dispatchMessage(Handler.java:102) 
    at android.os.Looper.loop(Looper.java:148) 
    at android.app.ActivityThread.main(ActivityThread.java:5417) 
    at java.lang.reflect.Method.invoke(Native Method) 
    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726) 
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)

以下是我的 MainActivity ,它在没有openDb()closeDb()功能的情况下运行,我已对其进行了测试。在我的代码中没有使用数据库是正常的,这是一个测试。

import android.app.Activity;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.widget.Toast;

import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.Vector;

public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    //Création de la base de données
    MatchDataBase matchDataBase = new MatchDataBase(this);
    Vector<Match> matchList = new Vector<Match>();
        matchList.addElement(new Match(1, "France", "Roumanie", "10/06/2016 - 15h00", new Score(2, 1), "Poule A"));
        matchList.addElement(new Match(2, "France", "Irlande", "12/06/2016 - 11h00", new Score(1, 0), "Quarts"));
        matchList.addElement(new Match(3, "France", "Allemagne", "15/06/2016 - 15h30", "Demi-finale"));
        matchList.addElement(new Match(4, "France", "Angleterre", "18/06/2016 - 18h00", "Finale"));
    matchDataBase.openDb();
    matchDataBase.closeDb();

}
}

这是我的 DataBaseHandler (扩展SQLiteOpenHelper的类):

import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;

public class DataBaseHandler extends SQLiteOpenHelper {

public DataBaseHandler(Context context, String name, SQLiteDatabase.CursorFactory factory, int version) {
    super(context, name, factory, version);
}

@Override
public void onCreate(SQLiteDatabase db) {
    db.execSQL(TABLE_MATCH_CREATE);
    db.execSQL(TABLE_USER_CREATE);
    db.execSQL(TABLE_BETS_CREATE);
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
    db.execSQL(TABLE_MATCH_DROP);
    db.execSQL(TABLE_USER_DROP);
    db.execSQL(TABLE_BETS_DROP);
    onCreate(db);
}

//Caractéristiques de la table relative aux Matches, indépendants des utilisateurs
public static final String TABLE_MATCH = "matchTable";
public static final String MATCH_KEY = "id";
public static final String DATE = "date";
public static final String INFO = "info";
public static final String SCORE = "score";
public static final String TEAMDOM = "teamDom";
public static final String TEAMEXT = "teamExt";
public static final String TABLE_MATCH_CREATE = "CREATE TABLE " + TABLE_MATCH + " ("
                + MATCH_KEY + " INTEGER PRIMARY KEY AUTOINCREMENT, "
                + DATE + " TEXT, "
                + INFO + " TEXT, "
                + SCORE + " TEXT, "
                + TEAMDOM + " TEXT, "
                + TEAMEXT + " TEXT);";
public static final String TABLE_MATCH_DROP = "DROP TABLE IF EXISTS " + TABLE_MATCH + ";";

//Caractéristiques de la table relative aux Utilisateurs
public static final String TABLE_USER= "userTable";
public static final String USER_KEY = "userId";
public static final String USERNAME = "userName";
public static final String TABLE_USER_CREATE = "CREATE TABLE " + TABLE_USER + " ("
        + USER_KEY + " INTEGER PRIMARY KEY AUTOINCREMENT, "
        + USERNAME + " TEXT); ";
public static final String TABLE_USER_DROP = "DROP TABLE IF EXISTS " + TABLE_USER + ";";

//Caractéristiques de la table relative aux Pronostics
public static final String TABLE_BETS= "betsTable";
public static final String BET_KEY = "betId";
public static final String BET_SCORE = "betScore";
public static final String BET_USER = "betUser";
public static final String BET_MATCH = "betMatch";
public static final String TABLE_BETS_CREATE = "CREATE TABLE " + TABLE_BETS + " ("
        + BET_KEY + " INTEGER PRIMARY KEY AUTOINCREMENT, "
        + BET_SCORE + " TEXT, "
        + BET_USER + "INTEGER, "
        + BET_MATCH + "INTEGER, "
        + "FOREIGN KEY(" + BET_USER + ") REFERENCES " + TABLE_USER + "(" + USER_KEY + "), "
        + "FOREIGN KEY(" + BET_MATCH + ") REFERENCES " + TABLE_MATCH + "(" + MATCH_KEY + ")); ";
public static final String TABLE_BETS_DROP = "DROP TABLE IF EXISTS " + TABLE_BETS + ";";

}

这是我的数据库类:

import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.support.annotation.Nullable;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.Vector;

public class MatchDataBase {

    private final static int VERSION = 1;
    private final static String NOM = "matches.db";
    private static SimpleDateFormat dateFormat = new SimpleDateFormat("dd/MM/yyyy' - 'HH'h'mm");

    private SQLiteDatabase mDb;
    private DataBaseHandler mHandler;
    public SQLiteDatabase getDb() {
        return mDb;
    }
    //Méthodes de création, d'ouverture et de fermeture de la base de données.
    public MatchDataBase(Context pContext) {
        this.mHandler = new DataBaseHandler(pContext, NOM, null, VERSION);
    }
    public void openDb() {
        //Pour ouvrir l'accès à la base de données.
        //getWritableDatabase ferme également la dernière base.
        this.mDb = this.mHandler.getWritableDatabase();
    }
    public void closeDb() {
        //Pour fermer l'accès à la base de données.
        this.mDb.close();
    }

    //Caractéristiques de la table des matches.
    private static final String TABLE_MATCH = "matchTable";
    private static final String MATCH_KEY = "id";
    private static final int NUM_COL_MATCH_KEY = 0;
    private static final String TEAMDOM = "teamDom";
    private static final int NUM_COL_TEAMDOM = 1;
    private static final String TEAMEXT = "teamExt";
    private static final int NUM_COL_TEAMEXT = 2;
    private static final String DATE = "date";
    private static final int NUM_COL_DATE = 3;
    private static final String SCORE = "score";
    private static final int NUM_COL_SCORE = 4;
    private static final String INFO = "info";
    private static final int NUM_COL_INFO = 5;

    //Fonctions de la table des matches
    //Cette fonction permet d'ajouter un match à la base de données.
    public void addMatch(Match match) {
        ContentValues value = new ContentValues();
        value.put(MatchDataBase.MATCH_KEY, match.getId());
        value.put(MatchDataBase.DATE, match.getDate());
        value.put(MatchDataBase.INFO, match.getInfo());
        value.put(MatchDataBase.SCORE, match.getScore().toString());
        value.put(MatchDataBase.TEAMDOM, match.getTeamDom());
        value.put(MatchDataBase.TEAMEXT, match.getTeamExt());
        //L'on veut que le match déterminé remplace le précédent, donc on supprime celui qui existait déjà.
        this.deleteMatch(match.getId());
        mDb.insert(MatchDataBase.TABLE_MATCH, null, value);
    }
    //Cette fonction permet de supprimer un match de la base de données.
    public void deleteMatch(long id) {
        mDb.delete(TABLE_MATCH, MATCH_KEY + " = ?", new String[]{String.valueOf(id)});
    }
    //Cette fonction permet de modifier les informations d'un match, connaissant son ID.
    public void updateMatch(Match match) {
        ContentValues value = new ContentValues();
        value.put(MatchDataBase.DATE, match.getDate());
        value.put(MatchDataBase.INFO, match.getInfo());
        value.put(MatchDataBase.SCORE, match.getScore().toString());
        value.put(MatchDataBase.TEAMDOM, match.getTeamDom());
        value.put(MatchDataBase.TEAMEXT, match.getTeamExt());
        mDb.update(TABLE_MATCH, value, MATCH_KEY + " = ?", new String[]{String.valueOf(match.getId())});
    }
    @Nullable //Cette fonction permet de récupérer la première ligne d'un cursor sous la forme d'un objet java de la classe Match.
    private Match cursorToMatch(Cursor c) {
        if (c.getCount() == 0) {
            return null;
        }
        //On se place au premier élément
        c.moveToFirst();

        Match returnedMatch = new Match();
        returnedMatch.setId(c.getLong(NUM_COL_MATCH_KEY));
        returnedMatch.setTeamDom(c.getString(NUM_COL_TEAMDOM));
        returnedMatch.setTeamExt(c.getString(NUM_COL_TEAMEXT));
        returnedMatch.setDate(c.getString(NUM_COL_DATE));
        String writtenScore = c.getString(NUM_COL_SCORE);
        returnedMatch.setScore(Score.convertStringToScore(writtenScore));
        returnedMatch.setInfo(c.getString(NUM_COL_INFO));

        c.close();
        return returnedMatch;
    }
    //Cette fonction permet de récupérer un match à partir de son ID.
    public Match getMatchWithId(long id) {
        Cursor c = mDb.query(TABLE_MATCH, new String[]{MATCH_KEY, TEAMDOM, TEAMEXT, DATE, SCORE, INFO},
                MATCH_KEY + "= ?", new String[]{String.valueOf(id)}, null, null, null);

        return cursorToMatch(c);
    }
    //Cette fonction permet de récupérer tous les matches qui auront lieu après une date donnée, dans une table de type ArrayList déjà créée.
    public void getMatchesAfterDate(String currentDateString, ArrayList<Match> listToComplete) {

        Date currentDate = new Date();
        Cursor c = mDb.query(TABLE_MATCH, new String[]{MATCH_KEY, TEAMDOM, TEAMEXT, DATE, SCORE, INFO},
                null, null, null, null, null);
        try {
            currentDate = dateFormat.parse(currentDateString);
        } catch (ParseException e) {
            e.printStackTrace();
        }
        if (c.getCount() == 0) {
        }
        for(c.moveToFirst(); !c.isAfterLast(); c.moveToNext()) {
            try {
                Date dateMatch = dateFormat.parse(c.getString(NUM_COL_DATE));

                if (dateMatch.after(currentDate)){
                    Match thisMatch = new Match();
                    thisMatch.setId(c.getLong(NUM_COL_MATCH_KEY));
                    thisMatch.setTeamDom(c.getString(NUM_COL_TEAMDOM));
                    thisMatch.setTeamExt(c.getString(NUM_COL_TEAMEXT));
                    thisMatch.setDate(c.getString(NUM_COL_DATE));
                    String writtenScore = c.getString(NUM_COL_SCORE);
                    thisMatch.setScore(Score.convertStringToScore(writtenScore));
                    thisMatch.setInfo(c.getString(NUM_COL_INFO));

                    listToComplete.add(thisMatch);
                }
            } catch (ParseException e) {
                e.printStackTrace();
            }
        }
        c.close();
    }

    //Caractéristiques de la table des utilisateurs.
    public static final String TABLE_USER= "userTable";
    public static final String USER_KEY = "userId";
    private static final int NUM_COL_USER_KEY = 0;
    public static final String USERNAME = "userName";
    private static final int NUM_COL_USERNAME = 1;

    //Fonctions de la table des utilisateurs.
    //Cette fonction permet d'ajouter un utilisateur à la base de données.
    public void addUser(User user) {
        ContentValues value = new ContentValues();
        value.put(MatchDataBase.USER_KEY, user.getUserId());
        value.put(MatchDataBase.USERNAME, user.getUserName());
        this.deleteUser(user.getUserId());
        mDb.insert(MatchDataBase.TABLE_USER, null, value);
    }
    //Cette fonction permet de supprimer un match de la base de données.
    public void deleteUser(long id) {
        mDb.delete(TABLE_USER, USER_KEY + " = ?", new String[]{String.valueOf(id)});
    }
    //Cette fonction permet de modifier les informations d'un utilisateur, connaissant son ID.
    public void updateUser(User user) {
        ContentValues value = new ContentValues();
        value.put(MatchDataBase.USERNAME, user.getUserName());
        mDb.update(TABLE_USER, value, USER_KEY + " = ?", new String[]{String.valueOf(user.getUserId())});
    }
    @Nullable //Cette fonction permet de récupérer la première ligne d'un cursor sous la forme d'un objet java de la classe User.
    private User cursorToUser(Cursor c) {
        if (c.getCount() == 0) {
            return null;
        }
        //On se place au premier élément
        c.moveToFirst();

        User returnedUser = new User();
        returnedUser.setUserId(c.getLong(NUM_COL_USER_KEY));
        returnedUser.setUserName(c.getString(NUM_COL_USERNAME));

        c.close();
        return returnedUser;
    }
    //Cette fonction permet de récupérer un utilisateur à partir de son ID.
    public User getUserWithId(long id) {
        Cursor c = mDb.query(TABLE_USER, new String[]{USER_KEY, USERNAME},
                USER_KEY + "= ?", new String[]{String.valueOf(id)}, null, null, null);
        return cursorToUser(c);
    }

    //Caractéristiques de la table des pronostics.
    public static final String TABLE_BETS= "betsTable";
    public static final String BET_KEY = "betId";
    private static final int NUM_COL_BET_KEY = 0;
    public static final String BET_SCORE = "betScore";
    private static final int NUM_COL_BET_SCORE = 1;
    public static final String BET_USER = "betUser";
    private static final int NUM_COL_BET_USER = 2;
    public static final String BET_MATCH = "betMatch";
    private static final int NUM_COL_BET_MATCH = 3;

    //Fonctions de la table des pronostics.
    //Cette fonction permet d'ajouter un utilisateur à la base de données.
    public void addBet(Bet bet) {
        ContentValues value = new ContentValues();
        value.put(MatchDataBase.BET_KEY, bet.getBetId());
        value.put(MatchDataBase.BET_SCORE, bet.getBetScore().toString());
        value.put(MatchDataBase.BET_USER, bet.getBetUser());
        value.put(MatchDataBase.BET_MATCH, bet.getBetMatch());
        this.deleteUser(bet.getBetId());
        mDb.insert(MatchDataBase.TABLE_USER, null, value);
    }
    //Cette fonction permet de supprimer un match de la base de données.
    public void deleteBet(long id) {
        mDb.delete(TABLE_BETS, BET_KEY + " = ?", new String[]{String.valueOf(id)});
    }
    //Cette fonction permet de modifier les informations d'un utilisateur, connaissant son ID.
    public void updateBet(Bet bet) {
        ContentValues value = new ContentValues();
        value.put(MatchDataBase.BET_SCORE, bet.getBetScore().toString());
        value.put(MatchDataBase.BET_USER, bet.getBetUser());
        value.put(MatchDataBase.BET_MATCH, bet.getBetMatch());
        mDb.update(TABLE_BETS, value, BET_KEY + " = ?", new String[]{String.valueOf(bet.getBetId())});
    }
    @Nullable //Cette fonction permet de récupérer la première ligne d'un cursor sous la forme d'un objet java de la classe User.
    private Bet cursorToBet(Cursor c) {
        if (c.getCount() == 0) {
            return null;
        }
        //On se place au premier élément
        c.moveToFirst();

        Bet returnedBet = new Bet();
        returnedBet.setBetId(c.getLong(NUM_COL_BET_KEY));
        String writtenScore = c.getString(NUM_COL_BET_SCORE);
        returnedBet.setBetScore(Score.convertStringToScore(writtenScore));
        returnedBet.setBetUser(c.getLong(NUM_COL_BET_USER));
        returnedBet.setBetMatch(c.getLong(NUM_COL_BET_MATCH));

        c.close();
        return returnedBet;
    }
    //Cette fonction permet de récupérer un utilisateur à partir de son ID.
    public Bet geBetWithId(long id) {
        Cursor c = mDb.query(TABLE_BETS, new String[]{BET_KEY, BET_SCORE, BET_USER, BET_MATCH},
                BET_KEY + "= ?", new String[]{String.valueOf(id)}, null, null, null);
        return cursorToBet(c);
    }

}

你知道这个问题吗?这很奇怪,因为(我重复一遍)我在其他电脑上得到了相同的代码,没有问题...

谢谢,

莫里奇

1 个答案:

答案 0 :(得分:0)

我不知道您做了哪些更改,但您的创建表查询如下所示:

您的查询

    CREATE TABLE betsTable (betId INTEGER PRIMARY KEY AUTOINCREMENT, betScore TEXT, FOREIGN KEY(betUser) REFERENCES userTable(userId), FOREIGN KEY(betMatch) REFERENCES matchTable(id));

没有名称为#34; betUser&#34;的列,所以首先需要创建列,然后您可以为其指定外键,

检查以下新查询:

正确查询

  CREATE TABLE betsTable (betId INTEGER PRIMARY KEY AUTOINCREMENT, betScore TEXT, betUser TEXT, betMatch TEXT, FOREIGN KEY(betUser)  REFERENCES userTable(userId), FOREIGN KEY(betMatch) REFERENCES matchTable(id))