【问题标题】:Prevent repetitive value from being inserted into database android防止重复值插入数据库android
【发布时间】:2021-12-28 05:48:02
【问题描述】:

这是我的代码:

    final String[] names_list = { "apple", "banana", "orange" };
    final int[] preview_list = { "R.drawable.apple", "R.drawable.banana", "R.drawable.orange" };
    final int[] colors_list = { "red", "yellow", "orange" };
    int random = (int) (Math.random() * 3);
    String name= names_list[random];
    int preview= preview_list[random];
    int color= colors_list[random];
    helper = new DatabaseHelper(getApplicationContext());
    helper.insertIntoDB(name, preview, color);

事实证明( int random = (int) (Math.random() * 3); )代码生成一个从 1 到 3 的随机数(取决于每个列表中数组的计数),然后例如如果变量 random 为 1,DatabaseHelper 将数组列表的第一个数组插入数据库(“apple”、“R.drawable.apple”和“red”),而 names_list 数组列表中的数组“apple”将作为主要唯一值插入.我的问题是,我可以做些什么来防止我的程序将重复数据插入数据库,例如,如果变量 random 第二次变为 1 程序忽略它并生成一个新的变量随机数。

这里是数据库模型:

public class DatabaseModel {
private String name;
private int preview;
private int color;

public String getName() {
    return name;
}
public void setName(String name) {
    this.name = name;
}
public int getPreview() {
    return preview;
}
public void setPreview(int preview) {
    this.preview = preview;
}
public int getColor() {
    return color;
}
public void setColor(int color) {
    this.color = color;
}

和数据库助手

public class DatabaseHelper extends SQLiteOpenHelper {
private static final String DATABASE_NAME="fruits";
private static final int DATABASE_VERSION = 1;
private static final String FRUITS_TABLE = "fruitsreg";
private static final String FS_TABLE = "create table "+FRUITS_TABLE +"(name TEXT primary key,preview TEXT, color TEXT)";
Context context;
public DatabaseHelper(Context context) {
    super(context, DATABASE_NAME, null, DATABASE_VERSION);
    this.context = context;
}
@Override
public void onCreate(SQLiteDatabase db) {
    db.execSQL(FS_TABLE);
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
    db.execSQL("DROP TABLE IF EXISTS " + FRUITS_TABLE);
    // Create tables again
    onCreate(db);
}
/* Insert into database*/
public void insertIntoDB(String name, int preview, int color){
    Log.d("insert", "before insert");
    // 1. get reference to writable DB
    SQLiteDatabase db = this.getWritableDatabase();
    // 2. create ContentValues to add key "column"/value
    ContentValues values = new ContentValues();
    values.put("name", name);
    values.put("preview", String.valueOf(preview));
    values.put("color", color);
    // 3. insert
    db.insert(FRUITS_TABLE, null, values);
    // 4. close
    db.close();
    Toast.makeText(context, "insert value", Toast.LENGTH_LONG);
    Log.i("insert into DB", "After insert");
}
/* Retrive  data from database */
public List<DatabaseModel> getDataFromDB(){
    List<DatabaseModel> modelList = new ArrayList<DatabaseModel>();
    String query = "select * from "+FRUITS_TABLE;
    SQLiteDatabase db = this.getWritableDatabase();
    Cursor cursor = db.rawQuery(query,null);
    if (cursor.moveToFirst()){
        do {
            DatabaseModel model = new DatabaseModel();
            model.setName(cursor.getString(0));
            model.setPreview(cursor.getInt(1));
            model.setColor(cursor.getInt(2));
            modelList.add(model);
        }while (cursor.moveToNext());
    }
    Log.d("Fruits database data", modelList.toString());
    return modelList;
}

【问题讨论】:

  • 可以发一下insertIntoDB函数的代码吗?
  • 我不是一个好的解决方案,但您可以使用临时列表和大小创建一个随机数。当你插入一个项目,然后删除临时列表的项目并重复这个过程,现在大小是 2,最后是 1。
  • @Luca Pizzini 我会尽快发布
  • @Luca Pizzini 嘿朋友我更新了帖子如果你不介意可以帮忙吗?

标签: android android-sqlite android-database


【解决方案1】:

我的问题是,我可以做些什么来防止我的程序将重复数据插入数据库,例如如果变量 random 第二次变为 1 程序忽略它。

要检查是否存在,您必须查询数据库以确定哪些存在和不存在。通过诸如

之类的查询
SELECT * FROM fruitsreg WHERE name = 'name';

但是。我建议您不要阻止尝试插入,而是检查 insert 方法的结果。 insert 方法根据 新插入行的行 ID 返回一个 long,如果发生错误则返回 -1

