|
注册免广告
您需要 登录 才可以下载或查看,没有账号?注册
×
本帖最后由 HelloWorld 于 2024-2-24 10:11 编辑
最近在写个 app 需要用到 sqlite,选择 orm 时,本来打算用 Prisma,但是这个必须 node 环境,expo 用不了
另一个比较流行的是 typeorm,查了一下,他们官方提供了 expo 例子:https://github.com/typeorm/expo-example ,将这个仓库拉本地运行直接失败,毕竟 6 年前老项目,expo 版本也不兼容了
于是自己新建一个 expo-router 项目:https://docs.expo.dev/router/installation ,然后将 expo-example 的页面代码和 entities 拷贝到 expo-router 项目里
由于 typeorm 用到装饰器,所以需要在 tsconfig.json 里添加 compilerOptions.experimentalDecorators 和 compilerOptions.emitDecoratorMetadata 并且值都设为 true
然后运行,一堆报错,其中一个可能是因为 expo-example 用的类组件搬到 expo-router 里无法被 tab 识别,于是将整个页面改成 function 组件,代码会放到帖子末尾
改了 function 组件运行再次报错,将错误消息拿去问 gemini,说在 entity 里需要设置变量类型,于是设置 @Column({type: 'string'}),运行又报错,再次问 gemini,它说 sqlite 没有 string 类型,于是用了 text,运行成功:
- import { Entity, PrimaryGeneratedColumn, Column } from "typeorm/browser";
- @Entity('category')
- export class Category {
- @PrimaryGeneratedColumn()
- id!: number;
- @Column({ type: 'text' })
- name!: string;
- }
复制代码
上文提到的类组件页面代码改成函数组件:
- import React, { useEffect, useState } from 'react'
- import {
- StyleSheet,
- Text,
- View,
- Button,
- Alert
- } from 'react-native';
- import { DataSource } from 'typeorm/browser';
- import { Category } from '@/database/entities/category';
- import { Author } from '@/database/entities/author';
- import { Post } from '@/database/entities/post';
- import * as FileSystem from 'expo-file-system'
- const database = 'test19.db' // without .db as extension is ok, but recommanded
- const dataSource = new DataSource({
- database,
- driver: require('expo-sqlite'),
- entities: [
- Category,
- Author,
- Post
- ],
- synchronize: true,
- type: "expo",
- })
- export default function SqlitePage() {
- const [progress, setProgress] = useState('')
- const [loadedPost, setLoadedPost] = useState<Post>()
- function connect() {
- return dataSource.initialize()
- }
- useEffect(() => {
- runDemo()
- }, [])
- async function runDemo() {
- const source = await connect();
- const category1 = new Category();
- category1.name = "TypeScript";
- const category2 = new Category();
- category2.name = "Programming";
- const author = new Author();
- author.name = "Person";
- const post = new Post();
- post.title = "Control flow based type analysis";
- post.text = "TypeScript 2.0 implements a control flow-based type analysis for local variables and parameters.";
- post.categories = [category1, category2];
- post.author = author;
- const postRepository = source.getRepository(Post);
- await postRepository.save(post);
- console.log("Post has been saved");
- setProgress("Post has been saved")
- const loadedPost = await postRepository.findOne({ where: { id: post.id }, relations: ["author", "categories"] });
- if (loadedPost) {
- console.log("Post has been loaded: ", loadedPost);
- setLoadedPost(loadedPost)
- }
- }
- async function checkSqliteFile() {
- const dataDirectory = FileSystem.documentDirectory || FileSystem.cacheDirectory;
- const databaseFilePath = `${dataDirectory}SQLite/${database}`
- console.log('databaseFilePath', databaseFilePath)
- try {
- const fileInfo = await FileSystem.getInfoAsync(databaseFilePath);
- const fileExists = fileInfo.exists;
- Alert.alert(`fileExists: ${fileExists}`, databaseFilePath)
- } catch (error) {
- console.error('Error getting file info:', error);
- }
- }
- return (
- <View style={styles.container}>
- <Text style={styles.welcome}>
- Welcome to the Expo Example for TypeORM!
- </Text>
- <Text style={styles.small}>
- {progress}
- </Text>
- <Text style={styles.small}>
- {JSON.stringify(loadedPost)}
- </Text>
- <Button title='If sqlite file exists' onPress={checkSqliteFile} />
- </View>
- );
- }
- const styles = StyleSheet.create({
- container: {
- flex: 1,
- justifyContent: 'center',
- alignItems: 'center',
- backgroundColor: '#F5FCFF',
- },
- welcome: {
- fontSize: 20,
- textAlign: 'center',
- margin: 10,
- },
- small: {
- textAlign: 'center',
- color: '#333333',
- marginBottom: 5,
- },
- });
复制代码
点击页面里的“If sqlite file exists”按钮,terminal log 会打印出 sqlite 数据库文件路径,按住 cmd 点击路径可以打开文件,如果你的 vscode 装了 SQLite Viewer 可以直接查看数据库内容 |
|