База данных SQLite инициализируется при каждом перезапуске приложения - PullRequest
0 голосов
/ 04 октября 2019

Ниже мой код, над которым я работаю.

App.js

    /**
 * Sample React Native App
 * https://github.com/facebook/react-native
 *
 * Generated with the TypeScript template
 * https://github.com/react-native-community/react-native-template-typescript
 *
 * @format
 */

import * as React from 'react';
import {
  SafeAreaView,
  StyleSheet,
  ScrollView,
  View,
  Text,
  StatusBar,
} from 'react-native';

import {
  Header,
  LearnMoreLinks,
  Colors,
  DebugInstructions,
  ReloadInstructions,
} from 'react-native/Libraries/NewAppScreen';
import SQLite from "react-native-sqlite-storage";

const database_name = "Test.db";
const database_version = "1.0";
const database_displayname = "SQLite Test Database";
const database_size = 200000;
SQLite.enablePromise(true);

let db;
type InitState={
  firstTimeUsage:boolean,
  errorOccured:boolean,
  errorMessage:string
}

export default class App extends React.Component<{},InitState>{
  constructor(props:any){
    super(props);
    this.state={
      firstTimeUsage:null,
      errorOccured:false,
      errorMessage:null
    }
  }

  componentDidMount(){
    console.log("Component did mount called");
    SQLite.openDatabase(database_name, database_version, database_displayname, database_size).then((DB)=>{
      console.log("database opened");
      db = DB;
      if(this.checkFirstTimeUsage(db)){
        this.createTable(db);
      }else{
        this.setState({firstTimeUsage:false});
      }
    }).catch((error)=>{
      console.log("error occured opening database");
      this.setState({errorOccured:true,errorMessage:"Error validating app installation"});
    });
  }

  createTable = (database:any) => {
    console.log("Creating table");
    database.transaction((tx:SQLite.transaction)=>{
      tx.executeSql("CREATE TABLE IF NOT EXISTS PROFILE_MASTER (PLAYER_TAG VARCHAR(10) PRIMARY KEY NOT NULL,DEFAULT_IND VARCHAR(1) NOT NULL);")
      .then(([tx,results]) => {
        console.log("Table created");
        this.setState({firstTimeUsage:true});
      }).catch((_error: any)=>{
        console.log("error occured creating table");
        this.setState({errorOccured:true,errorMessage:"Error initializing app"})
      });
      tx.executeSql("INSERT into PROFILE_MASTER (PLAYER_TAG,DEFAULT_IND) values ('ASDC','Y')")
      .then(([results])=>{
        console.log("added data to table");
        console.log(results);
      }).catch((error: any) => {
        console.log("error adding data to table");
        console.log(error)
      })
    })
  }


  checkFirstTimeUsage = async (database:SQLite.SQLiteDatabase) => {
    return await database.transaction((tx)=>{
      tx.executeSql("SELECT name from sqlite_master where type='TABLE' and name = 'PROFILE_MASTER'",null).
      then(([tx,results])=>{
        if(results.rows.length===0){
          return true;
        }else{
          return false;
        }
      })
    }).catch((error)=>{
      console.log(error);
      return false;
    })
  }
  render(){
    console.log("first time usage is "+this.state.firstTimeUsage);
    return (
      <>
        <StatusBar barStyle="dark-content" />
        <SafeAreaView>
          <ScrollView
            contentInsetAdjustmentBehavior="automatic"
            style={styles.scrollView}>
            <Header />
            <View style={styles.body}>
              <View style={styles.sectionContainer}>
                <Text style={styles.sectionTitle}>Step One{this.state.firstTimeUsage}</Text>
                <Text style={styles.sectionDescription}>
                  Edit <Text style={styles.highlight}>App.tsx</Text> to change this
                  screen and then come back to see your edits.
                </Text>
              </View>
              <View style={styles.sectionContainer}>
                <Text style={styles.sectionTitle}>See Your Changes</Text>
                <Text style={styles.sectionDescription}>
                  <ReloadInstructions />
                </Text>
              </View>
              <View style={styles.sectionContainer}>
                <Text style={styles.sectionTitle}>Debug</Text>
                <Text style={styles.sectionDescription}>
                  <DebugInstructions />
                </Text>
              </View>
              <View style={styles.sectionContainer}>
                <Text style={styles.sectionTitle}>Learn More</Text>
                <Text style={styles.sectionDescription}>
                  Read the docs to discover what to do next:
                </Text>
              </View>
              <LearnMoreLinks />
            </View>
          </ScrollView>
        </SafeAreaView>
      </>
    );
  }
}

