在我的CRUD Flutter应用中使用sqflite插件获取错误

时间:2018-09-17 14:00:35

标签: database sqlite flutter crud

我是Flutter的超级菜鸟,我正在尝试“琐碎的”(对于其他所有人) CRUD应用程序,因此我遵循了一些教程

https://grokonez.com/android/flutter-sqlite-example-listview-crud-operations-sqflite-plugin

他的“版本”显然有效,当然我的无效。 我收到此错误:https://i.stack.imgur.com/TM893.png

这是“我的”代码,我猜其中涉及的部分是DBHelper和TicketScreen:

  class DatabaseHelper {
  static final DatabaseHelper _instance = new DatabaseHelper.internal();

  factory DatabaseHelper() => _instance;

  final String ticketTable = 'ticketTable';
  final String columnId = 'id';
  final String columnDay = 'day';
  final String columnMonth = 'month';
  final String columnYear = 'year';
  final String columnFrom = 'from';
  final String columnTo = 'to';
  final String columnAircraft = 'aircraft';
  final String columnAirline = 'airline';

  static Database _db;

  DatabaseHelper.internal();

  Future<Database> get db async {
    if (_db != null) {
      return _db;
    }
    _db = await initDb();

    return _db;
  }

  initDb() async {
    String databasesPath = await getDatabasesPath();
    String path = join(databasesPath, 'ticket.db');
    var db = await openDatabase(path, version: 1, onCreate: _onCreate);
    return db;
  }

  void _onCreate(Database db, int newVersion) async {
    await db.execute(
        'CREATE TABLE $ticketTable($columnId INTEGER PRIMARY KEY, $columnDay TEXT, $columnMonth TEXT, $columnYear TEXT, $columnFrom TEXT, $columnTo TEXT, $columnAircraft TEXT, $columnAirline TEXT)');
  }

  Future<int> saveTicket(Ticket ticket) async {
    var dbClient = await db;
    var result = await dbClient.insert(ticketTable, ticket.toMap());
    return result;
  }

  Future<List> getAllTickets() async {
    var dbClient = await db;
    var result = await dbClient.query(ticketTable, columns: [
      columnId,
      columnDay,
      columnMonth,
      columnYear,
      columnFrom,
      columnTo,
      columnAircraft,
      columnAirline
    ]);
    return result.toList();
  }

  Future<int> getCount() async {
    var dbClient = await db;
    return Sqflite.firstIntValue(
        await dbClient.rawQuery('SELECT COUNT(*) FROM $ticketTable'));
  }

  Future<Ticket> getTicket(int id) async {
    var dbClient = await db;
    List<Map> result = await dbClient.query(ticketTable,
        columns: [
          columnId,
          columnDay,
          columnMonth,
          columnYear,
          columnFrom,
          columnTo,
          columnAircraft,
          columnAirline
        ],
        where: '$columnId = ?',
        whereArgs: [id]);
    if (result.length > 0) {
      return new Ticket.fromMap(result.first);
    }
    return null;
  }

  Future<int> deleteTicket(int id) async {
    var dbClient = await db;
    return await dbClient
        .delete(ticketTable, where: '$columnId = ?', whereArgs: [id]);
  }

  Future<int> updateTicket(Ticket ticket) async {
    var dbClient = await db;
    return await dbClient.update(ticketTable, ticket.toMap(),
        where: "$columnId = ?", whereArgs: [ticket.id]);
  }

  Future close() async {
    var dbClient = await db;
    return dbClient.close();
  }
}


 class TicketScreen extends StatefulWidget {
  final Ticket ticket;
  TicketScreen(this.ticket);

  @override
  State<StatefulWidget> createState() => new _TicketScreenState();
}

class _TicketScreenState extends State<TicketScreen> {
  DatabaseHelper db = new DatabaseHelper();

  TextEditingController _dayController;
  TextEditingController _monthController;
  TextEditingController _yearController;
  TextEditingController _fromController;
  TextEditingController _toController;
  TextEditingController _aircraftController;
  TextEditingController _airlineController;

