2016-06-15 1 views
0

Мой проект работал до того, как я скопировал каталог с моего старого компьютера на новый.Android Studio - база данных 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 + ";"; 

}

А вот мой DataBase класс:

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); 
    } 

} 

Do Вы г и любая идея проблемы? Это довольно странно, потому что (я повторяю это) я получил тот же код на моем другом компьютере, и не было никаких проблем ...

Спасибо,

Moric

ответ

0

Я не знаю, какие изменения сделали или нет, но ваш запрос создать таблицу, как показано ниже:

Ваш запрос

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

Там нет с olumn с именем «betUser», поэтому сначала нужно создать столбец, а затем вы можете назначить внешний ключ к нему,

Проверить ниже нового запроса:

Правильный запрос Для этого

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)) 
+0

Thank вы, я изменил его, но у меня все еще возникает такая же проблема, когда я запускаю MainActivity. – Moric

+0

Редактировать Ваш код поэтому можете проверить его – Vickyexpert

+0

Done! Я думаю, проблема возникает из openDb и getWritableDatabase, потому что мой конструктор DataBase работает хорошо. – Moric