Шаблон DAO с царством - PullRequest
       6

Шаблон DAO с царством

0 голосов
/ 24 июня 2018

Как можно использовать DAO с областью? Потому что, когда в своей деятельности я пытаюсь установить членов своего модельного класса, я получаю исключение:

java.lang.IllegalStateException: изменение данных области может быть сделано только из транзакции.

Я знаю, что использование realm.executeTransaction решает проблему, но код в моей деятельности больше не зависит от базы данных, потому что он будет исходным кодом, специфичным для связи с базами данных низкого уровня. Поэтому позже, если я захочу изменить базу данных, рефакторинг будет стоить много времени и работы ... Кроме того, мне придется обрабатывать во всех моих действиях ссылку на Realm.getDefaultInstance();

Вот пример кода моей деятельности

protected void onCreate(Bundle savedInstanceState)
{
    mBook = mBookDaoImpl.getBookById(bookId);
}

// Later in the code

private void saveBook(String name)
{
    mBook.setName(name);
}

Вот мой класс модели

public class Book extends RealmObject
{
    @Required
    @PrimaryKey
    private String id;

    private String name;

    public Book() {
    }

    public Book(String id, String name) {
        this.id = id;
        this.name = name;
    }

    // getter setter methods
}

Вот мой интерфейс DAO:

public interface BookDao
{
    List<Book> getAllBooks();

    Book getBookByIsbn(int isbn);

    void saveBook(Book book);

    void deleteBook(Book book);
}

И, наконец, моя реализация:

public class BookDaoImpl implements BookDao
{
    private static BookDaoImpl INSTANCE = null;

    private Realm mRealm;

    private BookDaoImpl()
    {
        mRealm = Realm.getDefaultInstance();
    }

    public static BookDaoImpl getInstance()
    {
        if (INSTANCE == null)
            INSTANCE = new BookDaoImpl();

        return INSTANCE;
    }

    @Override
    public List<Book> getAllBooks()
    {
        return mRealm.where(Book.class).findAll();
    }

    @Override
    public Book getBookById(String id)
    {
        return mRealm.where(Book.class).equalTo("id", id).findFirst();
    }

    @Override
    public void saveBook(final Book book)
    {
        mRealm.executeTransaction(new Realm.Transaction()
        {
            @Override
            public void execute(Realm realm)
            {
                if (book.getId() == null)
                    book.setId(UUID.randomUUID().toString());
                realm.copyToRealmOrUpdate(book);
            }
        });
    }

    @Override
    public void deleteBook(final Book book)
    {
        mRealm.executeTransaction(new Realm.Transaction()
        {
            @Override
            public void execute(Realm realm)
            {
                mRealm.where(Counter.class).equalTo("id", book.getId())
                        .findFirst()
                        .deleteFromRealm();
            }
        });
    }
}

1 Ответ

0 голосов
/ 24 июня 2018

Метод getInstance() Realm возвращает thread-local, reference counted instance which must be paired with a close() call, поэтому ваша реализация DAO, вероятно, не будет соответствовать вашим ожиданиям.

Если вы используете мою библиотеку Realm-Monarchy , которую я создалспециально для того, чтобы упростить «абстрагирование Realm», вы можете реализовать свой DAO следующим образом:

public class BookDaoImpl implements BookDao
{
    private static BookDaoImpl INSTANCE = null;

    private Monarchy monarchy;

    private BookDaoImpl(Monarchy monarchy)
    {
        this.monarchy = monarchy;
    }

    public static BookDaoImpl getInstance(Monarchy monarchy)
    {
        if (INSTANCE == null) {
            synchronized(BookDaoImpl.class) {
                if(INSTANCE == null) {
                    INSTANCE = new BookDaoImpl(monarchy);
                }
            }
        }
        return INSTANCE;
    }

    @Override
    public List<Book> getAllBooks()
    {
        return monarchy.fetchAllCopiedSync((realm) -> realm.where(Book.class));
    }

    @Override
    public Book getBookById(final String id)
    {
        List<Book> books = monarchy.fetchAllCopiedSync((realm) -> realm.where(Book.class).equalTo("id", id));
        if(books.isEmpty()) {
            return null;
        } else {
            return books.get(0);
        }
    }

    @Override
    public void saveBook(final Book book)
    {
        monarchy.runTransactionSync((realm) -> {
            if (book.getId() == null)
                book.setId(UUID.randomUUID().toString());
            realm.insertOrUpdate(book);
        });
    }

    @Override
    public void deleteBook(final Book book)
    {
        monarchy.runTransactionSync((realm) -> {
                realm.where(Counter.class).equalTo("id", book.getId())
                        .findFirst()
                        .deleteFromRealm();
        });
    }
}

PS: вы теряете много энергии / функциональности, если возвращаете List<T> синхронновместо наблюдаемого типа LiveData<List<T>> (или изначально RealmResults<T>).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...