如何用新数据正确覆盖 SQLite 表行?

Posted

技术标签:

【中文标题】如何用新数据正确覆盖 SQLite 表行?【英文标题】:How to correctly overwrite SQLite table rows with new data? 【发布时间】:2018-05-11 20:52:52 【问题描述】:

我正在制作一个显示 10 个最新新闻头条的新闻应用程序。当 API 返回 10 篇不同的新闻文章时,它们被插入到表中而不删除当前的文章,导致数据量每次增加 10。

到目前为止,我已尝试更新行,当表中已有数据时,该行有效。我尝试删除表并重新创建它,但没有显示任何内容...

我找到的唯一解决方案是将虚拟数据插入表中并用来自 api 的数据覆盖它......最好的方法是什么?请看下面的代码。

数据库助手

public class dbHelper extends SQLiteOpenHelper 
    private static final String DATABASE_NAME="mytube";
    private static final int DATABASE_VERSION = 1;
    private static final String NEWS_TABLE = "news";
    private static final String CREATE_TABLE = "create table "+NEWS_TABLE +"(title TEXT, desc TEXT, url TEXT)";

    Context context;

    public dbHelper(Context context) 
        super(context, DATABASE_NAME, null, DATABASE_VERSION);
        this.context = context;
    

    @Override
    public void onCreate(SQLiteDatabase db) 

        db.execSQL(CREATE_TABLE);
    


    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) 

        db.execSQL("DROP TABLE IF EXISTS " + NEWS_TABLE);
        // Create tables (again)
        onCreate(db);
    
    // Insert into DB

    public void insertIntoDB(String title,String desc,String url)
        Log.d("insert data", "");

        // get reference to writable DB
        SQLiteDatabase db = this.getWritableDatabase();

        // Create ContentValues to add key
        ContentValues values = new ContentValues();
        values.put("title", title);
        values.put("desc", desc);
        values.put("url", url);


        // Insert Data
        db.insert(NEWS_TABLE, null, values);

        // Close DB
        db.close();
        Toast.makeText(context, "insert value", Toast.LENGTH_LONG);
        Log.i("", "Insert complete");
    
    /* Retrive  data from database */
    public List<DatabaseModel> getDataFromDB()
        List<DatabaseModel> modelList = new ArrayList<DatabaseModel>();
        String query = "select * from "+NEWS_TABLE;

        SQLiteDatabase db = this.getWritableDatabase();
        Cursor cursor = db.rawQuery(query,null);

        if (cursor.moveToFirst())
            do 
                DatabaseModel model = new DatabaseModel();
                model.setTitle(cursor.getString(0));
                model.setDesc(cursor.getString(1));
                model.setUrl(cursor.getString(2));

                modelList.add(model);
            while (cursor.moveToNext());
        


       // Log.d("news data", modelList.toString());


        return modelList;
    





活动

public class journeyEntertainment extends AppCompatActivity 

    dbHelper helper;
    List<DatabaseModel> dbList;
    RecyclerView mRecyclerView;
    private RecyclerView.Adapter mAdapter;
    private RecyclerView.LayoutManager mLayoutManager;

    @Override
    protected void onCreate(Bundle savedInstanceState) 
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_journey_entertainment);
       /* Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);
        getSupportActionBar().setDisplayHomeAsUpEnabled(true);*/

        getNews();
        helper = new dbHelper(this);
        dbList= new ArrayList<DatabaseModel>();

        dbList = helper.getDataFromDB();

        mRecyclerView = (RecyclerView)findViewById(R.id.recycleview);

        mRecyclerView.setHasFixedSize(true);

        // use a linear layout manager
        mLayoutManager = new LinearLayoutManager(this);
        mRecyclerView.setLayoutManager(mLayoutManager);

        // specify an adapter (see also next example)
        mAdapter = new RecyclerAdapter(this,dbList);
        mRecyclerView.setAdapter(mAdapter);



    

    @Override
    public boolean onCreateOptionsMenu(Menu menu) 
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.menu_second, menu);
        return true;
    



    @Override
    public boolean onOptionsItemSelected(MenuItem item) 
        switch (item.getItemId()) 
            case android.R.id.home:
                finish();
                return true;
        
        return super.onOptionsItemSelected(item);
    


    public void getNews()
        RequestQueue queue = Volley.newRequestQueue(this);
        String url = "https://newsapi.org/v2/top-headlines?sources=bbc-news&apiKey=927e06d9dddb47ee929c9bb7597777055434";

        final StringRequest stringRequest = new StringRequest(url, new Response.Listener<String>() 
            @Override
            public void onResponse(String response) 
                try 
                    JSONObject jsonObject = new JSONObject(response);
                    JSONArray jsonArray = jsonObject.getJSONArray("articles");
                    for (int i = 0; i < jsonArray.length(); i++) 
                        JSONObject jo = jsonArray.getJSONObject(i);

                        String title = jo.getString("title");
                        String  desc = jo.getString("description");
                        String  url = jo.getString("url");

                        title = title.replaceAll("'", "");
                        desc = desc.replaceAll("'", "");
                        url = url.replaceAll("'", "");





                        helper = new dbHelper(journeyEntertainment.this);
                        helper.insertIntoDB(title, desc, url);


                    

                 catch (JSONException e) 

                

            

        , new Response.ErrorListener() 
            @Override
            public void onErrorResponse(VolleyError error) 


            
        );

        RequestQueue requestQueue = Volley.newRequestQueue(getApplicationContext());
        requestQueue.add(stringRequest);
    

【问题讨论】:

用新值更新旧值,而不是每次都插入新行。 但是在应用程序第一次运行时不会有要更新的值。 您可以在创建表格时使用默认值 为什么不能删除旧的? 【参考方案1】:

1) 将以下方法添加到您的dbHelper(这将删除表中的所有行);

public void removeAllRowsFromNewsTable()
    Log.d("insert data", "");

    // get reference to writable DB
    SQLiteDatabase db = this.getWritableDatabase();
    db.delete(NEWS_TABLE,null,null);

2) 在您的getNews 方法中修改:-

                    helper = new dbHelper(journeyEntertainment.this);
                    helper.insertIntoDB(title, desc, url);

到:-

                    helper = new dbHelper(journeyEntertainment.this);
                    helper.removeAllRowsFromNewsTable();
                    helper.insertIntoDB(title, desc, url);

【讨论】:

谢谢!但是,我以前尝试过类似的方法,它删除了除了表中的第一个条目之外的所有内容 破解了!移动'helper.removeAllRowsFromNewsTable();'到 for 循环上方...现在效果很好。谢谢@MikeT

以上是关于如何用新数据正确覆盖 SQLite 表行?的主要内容,如果未能解决你的问题,请参考以下文章

如果我使用核心数据,如何用新文件替换 sqlite 文件?

SQL如何用一条SQL语句更新表行

grafna如何用新的dashbord覆盖旧的dashbord

如何用新加密的数据更新部分加密数据?

如何用Entity Framework 6 连接Sqlite数据库

如何用新文件覆盖 log4j2.xml 中指定的日志文件名?