Как хранить и извлекать данные для конкретного пользователя, используя SQlite в Android - PullRequest
0 голосов
/ 19 июня 2019

Я хочу сохранить учетные данные пользователя (имя), а затем под этим именем я хочу сохранить некоторые данные для этого конкретного пользователя.Я использую SQlite для этого, и я успешно сохранил данные, но я не могу сделать это для конкретного пользователя. На данный момент он отображается для всех пользователей.Мое конкретное имя пользователя в настоящее время сохраняется в общих настройках.Пожалуйста, покажите мне подходящее решение для этого.

Помощник БД:

public class DBHelper extends SQLiteOpenHelper {
    private static final int DATABASE_VERSION = 1;
    private static final String DATABASE_NAME = "NOTES";
    public static final String USER_COLUMN_ID = "idu";
    public static final String TABLE_USER_NAME = "name";

    public static final String CREATE_TABLE_USER =
            "CREATE TABLE " + TABLE_USER_NAME + "("
                    + USER_COLUMN_ID + " INTEGER PRIMARY KEY AUTOINCREMENT"
                    + ")";

    public DBHelper(Context context) {
        super(context, DATABASE_NAME, null, DATABASE_VERSION);
    }

    @Override
    public void onCreate(SQLiteDatabase db) {
        db.execSQL(Notes.CREATE_TABLE_NOTE);
        db.execSQL(CREATE_TABLE_USER);
    }

    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
        db.execSQL("DROP TABLE IF EXISTS " + TABLE_NAME);
        db.execSQL("DROP TABLE IF EXISTS " + TABLE_USER_NAME);
        onCreate(db);
    }

    public long insertNote(String note) {
        SQLiteDatabase db = this.getWritableDatabase();

        ContentValues values = new ContentValues();
        values.put(Notes.COLUMN_NOTE, note);

        long id = db.insert(TABLE_NAME, null, values);
        db.close();
        return id;
    }

    public Notes getNote(long id) {
        SQLiteDatabase db = this.getReadableDatabase();

        Cursor cursor = db.query(TABLE_NAME,
                new String[]{Notes.NOTE_COLUMN_ID, Notes.COLUMN_NOTE},
                Notes.NOTE_COLUMN_ID + "=?",
                new String[]{String.valueOf(id)}, null, null, null, null);

        if (cursor != null)
            cursor.moveToFirst();

        Notes notes = new Notes(
                cursor.getInt(cursor.getColumnIndex(Notes.NOTE_COLUMN_ID)),
                cursor.getString(cursor.getColumnIndex(Notes.COLUMN_NOTE)));

        cursor.close();

        return notes;
    }

    public List<Notes> getAllNotes() {
        List<Notes> notes = new ArrayList<>();

        String selectQuery = "SELECT  * FROM " + TABLE_NAME + " ORDER BY " +
                Notes.NOTE_COLUMN_ID + " DESC";

        SQLiteDatabase db = this.getWritableDatabase();
        Cursor cursor = db.rawQuery(selectQuery, null);

        if (cursor.moveToFirst()) {
            do {
                Notes note = new Notes();
                note.setId(cursor.getInt(cursor.getColumnIndex(Notes.NOTE_COLUMN_ID)));
                note.setNote(cursor.getString(cursor.getColumnIndex(Notes.COLUMN_NOTE)));


                notes.add(note);
            } while (cursor.moveToNext());
        }

        db.close();

        return notes;
    }

    public int getNotesCount() {
        String countQuery = "SELECT  * FROM " + TABLE_NAME;
        SQLiteDatabase db = this.getReadableDatabase();
        Cursor cursor = db.rawQuery(countQuery, null);

        int count = cursor.getCount();
        cursor.close();
        return count;
    } 

}

Примечания:

public class Notes {

    public static final String NOTE_COLUMN_ID = "id";
    public static final String COLUMN_NOTE = "note";
    public static final String TABLE_NAME = "notes";
    private int id;
    private String note;

    public static final String CREATE_TABLE_NOTE =
            "CREATE TABLE " + TABLE_NAME + "("
                    + NOTE_COLUMN_ID + " INTEGER PRIMARY KEY AUTOINCREMENT,"
                    + COLUMN_NOTE + " TEXT"
                    + ")";