const styles = StyleSheet.create({
  scrollView: {
    backgroundColor: Colors.lighter,
  },
  engine: {
    position: 'absolute',
    right: 0,
  },
  body: {
    backgroundColor: Colors.white,
  },
  sectionContainer: {
    marginTop: 32,
    paddingHorizontal: 24,
  },
  sectionTitle: {
    fontSize: 24,
    fontWeight: '600',
    color: Colors.black,
  },
  sectionDescription: {
    marginTop: 8,
    fontSize: 18,
    fontWeight: '400',
    color: Colors.dark,
  },
  highlight: {
    fontWeight: '700',
  },
  footer: {
    color: Colors.dark,
    fontSize: 12,
    fontWeight: '600',
    padding: 4,
    paddingRight: 12,
    textAlign: 'right',
  },
});

package.json

{
  "name": "StatsRoyaleMulti",
  "version": "0.0.1",
  "private": true,
  "scripts": {
    "android": "react-native run-android",
    "ios": "react-native run-ios",
    "start": "react-native start",
    "test": "jest"
  },
  "dependencies": {
    "react": "16.9.0",
    "react-native": "0.61.1",
    "react-native-sqlite-storage": "^4.1.0"
  },
  "devDependencies": {
    "@babel/core": "^7.6.2",
    "@babel/runtime": "^7.6.2",
    "@react-native-community/eslint-config": "^0.0.5",
    "@types/jest": "^24.0.18",
    "@types/react": "^16.9.4",
    "@types/react-native": "^0.60.17",
    "@types/react-test-renderer": "16.9.0",
    "babel-jest": "^24.9.0",
    "jest": "^24.9.0",
    "metro-react-native-babel-preset": "^0.56.0",
    "react-test-renderer": "16.9.0",
    "typescript": "^3.6.3"
  },
  "jest": {
    "preset": "react-native",
    "moduleFileExtensions": [
      "ts",
      "tsx",
      "js",
      "jsx",
      "json",
      "node"
    ]
  }
}

Журнал консоли:

Running "StatsRoyaleMulti" with {"rootTag":1}
 LOG  first time usage is null
 LOG  Component did mount called
 LOG  database opened
 LOG  Creating table
 LOG  Table created
 LOG  first time usage is true
 LOG  added data to table
 LOG  {"db": {"dbname": "Test.db", "openError": [Function error], "openSuccess": [Function success], "openargs": {"dblocation": "nosync", "name": "Test.db"}}, "error": [Function error], "executes": [], "finalized": true, "fn": [Function anonymous], "readOnly": false, "success": [Function success], "txlock": true}


 LOG  Running "StatsRoyaleMulti" with {"rootTag":11}
 LOG  first time usage is null
 LOG  Component did mount called
 LOG  database opened
 LOG  Creating table
 LOG  Table created
 LOG  first time usage is true
 WARN  Possible Unhandled Promise Rejection (id: 0):
Object {
  "code": 0,
  "message": "UNIQUE constraint failed: PROFILE_MASTER.PLAYER_TAG (code 1555 SQLITE_CONSTRAINT_PRIMARYKEY)",
}

Что происходит: Когда приложение запускается, я проверяю, существует ли таблица. Если его не существует, я создаю таблицу. Я закрываю приложение и снова открываю его, и я вижу, что таблица создается снова.

То, что я ожидаю, произойдет: При первом запуске приложения должны быть созданы таблица и последующиеЗапуски должны обнаружить, что таблица существует, и не должны создавать ее снова.

Ребята, скажите, что я здесь не так делаю.

1 Ответ

0 голосов
/ 05 октября 2019

Хорошо. Есть несколько вещей, которые я делаю неправильно в приведенном выше вопросе.

  1. Используйте type = 'table' вместо type = 'TABLE' в запросе выбора для проверки базы данных. Я просматривал некоторые результаты поиска в Интернете и наблюдал это.

  2. Перепишите componentDidMount и checkFirstTimeUsage методы, как показано ниже

componentDidMount

async componentDidMount(){
    console.log("Component did mount called");
    let db = await SQLite.openDatabase(database_name, database_version, database_displayname, database_size);
    let firstTimeUsage = await this.checkFirstTimeUsage(db);
    if(firstTimeUsage){
      this.createTable(db);
    }else{
      this.setState({firstTimeUsage:false});
    }
  }

checkFirstTimeUsage

checkFirstTimeUsage = async (database:SQLite.SQLiteDatabase) => {
    let firstTimeUsage = null;
    await database.transaction((tx)=>{
      tx.executeSql("SELECT name from sqlite_master where type='table' and name = 'PROFILE_MASTER'",null).
      then(([tx,results])=>{
        if(results.rows.length===0){
          firstTimeUsage = true;
        }else{
          console.log("rows length greater than 0");
          firstTimeUsage = false;
        }
      })
    }).catch((error: any)=>{
      console.log(error);
      firstTimeUsage = false;
    });
    return firstTimeUsage;
  }

Причиной, по которой я всегда создавал таблицу, была неправильная ситуация, если у меня было условие componentDidMountметод. checkFirstTimeUsage - это асинхронная функция, которая возвращала обещание, в котором я непосредственно использовал условие if, которое всегда оценивалось как true, поскольку обещание не является одним из false, null, undefined.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...