  @override
  void initState() {
    super.initState();
    _dayController = new TextEditingController(text: widget.ticket.day);
    _monthController = new TextEditingController(text: widget.ticket.month);
    _yearController = new TextEditingController(text: widget.ticket.year);
    _fromController = new TextEditingController(text: widget.ticket.from);
    _toController = new TextEditingController(text: widget.ticket.to);
    _aircraftController = new TextEditingController(text: widget.ticket.aircraft);
    _airlineController = new TextEditingController(text: widget.ticket.airline);
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text('Ticket')),
      body: Container(
        margin: EdgeInsets.all(15.0),
        alignment: Alignment.center,
        child: Column(
          children: <Widget>[
            Text('Travel Date',
              style: new TextStyle(fontWeight: FontWeight.bold),
            ),
            Row(
              children: <Widget>[
          Container(
            alignment: Alignment.center, 
            width: 80.0,
                child: TextField(
                  maxLength: 2,
                  keyboardType: TextInputType.number,
                  controller: _dayController,
                  decoration: InputDecoration(labelText: 'Day'),
                ),
          ),
                Text(' / '),
      Container(
        width: 80.0,
        child: TextField(
                  maxLength: 2,
                  keyboardType: TextInputType.number,
                  controller: _monthController,
                  decoration: InputDecoration(labelText: 'Month'),
                ),
      ),
                Text(' / '),
      Container(
        width: 160.0,
        child: TextField(
                  maxLength: 4,
                  keyboardType: TextInputType.number,
                  controller: _yearController,
                  decoration: InputDecoration(labelText: 'Year'),
                ),
        ),
              ],
            ),
            Padding(padding: new EdgeInsets.all(5.0)),
            Row(
              children: <Widget>[
                Container(
                  width: 160.0,
                  child: TextField(
                  controller: _fromController,
                  decoration: InputDecoration(labelText: 'From'),
                ),
                ),
                Container(
                  width: 160.0,
                  child: TextField(
                  controller: _toController,
                  decoration: InputDecoration(labelText: 'To'),
                ),
                ),
              ],
            ),
            Padding(padding: new EdgeInsets.all(5.0)),
            Row(
              children: <Widget>[
                Container(
                  width: 160.0,
                  child: TextField(
                  controller: _aircraftController,
                  decoration: InputDecoration(labelText: 'Aircraft'),
                ),
                ),
                Container(
                  width: 160.0,
                  child: TextField(
                  controller: _airlineController,
                  decoration: InputDecoration(labelText: 'Airline'),
                ),
                ),
              ],
            ),
            Padding(padding: new EdgeInsets.all(5.0)),
            RaisedButton(
              child: (widget.ticket.id != null) ? Text('Update') : Text('Add'),
              onPressed: () {
                if (widget.ticket.id != null) {
                  db
                      .updateTicket(Ticket.fromMap({
                    'id': widget.ticket.id,
                    'day': _dayController.text,
                    'year': _yearController.text,
                    'from': _fromController.text,
                    'to': _toController.text,
                    'aircraft': _aircraftController.text,
                    'airline': _airlineController.text
                  }))
                      .then((_) {
                    Navigator.pop(context, 'update');
                  });
                } else {
                  db
                      .saveTicket(Ticket(
                          _dayController.text,
                          _monthController.text,
                          _yearController.text,
                          _fromController.text,
                          _toController.text,
                          _aircraftController.text,
                          _airlineController.text))
                      .then((_) {
                    Navigator.pop(context, 'save');
                  });
                }
              },
            ),
          ],
        ),
      ),
    );
  }
}

然后是其他一些东西,但我倾向于排除它们是问题的根源

    class MyListView extends StatefulWidget {
  @override
  _ListViewState createState() => new _ListViewState();
}

class _ListViewState extends State<MyListView> {
  List<Ticket> items = new List();
  DatabaseHelper db = new DatabaseHelper();