    public Notes() {
    }

    public Notes(int id, String note) {
        this.id = id;
        this.note = note;
    }

    public int getId() {
        return id;
    }

    public String getNote() {
        return note;
    }

    public void setNote(String note) {
        this.note = note;
    }


    public void setId(int id) {
        this.id = id;
    }


}

Фрагмент

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.fragment_notes, container, false);
        recyclerView = view.findViewById(R.id.recycler_view);
        noNotesView = view.findViewById(R.id.empty_notes_view);
        logout = view.findViewById(R.id.button_logout);

        GoogleSignInOptions gso = new GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN)
                .requestEmail()
                .build();
        mGoogleSignInClient = GoogleSignIn.getClient(getActivity(), gso);
        GoogleSignInAccount acct = GoogleSignIn.getLastSignedInAccount(getActivity());
        mUser = acct.getDisplayName().trim();
        LoggedInSharedPreference.setGoogleUserId(getActivity(), mUser);


        db = new DBHelper(getActivity());
        user = db.insertUser(mUser);
        notesList.addAll(db.getNotesByUser(user));

        FloatingActionButton fab = (FloatingActionButton) view.findViewById(R.id.fab);
        fab.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                showNoteDialog(false, null, -1);
            }
        });

        mAdapter = new NotesAdapter(getActivity(), notesList);
        RecyclerView.LayoutManager mLayoutManager = new LinearLayoutManager(getContext());
        recyclerView.setLayoutManager(mLayoutManager);
        recyclerView.setItemAnimator(new DefaultItemAnimator());
        recyclerView.setAdapter(mAdapter);

        toggleEmptyNotes();

        recyclerView.addOnItemTouchListener(new NotesItemListener(getActivity(),
                recyclerView, new NotesItemListener.ClickListener() {
            @Override
            public void onClick(View view, final int position) {
            }

            @Override
            public void onLongClick(View view, int position) {
                showActionsDialog(position);
            }
        }));

        return view;
    }

    private void createNote(String note, long user) {
        long id = db.insertNote(note, user);

        Notes n = db.getNote(id);

        if (n != null) {
            notesList.add(0, n);
            mAdapter.notifyDataSetChanged();
            toggleEmptyNotes();
        }
    }

    private void updateNote(String note, int position) {
        Notes n = notesList.get(position);
        n.setNote(note);
        db.updateNote(n);
        notesList.set(position, n);
        mAdapter.notifyItemChanged(position);

        toggleEmptyNotes();
    }

    private void deleteNote(int position) {
        db.deleteNote(notesList.get(position));
        notesList.remove(position);
        mAdapter.notifyItemRemoved(position);

        toggleEmptyNotes();
    }

    private void showActionsDialog(final int position) {
        CharSequence charSequences[] = new CharSequence[]{"Edit", "Delete"};

        AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
        builder.setTitle("Select");
        builder.setItems(charSequences, new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialog, int which) {
                if (which == 0) {
                    showNoteDialog(true, notesList.get(position), position);
                } else {
                    deleteNote(position);
                }
            }
        });
        builder.show();
    }

    private void showNoteDialog(final boolean shouldUpdate, final Notes notes, final int position) {
        LayoutInflater layoutInflaterAndroid = LayoutInflater.from(getContext());
        View view = layoutInflaterAndroid.inflate(R.layout.note_dialog, null);

        AlertDialog.Builder alertDialogBuilderUserInput = new AlertDialog.Builder(getActivity());
        alertDialogBuilderUserInput.setView(view);

        final EditText inputNote = view.findViewById(R.id.notes);
        TextView dialogTitle = view.findViewById(R.id.dialog_title);
        dialogTitle.setText(!shouldUpdate ? getString(R.string.new_note) : getString(R.string.edit_note));

        if (shouldUpdate && notes != null) {
            inputNote.setText(notes.getNote());
        }
        alertDialogBuilderUserInput
                .setCancelable(false)
                .setPositiveButton(shouldUpdate ? "update" : "save", new DialogInterface.OnClickListener() {
                    public void onClick(DialogInterface dialogBox, int id) {

                    }
                })
                .setNegativeButton("cancel",
                        new DialogInterface.OnClickListener() {
                            public void onClick(DialogInterface dialogBox, int id) {
                                dialogBox.cancel();
                            }
                        });

        final AlertDialog alertDialog = alertDialogBuilderUserInput.create();
        alertDialog.show();

        alertDialog.getButton(AlertDialog.BUTTON_POSITIVE).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if (TextUtils.isEmpty(inputNote.getText().toString())) {
                    Toast.makeText(getActivity(), "Add Note", Toast.LENGTH_SHORT).show();
                    return;
                } else {
                    alertDialog.dismiss();
                }

                if (shouldUpdate && notes != null) {
                    updateNote(inputNote.getText().toString(), position);
                } else {
                    createNote(inputNote.getText().toString(), user);
                }
            }
        });
    }

}

