2011-12-31 5 views
8

Mam bazę danych SQLite w systemie Android i używam ContentProvider do obsługi operacji, które są utrzymywane w tabeli z kwalifikatorem UNIQUE w kolumnie.Czy można polegać na SQLiteConstraint i pozwolić SQLite na sprawdzanie? Czy jest haczyk?

Problem:

Jednak, kiedy insert zduplikowane wartości w bazie danych, nie złamię kod per se, ale nadal pluje tysiące SQLiteConstraintException linii dziennika, a do mojego użytkownika, po prostu czuje się jak zanieczyszczający Log, coś nieokrzesanego. Próbowałem przechwycić wyjątek tylko po to, aby eksperymentować, ale nadal się loguje.

Pytanie:

Tak, jak mogę milczeć te linie dziennika? Czy to w ogóle jest możliwe?

Proszę przeczytać poniższy komentarz, aby zadać pytanie.

Błąd:

kolumna Czas ma UNIQUE ograniczenia:

Error inserting Factor=2.0 Time=1325375465000 Extra=none 
android.database.sqlite.SQLiteConstraintException: error code 19: constraint failed 
    at android.database.sqlite.SQLiteStatement.native_execute(Native Method) 
    at android.database.sqlite.SQLiteStatement.execute(SQLiteStatement.java:55) 
    at android.database.sqlite.SQLiteDatabase.insertWithOnConflict(SQLiteDatabase.java:1549) 
    at android.database.sqlite.SQLiteDatabase.insert(SQLiteDatabase.java:1410) 
    at mypackage.myapp.provider.DataProvider.bulkInsert(DataProvider.java:353) 
    at android.content.ContentProvider$Transport.bulkInsert(ContentProvider.java:179) 
    at android.content.ContentResolver.bulkInsert(ContentResolver.java:646) 
    at mypackage.myapp.service.MyService.onHandleIntent(MyService.java:96) 
    at android.app.IntentService$ServiceHandler.handleMessage(IntentService.java:59) 
    at android.os.Handler.dispatchMessage(Handler.java:99) 
    at android.os.Looper.loop(Looper.java:123) 
    at android.os.HandlerThread.run(HandlerThread.java:60) 
+0

czuję, że to wszystko oznacza, że ​​to, co staram się robić to leniwy sposób, aby odzyskać od powtórzoną wkładką na unikalność, stąd „matowy” czuć w dzienniku. Prawdopodobnie lepiej naprawię to, co tworzy zduplikowane wpisy (i wywołuję wstawki) na początek. Jestem za gładkością. Ale to rodzi pytanie (do mnie): dlaczego nie możemy po prostu bezpiecznie "odciążyć" pracy do sprawdzania ograniczeń i pozwolić jej na niepowodzenie w sposób logiczny? Na wszelki wypadek ... może oczekujemy duplikatów ... więc nie ma się czym martwić. Może nasze źródło danych, poza naszą kontrolą, jest wadliwe na początek ... – davidcesarino

+0

Komentowanie po udzieleniu odpowiedzi: jak już powiedziałem, byłem leniwy celowo, dla celów tego pytania, ponieważ starałem się nie kodować czeków i zostaw to dla SQLite zastanawiające się nad 1) bezpieczeństwem (współbieżność), 2) wydajnością (czy jest lepiej/szybciej niż ja na tym)? a także 3) praktycznie (mniej kodu). Jednak niektóre rzeczy przykuły moją uwagę (liczba wierszy wstawiania), więc zaimplementowałem sprawdzanie duplikatów oprócz ograniczeń. W każdym razie, byłem bardzo zadowolony z mojego kodu dotyczącego (1). Pamiętaj, że czytając to pytanie. – davidcesarino

+0

Jeśli nie używasz android.util.Zaloguj się, to dlaczego martwisz się o błędy w logowaniu do użytkownika? –

Odpowiedz

10

Jeśli można sformułować lub modyfikować SQL siebie, albo dla INSERT lub początkowego CREATE TABLE, można użyć SQLite's conflict handling extensions. Istnieją dwa sposoby, jak to zrobić:

  • Po włożeniu, używają INSERT OR IGNORE zamiast po prostu INSERT. Można również użyć OR REPLACE, OR ABORT lub dowolnej z kilku innych reakcji.
  • Podczas tworzenia tabeli należy podać klauzulę ON CONFLICT IGNORE dla ograniczenia więzów UNIQUE. To spowoduje, że inserty lub aktualizacje, które naruszają ograniczenie, będą milcząco robić nic.

Uważam, że pomysł używania zdalnej ilości danych, szczególnie w środowiskach współbieżnych, jest bardzo czysty. Sprawdza duplikację raz - w bazie danych - i unika warunków wyścigu, w których najpierw sprawdza się istnienie (co prawda nie stanowi problemu, jeśli tylko jeden proces/wątek uzyskuje dostęp do bazy danych).

Jeśli jednak duplikaty są wynikiem błędu (a nie zduplikowanych zdarzeń/działań, których kod nie jest wyraźnie powielany), może to po prostu ukryć błąd, a nie go naprawić. Brak wyraźnej dekoncentracji nie jest jednak moim zdaniem błędem. Jeśli więc poprawka polega na sprawdzaniu duplikatów, użyj bazy danych; jeśli prawdziwym problemem jest to, że zostały wygenerowane w pierwszej kolejności (na poziomie rzeczywistym aplikacji, a nie na poziomie wiersza bazy danych), to prawdopodobnie szukałbym tego problemu.

+2

Dzięki, właśnie to miałem na myśli. Zauważyłem również, że jeśli użyję 'ON CONFLICT IGNORE' w schemacie tabeli,' SQLiteDatabase.insert systemu Android (String, String, ContentValues) zgłosi wiersz jako wstawiony ... więc bądź ostrożny, jeśli tego potrzebujesz. I tak, biorąc pod uwagę, że mam wiele usług pobierania rzeczy, ma również zaletę unikania wyścigów. Dzięki. – davidcesarino

1

Tak, można go opuścić i jak można powiedzieć, że można to naprawić. Moim zdaniem to zależy od tego, czy dupki są wyjątkowymi zdarzeniami, czy też "właśnie się zdarzają, ponieważ jesteś leniwy".

Sądzę, że w zasadzie kosztuje to mniej oczyścić dane przy wejściu do modułu niż później. Jednak sposób, w jaki definiujesz koszt, zależy od Ciebie.

+0

Większość duplikatów nie jest, ale niektóre z nich mogą zostać naprawione przeze mnie, zanim uruchomię usługę downloader. Zgadzam się na sprawdzenie w punkcie wejścia. Jednak daleko mi do ukończenia kodu i pytałem o to również w perspektywie "co-jeśli". – davidcesarino

4

Zastosowanie SQLiteDatabase.insertOrThrow(...)

Powiązane problemy