  @override
  void initState() {
    super.initState();

    db.getAllTickets().then((tickets) {
      setState(() {
        tickets.forEach((ticket) {
          items.add(Ticket.fromMap(ticket));
        });
      });
    });
  }

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Ticket List',
      home: Scaffold(
        appBar: AppBar(
          title: Text('Ticket List'),
          centerTitle: true,
          backgroundColor: Colors.blue,
        ),
        body: Center(
          child: ListView.builder(
              itemCount: items.length,
              padding: const EdgeInsets.all(15.0),
              itemBuilder: (context, position) {
                return Column(
                  children: <Widget>[
                    Divider(height: 5.0),
                    ListTile(
                      title: Text(
                        'From ${items[position].from} to ${items[position].to}',
                        style: TextStyle(
                          fontSize: 22.0,
                          color: Colors.deepOrangeAccent,
                        ),
                      ),
                      subtitle:
                        Text(
                          'Operated by ${items[position].airline} with  ${items[position].aircraft} ',
                          style: new TextStyle(
                            fontSize: 18.0,
                            fontStyle: FontStyle.italic,
                          ),
                        ),
                      leading: Column(
                        children: <Widget>[
                          Padding(padding: EdgeInsets.all(10.0)),
                          CircleAvatar(
                            backgroundColor: Colors.blueAccent,
                            radius: 20.0,
                            child: Text(
                              '${items[position].day}/${items[position].month}/${items[position].year}',
                              style: TextStyle(
                                fontSize: 22.0,
                                color: Colors.white,
                              ),
                            ),
                          ),
                          IconButton(
                              icon: const Icon(Icons.remove_circle_outline),
                              onPressed: () => _deleteTicket(context, items[position], position)
                          ),
                        ],
                      ),
                      onTap: () => _navigateToTicket(context, items[position]),
                    ),
                  ],
                );
              }),
        ),
        floatingActionButton: FloatingActionButton(
          child: Icon(Icons.add),
          onPressed: () => _createNewTicket(context),
        ),
      ),
    );
  }

  void _deleteTicket(BuildContext context, Ticket ticket, int position) async {
    db.deleteTicket(ticket.id).then((tickets) {
      setState(() {
        items.removeAt(position);
      });
    });
  }

  void _navigateToTicket(BuildContext context, Ticket ticket) async {
    String result = await Navigator.push(
      context,
      MaterialPageRoute(builder: (context) => TicketScreen(ticket)),
    );

    if (result == 'update') {
      db.getAllTickets().then((tickets) {
        setState(() {
          items.clear();
          tickets.forEach((ticket) {
            items.add(Ticket.fromMap(ticket));
          });
        });
      });
    }
  }

  void _createNewTicket(BuildContext context) async {
    String result = await Navigator.push(
      context,
      MaterialPageRoute(builder: (context) => TicketScreen(Ticket('', '', '', '', '', '', ''))),
    );

    if (result == 'save') {
      db.getAllTickets().then((tickets) {
        setState(() {
          items.clear();
          tickets.forEach((ticket) {
            items.add(Ticket.fromMap(ticket));
          });
        });
      });
    }
  }
}


  class Ticket {
  int _id;
  String _day;
  String _month;
  String _year;
  String _from;
  String _to;
  String _aircraft;
  String _airline;



  Ticket(this._day, this._month, this._year, this._from, this._to, this._aircraft, this._airline);

  Ticket.map(dynamic obj) {
    this._id = obj['id'];
    this._day = obj['day'];
    this._month = obj['month'];
    this._year = obj['year'];
    this._from = obj['form'];
    this._to = obj['to'];
    this._aircraft = obj['aircraft'];
    this._airline = obj['airline'];
  }

  int get id => _id;
  String get day => _day;
  String get month => _month;
  String get year => _year;
  String get from => _from;
  String get to =>_to;
  String get aircraft =>_aircraft;
  String get airline => _airline;

  Map<String, dynamic> toMap() {
    var map = new Map<String, dynamic>();
    if (_id != null) {
      map['id'] = _id;
    }
    map['day'] = _day;
    map['month'] = _month;
    map['year'] = _year;
    map['from'] = _from;
    map['to'] = _to;
    map['aircraft'] = _aircraft;
    map['airline'] = _airline;

    return map;
  }

  Ticket.fromMap(Map<String, dynamic> map) {
    this._id = map['id'];
    this._day = map['day'];
    this._month = map['month'];
    this._year = map['year'];
    this._from =  map['from'];
    this._to = map['to'];
    this._aircraft = map['aircraft'];
    this._airline = map['airline'];
  }
}


  void main() => runApp(
  MaterialApp(
    title: 'Returning Data',
    home: MyListView(),
  ),
);

那么,你能告诉我我做错了什么吗? 预先谢谢你

奖金问题: 我不喜欢SQL, 有没有其他可供选择的分贝? 我的意思是真正的数据库,不是将数据保存在sharedpref或使用Firebase, 我喜欢领域,但看起来好像没有动静。

再次感谢

1 个答案:

答案 0 :(得分:1)

问题是您在列名中使用了保留关键字'From',同时还使用了'To'

'CREATE TABLE $ticketTable($columnId INTEGER PRIMARY KEY, $columnDay TEXT, $columnMonth TEXT, $columnYear TEXT, $columnFrom TEXT, $columnTo TEXT, $columnAircraft TEXT, $columnAirline TEXT)');

因此,本质上您是在要求它创建一个名为TicketTable的表,该表具有以下列名-id,day,month,year ..,其中包含这些特定的数据类型。但是,当到达名为“ from”的列时,它认为您想从名为“ Text”的表中创建一个空值(因为列名不存在),这没有任何意义。

以下是您应避免使用的关键字列表-https://docs.oracle.com/database/121/SQLRF/ap_keywd001.htm#SQLRF55621

您也许可以通过用双引号将变量引起来来解决此问题,但是您必须自己进行测试。