1 Ответ

0 голосов
/ 19 июня 2019

Похоже, вам нужна связь между Заметкой (дочерней) и ее пользователем (родительской). Предполагая, что заметка будет иметь только одного пользователя (которому принадлежит заметка). Затем вы можете добавить столбец в таблицу, где вы храните заметки.

Поскольку в таблице User столбец id определен с использованием INTEGER PRIMARY KEY, этот столбец является идеальным кандидатом для отношения (он проиндексирован и также уникален (неявно)). Это будет целочисленное значение (потенциально длинное в Java).

Чтобы быть последовательным, вы должны определить константу для имени столбца, поэтому добавьте: -

public static final String NOTE_COLUMN_USERMAP = "usermap"; 

Затем вы можете определить изменение константы CREATE_TABLE_NOTE для включения

+ NOTE_COLUMN_USERMAP + " INTEGER "; //<<<<<<<<<comma if needed after INTEGER

Или, если вы хотите ввести ограничения FOREIGN KEY и использовать

+ NOTE_COLUMN_USERMAP + "INTEGER REFERENCES " + DBHelper.TABLE_USER_NAME + "(" + USER_COLUMN_ID + ") ON DELETE CASCADE ON UPDATE CASCADE "; //<<<<<<<<<comma if needed after 2nd CASCADE

Вы должны сделать бесплатное изменение класса / объекта Notes, чтобы сохранить идентификатор пользователь (карта / отношение) (предпочтительно как длинный) пользователя-владельца в классе и добавить геттер и сеттер для идентификатора пользователя. У вас также должен быть конструктор, который включает идентификатор пользователя для использования при извлечении заметки из базы данных.

Затем вам нужно будет внести изменения в методы DBHelper для обслуживания дополнительного столбца. например

Метод insertNote может стать: -

public long insertNote(String note, long userMap) {
    SQLiteDatabase db = this.getWritableDatabase();

    ContentValues values = new ContentValues();
    values.put(Notes.COLUMN_NOTE, note);
    values.put(Notes.NOTE_COLUMN_USERMAP,userMap);

    long id = db.insert(TABLE_NAME, null, values);
    db.close();
    return id;
}

Метод getNotes может стать: -

public Notes getNote(long id) {

    Notes notes;
    SQLiteDatabase db = this.getReadableDatabase();
    Cursor cursor = db.query(TABLE_NAME,
            new String[]{Notes.NOTE_COLUMN_ID, Notes.COLUMN_NOTE,Notes.NOTE_COLUMN_USERMAP},
            Notes.NOTE_COLUMN_ID + "=?",
            new String[]{String.valueOf(id)}, null, null, null, null);

    if (cursor.moveToFirst()) {

        notes = new Notes(
            cursor.getInt(cursor.getColumnIndex(Notes.NOTE_COLUMN_ID)),
            cursor.getString(cursor.getColumnIndex(Notes.COLUMN_NOTE)),
            cursor.getLong(cursor.getColumnIndex(Notes.NOTE_COLUMN_USERMAP))
        );
    }

    cursor.close();
    return notes;
}
  • Обратите внимание, что в приведенном выше примере предполагается, что конструктор имеет значение для отображения пользователя в качестве последнего.
  • Заметьте, что проверка Cursor на null бесполезна, она никогда не будет нулевой, когда возвращается из метода SQliteDatabase Следовательно, вышеизложенное использует результат метода moveToFirst для определения, существует строка или нет.
  • Обратите внимание, что вышеупомянутое вернет ноль (а не провал), если примечание не будет найдено.