  • 如果尝试插入现有的 PRIMARY KEY 值,则错误将导致返回 -1。

  • 您可能会质疑但我的主要值是一个字符串我没有声明一个Id列。 SQLite 除非使用 WITHOUT ROWID 子句定义表,否则总是有一个列名 rowid 这是一个唯一的整数值(1,然后可能是 2,然后可能是 3 ....)。如果无法插入行,则返回此值或 -1。

因此,只需对您的 insertIntoDB 方法稍作改动,即可检测该行是否已插入。从而避免了插入前查询的需要。

所以也许考虑一下:-

/* Insert into database*/
public long insertIntoDB(String name, int preview, int color) {
    Log.d("insert", "before insert");
    // 1. get reference to writable DB
    SQLiteDatabase db = this.getWritableDatabase();
    // 2. create ContentValues to add key "column"/value
    ContentValues values = new ContentValues();
    values.put("name", name);
    values.put("preview", String.valueOf(preview));
    values.put("color", color);
    // 3. insert
    long rv = db.insert(FRUITS_TABLE, null, values);
    // 4. close
    db.close();
    Toast.makeText(context, "insert value", Toast.LENGTH_LONG);
    Log.i("insert into DB", "After insert");
    return rv;
}

并生成一个新的可变随机数

然后可以根据您的代码的这种改编来利用上述内容(在演示活动中):-

public class MainActivity extends AppCompatActivity {

    DatabaseHelper helper;
    final String[] names_list = { "apple", "banana", "orange" };
    final int[] preview_list = { /*"R.drawable.apple"*/ 100, /*"R.drawable.banana"*/ 200, /*"R.drawable.orange"*/ 300};
    final int[] colors_list = { /*"red"*/ 0xff0000, /*"yellow"*/ 0xFFFF0, /*"orange"*/ 0xFFa500};

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        helper = new DatabaseHelper(getApplicationContext());

        /* Try inserting 5 times */
        for(int i=0;i < 5; i++) {
            myCode();
        }

        for(DatabaseModel d: helper.getDataFromDB()) {
            Log.d("APPLOG","Name is " + d.getName() + " Preview is " + d.getPreview() + " Color is " + d.getColor() );
        }
    }

    private void myCode() {
        //Here is my code:
        //int random = (int) (Math.random() * 3);
        int random = (int) (Math.random() * names_list.length);
        int limit =0;
        while (
                helper.insertIntoDB(
                        names_list[random],
                        preview_list[random],
                        colors_list[random]
                )
                        < 0 /*( if insert is ok will be 1 or greater)*/
                        && limit++ < names_list.length /* limit the number of attempts */
        ) {
            random = (int) (Math.random() * names_list.length); /* next random value */
        }
        Log.d("APPLOG"," tried " + limit + " retires to insert.");
    }
}
  • 注意资源 ID 的值

因此运行上述程序,从新安装开始,将有 5 次尝试插入 3 种可能的行,因为有 3 种颜色。

无法保证所有 3 行都会插入,因为尝试使用可能与以前一样的随机数可能会插入更少的行。

一个示例运行可能会在日志中产生以下内容:-

D/APPLOG:  tried 0 times to insert.
D/APPLOG:  tried 2 times to insert.
D/APPLOG:  tried 0 times to insert.
D/APPLOG:  tried 4 times to insert.
D/APPLOG:  tried 4 times to insert.
D/APPLOG: Name is orange Preview is 300 Color is 16753920
D/APPLOG: Name is banana Preview is 200 Color is 1048560
D/APPLOG: Name is apple Preview is 100 Color is 16711680

所以

  • 在第一次尝试时插入了 5 行中的 1 次(重试 0 次)。
  • 在第三次尝试(2 次重试)时插入了 5 行中的 2 次尝试。
    • 所以尝试 1 和尝试 2 都生成了与尝试 1 中使用的相同的随机数
  • 在第一次尝试时插入了 5 行中的 3 次(重试 0 次)。
    • 所以现在所有三行都已插入。
  • 5 次尝试中的 4 次未在超过重试限制之前插入行。
  • 5 次尝试中的 5 次未在超出重试限制之前插入行。

除了上述之外,使用 Android Studio 的 App Inspection 数据库是:-

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-10-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-08-14
    • 1970-01-01
    • 2018-06-29
    • 2016-04-11
    相关资源
    最近更新 更多