GreenDao IndsertOrReplaceInTx вставить только последний элемент списка
У меня есть несколько POJOS и создать несколько таблиц для них. Все они работают хорошо, что означает, что я могу вставить их и загрузить их... кроме этого:
Мой список брендов содержит 6 элементов, и я действительно уверен, что они разные (поставьте точку останова и увидели их), но когда я собираюсь вставить их в БД, greenDao
вставлен только последний элемент. Моя таблица пуста, и это утверждение предполагает ее заполнение.
коды:
public class SingletonDatabase {
private static SingletonDatabase mInstance;
private DaoMaster.OpenHelper mHelper;
private DaoSession mDaoSessionForUI;
private DaoMaster mDaoMaster;
private static Context mCtx;
private SingletonDatabase(Context context) {
mCtx = context;
setupDb();
}
public static synchronized SingletonDatabase getInstance(Context context) {
if (mInstance == null) {
mInstance = new SingletonDatabase(context);
}
return mInstance;
}
private void setupDb() {
mHelper = new DaoMaster.OpenHelper(
mCtx.getApplicationContext(), "mydb", null) {
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion,
int newVersion) {
// Handle upgrade
}
};
SQLiteDatabase db = mHelper.getWritableDatabase();
mDaoMaster = new DaoMaster(db);
mDaoSessionForUI = mDaoMaster.newSession();
}
public DaoSession getDaoSessionForUI() {
return mDaoSessionForUI;
}
public DaoSession getDaoSeesion(){
return mDaoMaster.newSession();
}
}
Сгенерированный код бренда:
* Entity mapped to table BRAND.
*/
public class Brand {
private long tableId;
private String id;
private String name;
private String publicImage;
private String description;
private String lastDownloadedTime;
public Brand() {
}
public Brand(long tableId) {
this.tableId = tableId;
}
public Brand(long tableId, String id, String name, String publicImage, String description, String lastDownloadedTime) {
this.tableId = tableId;
this.id = id;
this.name = name;
this.publicImage = publicImage;
this.description = description;
this.lastDownloadedTime = lastDownloadedTime;
}
public long getTableId() {
return tableId;
}
public void setTableId(long tableId) {
this.tableId = tableId;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getPublicImage() {
return publicImage;
}
public void setPublicImage(String publicImage) {
this.publicImage = publicImage;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public String getLastDownloadedTime() {
return lastDownloadedTime;
}
public void setLastDownloadedTime(String lastDownloadedTime) {
this.lastDownloadedTime = lastDownloadedTime;
}
}
Код для создания схемы:
public class DaoGen {
public static void main(String[] args) throws Exception {
Schema schema = new Schema(1, "com.mmlooloo");
Entity brandList = addBrand(schema);
File f = new File("src-gen");
f.mkdir();
new DaoGenerator().generateAll(schema,f.getAbsolutePath());
}
private static Entity addBrand(Schema schema) {
Entity brand = schema.addEntity("Brand");
brand.addLongProperty("tableId").notNull().primaryKey().autoincrement();
brand.addStringProperty("id");
brand.addStringProperty("name");
brand.addStringProperty("publicImage");
brand.addStringProperty("description");
brand.addStringProperty("lastDownloadedTime");
return brand;
}
}
и наконец как я их вставляю:
public class BrandDownloadService extends IntentService {
public BrandDownloadService() {
super("BrandDownloadService");
}
@Override
protected void onHandleIntent(Intent intent) {
....
BrandDao brandDao = SingletonDatabase.getInstance(this).getDaoSeesion().getBrandDao();
brandDao.insertOrReplaceInTx(brandList,true);
}
Я устанавливаю точку останова и проверяю brandlist
и имеет 6 элементов.
Любая помощь, обойти, отладить советы... Я действительно не знаю, в чем проблема.
Большое спасибо!!
РЕДАКТИРОВАТЬ:
Я создал очень очень простой (очень простой, поверьте мне:-)) тестовый проект, который читает json из файла, анализирует его в списке и вставляет его в db, и проблема существует. Может кто-нибудь сказать мне, в чем моя ошибка? большое большое спасибо:-).
1 ответ
Вероятно, ваши 6 элементов бренда находятся в одной таблице. Таким образом, greendao считает, что это один элемент (идентифицируемый первичным ключом) и заменяет первый на второй, второй на третий и так далее...
Если вы использовалиnotNull().primaryKey().autoincrement()
Однажды у меня возникла та же проблема, и я "исправил" ее, изменив dao-шаблон, который используется для генерации кода в проекте dao-generator.
Возможно, это также будет работать, если вы не используете notNull()
на свойство первичного ключа.
ОБНОВИТЬ
Я снова посмотрел на greendao:
В greendao-генератор, файл src-template/dao.ftl
Вы можете найти следующие строки:
protected void bindValues(SQLiteStatement stmt, ${entity.className} entity) {
stmt.clearBindings();
<#list entity.properties as property>
<#if property.notNull || entity.protobuf>
<#if entity.protobuf>
if(entity.has${property.propertyName?cap_first}()) {
</#if> stmt.bind${toBindType[property.propertyType]}(${property_index + 1}, entity.get${property.propertyName?cap_first}()<#if
property.propertyType == "Boolean"> ? 1l: 0l</#if><#if property.propertyType == "Date">.getTime()</#if>);
Это означает, что если вы используете notNull()
на ваше autoincrement
-свойство соответствующая переменная всегда будет привязана к вставке или обновлению операторов. Это приводит к тому, что вы всегда устанавливаете значение для вашего первичного ключа вручную и игнорируете autoincrement
, поскольку
CREATE TABLE mytable ( id integer primary key autoincrement, details varchar(30));
INSERT INTO mytable (id, details) VALUES (0, 'something');
Результаты в этой строке базы данных: 0 | 'something'
,
Следовательно, это ошибка внутри greendao! Для решения этой проблемы вы можете либо не указывать notNull
на вашем столбце первичного ключа или вы можете изменить файл dao.ftl
(строка 126ff):
<#list entity.properties as property>
<#if property.notNull || entity.protobuf>
<#if entity.protobuf>
if(entity.has${property.propertyName?cap_first}()) {
</#if>
<#if property.pkAutoincrement>
if(entity.get${property.propertyName?cap_first}() != 0) {
</#if> stmt.bind${toBindType[property.propertyType]}(${property_index + 1}, entity.get${property.propertyName?cap_first}()<#if
property.propertyType == "Boolean"> ? 1l: 0l</#if><#if property.propertyType == "Date">.getTime()</#if>);
<#if entity.protobuf || property.pkAutoincrement>
}
</#if>
<#else> <#-- nullable, non-protobuff -->
${property.javaType} ${property.propertyName} = entity.get${property.propertyName?cap_first}();
if (${property.propertyName} != null) {
<#if property.pkAutoincrement> if (${property.propertyName} != 0) {
</#if> stmt.bind${toBindType[property.propertyType]}(${property_index + 1}, ${property.propertyName}<#if property.propertyType == "Boolean"> ? 1l: 0l</#if><#if property.propertyType == "Date">.getTime() </#if>);
<#if property.pkAutoincrement> }</#if>
}
</#if>
Это заставит greendao НЕ связывать ваше значение autoincrement-primarykey с вашими обновлениями или инструкциями вставки, если это не так. != 0
или же null
,
Будьте осторожны со вторым подходом: он не проверен и, следовательно, может также иметь побочные эффекты в других частях greendao!