но я не могу сделать это для конкретного пользователя. Сейчас он показывает для всех пользователей

После вышесказанного вы можете написать запрос, содержащий предложение WHERE, основанное на столбце usermap.

например. getNotesByUser может быть: -

public List<Notes> getNotesByUser(long usermap) {

    List<Notes> notes = new ArrayList<>();
    SQLiteDatabase db = this.getReadableDatabase();
    Cursor cursor = db.query(TABLE_NAME,
            new String[]{Notes.NOTE_COLUMN_ID, Notes.COLUMN_NOTE,Notes.NOTE_COLUMN_USERMAP},
            Notes.NOTE_COLUMN_USERMAP + "=?",
            new String[]{String.valueOf(usermap)}, null, null, null, null);
    while(cursor.moveToNext()) {
        notes.add(new Notes(cursor.getInt(cursor.getColumnIndex(Notes.NOTE_COLUMN_ID)),
            cursor.getString(cursor.getColumnIndex(Notes.COLUMN_NOTE)),
            cursor.getLong(cursor.getColumnIndex(Notes.NOTE_COLUMN_USERMAP)))
        );
    }
    cursor.close();
    return notes;
}
  • Обратите внимание на более простой цикл while, т. Е. Метод moveToNext возвращает значение false, если перемещение не может быть выполнено (т. Е. После последней строки), тогда нет необходимости moveToFirst , поскольку он сделаю это для первого ряда.

Примечание Выше приведен принципиальный код. Он не тестировался и не запускался, поэтому может содержать некоторые ошибки. Это было предоставлено в качестве руководства.

Рабочий пример

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

Приложение добавляет двух пользователей (Фред и Мэри), а затем добавляет 2 заметки для каждого пользователя. Затем он извлекает все заметки, а затем все заметки для Фреда, а затем для Мэри. Затем 3 набора извлеченных выходных данных выводятся в журнал.

В результате: -

Для всех Заметки для всех пользователей: -

06-20 12:29:22.901 2401-2401/s.e.so56674777notes D/LOGNOTEALL: Note isMy Second Note
       ID is 4
      Owned by User who's ID is 2
06-20 12:29:22.901 2401-2401/s.e.so56674777notes D/LOGNOTEALL: Note isMy Second Note
       ID is 3
      Owned by User who's ID is 1
06-20 12:29:22.901 2401-2401/s.e.so56674777notes D/LOGNOTEALL: Note isMy First Note
       ID is 2
      Owned by User who's ID is 2
06-20 12:29:22.901 2401-2401/s.e.so56674777notes D/LOGNOTEALL: Note isMy First Note
       ID is 1
      Owned by User who's ID is 1

Для Фреда (идентификатор пользователя 1): -

06-20 12:29:22.901 2401-2401/s.e.so56674777notes D/LOGNOTEFRED: Note isMy First Note
       ID is 1
      Owned by User who's ID is 1
06-20 12:29:22.901 2401-2401/s.e.so56674777notes D/LOGNOTEFRED: Note isMy Second Note
       ID is 3
      Owned by User who's ID is 1

Для Мэри (ID пользователя 2): -

06-20 12:29:22.901 2401-2401/s.e.so56674777notes D/LOGNOTEMARY: Note isMy First Note
       ID is 2
      Owned by User who's ID is 2


06-20 12:29:22.901 2401-2401/s.e.so56674777notes D/LOGNOTEMARY: Note isMy Second Note
       ID is 4
      Owned by User who's ID is 2

код

Notes.java

public class Notes {

    public static final String TABLE_NAME = "notes";
    public static final String NOTE_COLUMN_ID = BaseColumns._ID;
    public static final String COLUMN_NOTE = "note";
    public static final String NOTE_COLUMN_USERMAP = "usermap";

