SQLite 数据库在每次应用重启时初始化
SQLite database getting initialized on every app restart
下面是我正在处理的代码。
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)",
}
发生了什么: 当应用程序启动时,我正在检查 table 是否存在。如果它不存在,那么我正在创建 table。我关闭应用程序并再次打开它,我看到 table 正在再次创建。
我期望发生的事情: 应用程序的第一次启动应该创建 table,随后的启动应该发现 table 存在并且不应再次创建它。
你们能告诉我我做错了什么吗?
好的。我在上面的问题中有很多地方做错了。
在 select 查询中使用 type = 'table'
而不是 type = 'TABLE'
来检查数据库。我浏览了一些在线搜索结果并观察到了这一点。
重写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;
}
我总是创建 table 的原因是我在 componentDidMount
方法中的 if 条件错误。 checkFirstTimeUsage
是一个异步函数,返回一个我直接在 if 条件中使用的 promise,因为 promise 不是 false
、null
、undefined
中的一个,所以它始终评估为 true。
下面是我正在处理的代码。
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)",
}
发生了什么: 当应用程序启动时,我正在检查 table 是否存在。如果它不存在,那么我正在创建 table。我关闭应用程序并再次打开它,我看到 table 正在再次创建。
我期望发生的事情: 应用程序的第一次启动应该创建 table,随后的启动应该发现 table 存在并且不应再次创建它。
你们能告诉我我做错了什么吗?
好的。我在上面的问题中有很多地方做错了。
在 select 查询中使用
type = 'table'
而不是type = 'TABLE'
来检查数据库。我浏览了一些在线搜索结果并观察到了这一点。重写
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;
}
我总是创建 table 的原因是我在 componentDidMount
方法中的 if 条件错误。 checkFirstTimeUsage
是一个异步函数,返回一个我直接在 if 条件中使用的 promise,因为 promise 不是 false
、null
、undefined
中的一个,所以它始终评估为 true。