Почему Anko не может игнорировать переданное значение _id, когда _id имеет значение INTEGER + PRIMARY_KEY+ AUTOINCREMENT?

Я разработал поле _id INTEGER + PRIMARY_KEY+ AUTOINCREMENT, я использую код SettingManage().addSetting(MSetting(10L,"My Settings",2000L,"This is description!")) для вставки записи в таблицу.

Я думаю, что Anko проигнорирует переданное значение 10 _id и автоматически передаст новое значение _id, но на самом деле значение 10 _id вставляется в таблицу.

Как заставить Anko игнорировать переданное значение _id, когда _id равно INTEGER + PRIMARY_KEY+ AUTOINCREMENT?

Вставить данные

SettingManage().addSetting(MSetting(10L,"My Settings",2000L,"This is description!"))

Таблица макетов

    class DBSettingHelper(mContext: Context = UIApp.instance) : ManagedSQLiteOpenHelper(
            mContext,
            DB_NAME,
            null,
            DB_VERSION) {

        companion object {
            val DB_NAME = "setting.db"
            val DB_VERSION = 5
            val instance by lazy { DBSettingHelper() }
        }

        override fun onCreate(db: SQLiteDatabase) {
            db.createTable( DBSettingTable.TableNAME , true,
                    DBSettingTable._ID to INTEGER + PRIMARY_KEY+ AUTOINCREMENT ,
                    DBSettingTable.Name to TEXT,
                    DBSettingTable.CreatedDate to INTEGER,
                    DBSettingTable.Description to TEXT
            )
        }

        override fun onUpgrade(db: SQLiteDatabase, oldVersion: Int, newVersion: Int) {
            db.dropTable(DBSettingTable.TableNAME, true)
            onCreate(db)
        }

    }



    class DBSetting(val mMutableMap: MutableMap<String, Any?>) {
        var _id: Long by mMutableMap
        var name: String by mMutableMap
        var createdDate: Long by mMutableMap
        var description: String by mMutableMap

        constructor(_id: Long, name: String, createdDate: Long, description: String)
                : this(HashMap()) {
            this._id = _id
            this.name = name
            this.createdDate = createdDate
            this.description=description
        }
    }


    object DBSettingTable {
        val TableNAME = "SettingTable"

        val _ID = "_id"
        val Name = "name"
        val CreatedDate = "createdDate"
        val Description="description"
    }


   data class MSetting (
        val _id: Long,  
        val name: String,
        val createdDate: Long,
        val description: String
   )

Бизнес-логика

class SettingManage {
    fun addSetting(mMSetting:MSetting){
        DBSettingManage().addDBSetting(DbDataMapper().convertMSetting_To_DBSetting(mMSetting))
    }
}

class DBSettingManage(private val mDBSettingHelper: DBSettingHelper =DBSettingHelper.instance) {
    fun addDBSetting(mDBSetting: DBSetting)=mDBSettingHelper.use{
        insert(DBSettingTable.TableNAME,*mDBSetting.mMutableMap.toVarargArray())
    }
}

class DbDataMapper {
    fun convertMSetting_To_DBSetting(mMSetting: MSetting) =with(mMSetting){
        DBSetting(_id,name,createdDate,description)
    }
    fun convertDBSetting_To_MSetting(mDBSetting: DBSetting)=with(mDBSetting){
        MSetting(_id,name,createdDate,description )
    }
}


fun <T : Any> SelectQueryBuilder.parseList(parser: (Map<String, Any?>) -> T): List<T> =
        parseList(object : MapRowParser<T> {
            override fun parseRow(columns: Map<String, Any?>): T = parser(columns)
        })

person HelloCW    schedule 15.11.2017    source источник
comment
Просто проверяю, правильно ли я понял: вы хотите, чтобы anko игнорировал значение, переданное как _id, когда это первичный ключ с автоматическим увеличением?   -  person Zoe    schedule 17.11.2017
comment
Да! Я хочу, чтобы anko игнорировал значение, переданное как _id, когда это первичный ключ с автоматическим увеличением.   -  person HelloCW    schedule 17.11.2017
comment
Я должен поместить свойство _id в класс DBSetting(val mMutableMap: MutableMap<String, Any?>)..., потому что мне нужно значение _id, когда я получаю запись из таблицы. Но когда я вставляю новую запись в таблицу, я надеюсь, что система сможет автоматически передать неповторяющееся значение в поле _id, когда поле _id равно INTEGER + PRIMARY_KEY+ AUTOINCREMENT   -  person HelloCW    schedule 17.11.2017
comment
нужно провести дополнительные исследования, если это так. Я обновлю ответ, когда найду что-нибудь   -  person Zoe    schedule 17.11.2017
comment
Не знаю насчет анко, но вообще с sqlite: вставьте null в те столбцы, где вы хотите видеть значение по умолчанию.   -  person laalto    schedule 18.11.2017
comment
@laalto при условии, что столбец может иметь значение NULL. Целые числа с автоматическим приращением могут быть автоматически увеличены без передачи значения   -  person Zoe    schedule 18.11.2017


Ответы (1)


Anko, в вашем использовании, является оболочкой для SQLite. Сам SQL переопределяет автоматическое увеличение, когда передается пользовательское значение. Если значение не передано -> Автоматическое значение. В противном случае -> вручную. Предполагается, что он уникален из-за PRIMARY_KEY, но это другая проблема.

Насколько мне известно, в Anko нет встроенной функции, позволяющей переопределить это вручную. Вместо этого единственное, что вы можете сделать, это не передавать значение. Любой неправильный SQL-запрос будет обнаружен не самим Anko, а необработанным SQL. Это SQL, который генерирует любые исключения, что означает, что Anko не будет проверять отсутствующие данные.

Просто не передавайте идентификатор. Вы можете написать функцию, которая по-прежнему принимает идентификатор, но отбрасывает его, если для строки установлено значение PRIMARY_KEY и AUTO_INCREMENT.


Я сделал больше копания в исходном коде, и нет поддержки игнорирования переданных значений, если для него установлено автоматическое увеличение.

Это означает, что единственный способ заставить его автоматически увеличиваться — не передавать никаких значений. Если вы используете ручные запросы любого типа, вы просто не передаете никакого значения. Итак, не давайте базе данных идентификатор. Поскольку это автоматическое увеличение, оно автоматически добавит его, и это на базовом уровне SQL.

Ank не игнорирует его по умолчанию, потому что по сути это оболочка для SQLite. Это означает, что его нужно передать, если идентификатор должен быть переопределен (см. ссылку во втором предложении этого ответа). Таким образом, игнорирование Анко вызовет больше проблем, чем пользы. Вы должны убедиться, что он не передан вместо этого

person Zoe    schedule 17.11.2017
comment
Работает нормально @zoe - person InsaneCat; 20.11.2017