    public static final String CREATE_TABLE_NOTE = "CREATE TABLE IF NOT EXISTS " + TABLE_NAME  + "(" +
            NOTE_COLUMN_ID + " INTEGER PRIMARY KEY, " +
            COLUMN_NOTE + " TEXT, " +
            NOTE_COLUMN_USERMAP + " INTEGER " +
            "REFERENCES " + DBHelper.TABLE_USER_NAME + "(" + DBHelper.USER_COLUMN_ID + ") " +
            "ON DELETE CASCADE ON UPDATE CASCADE" +
            ")";

    public Notes(int id, String note, long usermap) {
        this.id = id;
        this.note = note;
        this.usermap = usermap;
    }

    public Notes() {}

    private int id;
    private String note;
    private long usermap;

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getNote() {
        return note;
    }

    public void setNote(String note) {
        this.note = note;
    }

    public long getUsermap() {
        return usermap;
    }

    public void setUsermap(long usermap) {
        this.usermap = usermap;
    }
}

DBHelper.java

public class DBHelper extends SQLiteOpenHelper {
    private static final int DATABASE_VERSION = 1;
    private static final String DATABASE_NAME = "NOTES";
    public static final String USER_COLUMN_ID = "idu";
    public static final String TABLE_USER_NAME = "name";
    public static final String USER_COLUMN_NAME = TABLE_USER_NAME;

    public static final String CREATE_TABLE_USER =
            "CREATE TABLE " + TABLE_USER_NAME + "("
                    + USER_COLUMN_ID + " INTEGER PRIMARY KEY,"
                    + USER_COLUMN_NAME + " TEXT UNIQUE "
                    + ")";

    public DBHelper(Context context) {
        super(context, DATABASE_NAME, null, DATABASE_VERSION);
    }

    @Override
    public void onCreate(SQLiteDatabase db) {
        db.execSQL(Notes.CREATE_TABLE_NOTE);
        db.execSQL(CREATE_TABLE_USER);
    }

    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
        db.execSQL("DROP TABLE IF EXISTS " + Notes.TABLE_NAME);
        db.execSQL("DROP TABLE IF EXISTS " + TABLE_USER_NAME);
        onCreate(db);
    }

    @Override
    public void onConfigure(SQLiteDatabase db) {
        super.onConfigure(db);
        db.setForeignKeyConstraintsEnabled(true);
    }

    public long insertUser(String username) {
        SQLiteDatabase db = this.getWritableDatabase();
        ContentValues cv = new ContentValues();
        cv.put(USER_COLUMN_NAME,username);
        return db.insert(TABLE_USER_NAME,null,cv);
    }

    public long insertNote(String note, long usermap) {
        SQLiteDatabase db = this.getWritableDatabase();
        ContentValues values = new ContentValues();
        values.put(Notes.COLUMN_NOTE, note);
        values.put(Notes.NOTE_COLUMN_USERMAP,usermap);
        long id = db.insert(Notes.TABLE_NAME, null, values);
        db.close();
        return id;
    }

    public Notes getNote(long id) {

        Notes notes = null;
        SQLiteDatabase db = this.getReadableDatabase();

        Cursor cursor = db.query(Notes.TABLE_NAME,
                new String[]{Notes.NOTE_COLUMN_ID, Notes.COLUMN_NOTE, Notes.NOTE_COLUMN_USERMAP},
                Notes.NOTE_COLUMN_ID + "=?",
                new String[]{String.valueOf(id)},
                null, null, null, null
        );
        if (cursor.moveToFirst()) {
            notes = new Notes(
                    cursor.getInt(cursor.getColumnIndex(Notes.NOTE_COLUMN_ID)),
                    cursor.getString(cursor.getColumnIndex(Notes.COLUMN_NOTE)),
                    cursor.getLong(cursor.getColumnIndex(Notes.NOTE_COLUMN_USERMAP))
            );
        }
        cursor.close();
        return notes;
    }

    public List<Notes> getAllNotes() {
        List<Notes> notes = new ArrayList<>();

        String selectQuery = "SELECT  * FROM " + Notes.TABLE_NAME + " ORDER BY " +
                Notes.NOTE_COLUMN_ID + " DESC";

        SQLiteDatabase db = this.getWritableDatabase();
        Cursor cursor = db.rawQuery(selectQuery, null);

        while (cursor.moveToNext()) {
            Notes note = new Notes();
            note.setId(cursor.getInt(cursor.getColumnIndex(Notes.NOTE_COLUMN_ID)));
            note.setNote(cursor.getString(cursor.getColumnIndex(Notes.COLUMN_NOTE)));
            note.setUsermap(cursor.getLong(cursor.getColumnIndex(Notes.NOTE_COLUMN_USERMAP)));
            notes.add(note);
        }
        db.close();
        return notes;
    }

    public List<Notes> getNotesByUser(long usermap) {

        List<Notes> notes = new ArrayList<>();
        SQLiteDatabase db = this.getReadableDatabase();
        Cursor cursor = db.query(Notes.TABLE_NAME,
                new String[]{Notes.NOTE_COLUMN_ID, Notes.COLUMN_NOTE,Notes.NOTE_COLUMN_USERMAP},
                Notes.NOTE_COLUMN_USERMAP + "=?",
                new String[]{String.valueOf(usermap)}, null, null, null, null);
        while(cursor.moveToNext()) {
            notes.add(new Notes(cursor.getInt(cursor.getColumnIndex(Notes.NOTE_COLUMN_ID)),
                    cursor.getString(cursor.getColumnIndex(Notes.COLUMN_NOTE)),
                    cursor.getLong(cursor.getColumnIndex(Notes.NOTE_COLUMN_USERMAP)))
            );
        }
        cursor.close();
        return notes;
    }

    public int getNotesCount() {
        String countQuery = "SELECT  * FROM " + Notes.TABLE_NAME;
        SQLiteDatabase db = this.getReadableDatabase();
        Cursor cursor = db.rawQuery(countQuery, null);
        int count = cursor.getCount();
        cursor.close();
        return count;
    }
}
  • Обратите внимание на добавление, которое переопределяет метод onConfigure , это включает поддержку ForeignKey (в противном случае определения внешнего ключа игнорируются).
  • Примечание AUTOINCREMENT была удалена, она не нужна и имеет накладные расходы.
  • Обратите внимание на добавление столбца имени для таблицы имен и на то, что она имеет ограничение unqiue.

