HelloWorld 发表于 2024-2-23 23:58:25

typeorm 在 expo app 里的使用示例

本帖最后由 HelloWorld 于 2025-1-5 11:54 编辑

最近在写个 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 = useState('')
const = 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 = ;
    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 可以直接查看数据库内容
页: [1]
查看完整版本: typeorm 在 expo app 里的使用示例