Какова цель карты проекции Android в контент-провайдере?
Я рассматриваю пример кода приложения для блокнота Android в <path_to_SDK>/samples/android-16/NotePad/src/com/example/android/notepad
.
Мне было интересно, может ли кто-нибудь объяснить мне, зачем нужен следующий код в NotepadProvider.java
?
// Creates a new projection map instance. The map returns a column name
// given a string. The two are usually equal.
sNotesProjectionMap = new HashMap<String, String>();
// Maps the string "_ID" to the column name "_ID"
sNotesProjectionMap.put(NotePad.Notes._ID, NotePad.Notes._ID);
// Maps "title" to "title"
sNotesProjectionMap.put(NotePad.Notes.COLUMN_NAME_TITLE,NotePad.Notes.COLUMN_NAME_TITLE);
// Maps "note" to "note"
sNotesProjectionMap.put(NotePad.Notes.COLUMN_NAME_NOTE, NotePad.Notes.COLUMN_NAME_NOTE);
// Maps "created" to "created"
sNotesProjectionMap.put(NotePad.Notes.COLUMN_NAME_CREATE_DATE, NotePad.Notes.COLUMN_NAME_CREATE_DATE);
// Maps "modified" to "modified"
sNotesProjectionMap.put(
NotePad.Notes.COLUMN_NAME_MODIFICATION_DATE,
NotePad.Notes.COLUMN_NAME_MODIFICATION_DATE)
Я заметил, что проекционная карта используется позже в методе query()
:
...
SQLiteQueryBuilder qb = new SQLiteQueryBuilder();
qb.setTables(NotePad.Notes.TABLE_NAME);
/**
* Choose the projection and adjust the "where" clause based on URI pattern-matching.
*/
switch (sUriMatcher.match(uri)) {
// If the incoming URI is for notes, chooses the Notes projection
case NOTES:
qb.setProjectionMap(sNotesProjectionMap);
break;
...
Зачем нужна карта проекций?
Ответы
Ответ 1
Приложение Notepad
из демонстраций SDK
является примером приложения, которое должно быть примером использования API и передовой практики с использованием этих API-интерфейсов, поэтому они, вероятно, используют карту прогноза. Хотя образец Notepad
действительно не нужен проекционная карта, использование одного из них является хорошей демонстрацией для более сложных случаев, когда это необходимо. Например, если я правильно помню, приложение Shelves
, написанное одним из инженеров Google, использует карту проецирования в своем ContentProvider
, и эта проекционная карта - это не просто сопоставление с идентичными парами ключ-значение.
Я также добавил ссылку на документацию по методу SQLiteQueryBuilder.setProjectionMap
, в котором есть некоторые сведения о том, почему вам нужна проекционная карта.
Ответ 2
Его основная цель - переименовать имена столбцов, найденные в курсоре, создаваемом запросом.
@статическая декларация
SEARCH_PROJECTION_MAP = new HashMap<String, String>();
SEARCH_PROJECTION_MAP.put( OpenHelper.NAME, OpenHelper.NAME + " as _name" );
SEARCH_PROJECTION_MAP.put( OpenHelper.ID , OpenHelper.ID + " as _id" );
Функциональность вашего запроса
//if you query using sqliteQueryBuilder then
sqLiteQueryBuilder.setProjectionMap( SEARCH_PROJECTION_MAP );
//example if you just query
Cursor cursor = sqLiteQueryBuilder.query( db, projection, selection, selectionArgs, null, null, sortOrder );
возвращенные столбцы теперь являются _name и _id в этом примере.
Ответ 3
В дополнение к тому, как сказал Хуан, целью проекционной карты является переименование имен столбцов, а также устранение неоднозначности имен столбцов при выполнении объединений, важная цель проекционных карт - проверка выбора против вредоносных аргументов.
При использовании SQLiteQueryBuilder
для создания оператора с использованием buildQueryString(boolean, String, String[], String, String, String, String, String)
, если указана карта проекции, поля, не содержащие эту карту, будут игнорироваться.
Чтобы получить максимальную защиту от вредоносных сторонних приложений (например, потребителей контент-провайдера), вы можете сделать следующее:
- Установить
SQLiteQueryBuilder#setStrict(true)
- Используйте карту проецирования.
- Используйте одну из перегрузок запросов вместо получения инструкции как
Строка sql
Ответ 4
Возможно, кому-то нужно более подробное объяснение. Я собрал важные факты о проекционной карте:
-
Если вам не нужна карта проекции, просто не устанавливайте ее. Таким образом, проекционные имена обрабатываются "как есть", точно так же, как переданные через проекционный массив.
-
Даже проекционный массив не является обязательным. Если вы передаете null в запрос, он генерирует операцию "SELECT *". (на самом деле это не рекомендуется в SQL, из-за поломки, которая может возникнуть, если столбцы добавлены/удалены или переупорядочены).
-
Прилагаемая карта проекции относится только к списку выбора! Таким образом, вы можете сопоставить "store_name" = > "bookstore.storename", и это приведет к "select bookstore.storename...", но если вы указали "store_name" в параметре "order by" query builder или один из другие квалифицированные параметры, вы можете в конечном итоге с плохим SQL.
-
Карта проекции может быть переупорядочена. Если ключевая часть записи проекции содержит предложение "как", часть значения игнорируется, а ключевая часть вставляется в результирующий SQL. Например, "попугай, как польский" = > "взломщик" будет генерировать "SELECT попугай, как политический...", а не "взломщик". "As" может быть либо в верхнем регистре, либо в любом нижнем регистре (не смешанный случай) и должен иметь по крайней мере одно пространство до и после слова "как".
Подробнее читайте в этой статье:
http://www.mousetech.com/blog/android-projection-maps-explained/