MainActivity.java

Это объединяет все вместе

public class MainActivity extends AppCompatActivity {

    DBHelper mDBHlpr;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        mDBHlpr = new DBHelper(this);

        long user1 = mDBHlpr.insertUser("Fred");
        long user2 = mDBHlpr.insertUser("Mary");
        Notes n1 = new Notes(-1,"My First Note",-1);
        Notes n2 = new Notes(-1,"My Second Note",-1);

        if (mDBHlpr.getNotesCount() < 1) {
            mDBHlpr.insertNote(n1.getNote(), user1);
            mDBHlpr.insertNote(n1.getNote(), user2);
            mDBHlpr.insertNote(n2.getNote(), user1);
            mDBHlpr.insertNote(n2.getNote(), user2);
        }
        List<Notes> allusers = mDBHlpr.getAllNotes();
        List<Notes> fredsnotes = mDBHlpr.getNotesByUser(user1);
        List<Notes> marysnotes = mDBHlpr.getNotesByUser(user2);
        for (Notes n: allusers) {
            logNote("ALL",n);
        }
        for (Notes n: fredsnotes) {
            logNote("FRED",n);
        }
        for (Notes n: marysnotes) {
            logNote("MARY",n);
        }
    }

    private void logNote(String type, Notes n) {
        Log.d("LOGNOTE" + type,"Note is" + n.getNote() + "\n\t ID is " + String.valueOf(n.getId()) + "\n\t" + "Owned by User who's ID is " + String.valueOf(n.getUsermap()));
    }
}
  • Обратите внимание, что вышеуказанное предназначено для запуска только один раз. При последующем запуске оба идентификатора для Фреда и Мэри будут равны -1, поскольку строки не будут добавлены из-за повторяющегося имени, и, следовательно, не будет никаких примечаний, извлеченных в fredsnotes и marynotes.
...