java - 具有 Realm 的 DAO 模式

标签 java android realm

DAO 如何与 realm 一起使用?因为在我的 Activity 中,我尝试设置模型类的成员时出现异常:

java.lang.IllegalStateException: Changing Realm data can only be done from inside a transaction.

我知道使用 realm.executeTransaction 可以解决这个问题,但我 Activity 中的代码不再与数据库无关,因为它将计算特定于低级数据库通信的代码。所以以后如果我想更改数据库,重构将花费大量时间和工作......此外,我将不得不在我的所有 Activity 中处理对 Realm.getDefaultInstance();

这是我的 Activity 代码示例

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 接口(interface):

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();
            }
        });
    }
}

最佳答案

Realm 的 getInstance()方法返回 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();
        });
    }
}

P.S.:如果返回 List<T>,您将放弃很多功能/功能同步,而不是像 LiveData<List<T>> 这样的可观察对象(或最初是 RealmResults<T> )。

关于java - 具有 Realm 的 DAO 模式,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51005438/

相关文章:

android - channel 或 mutablesharedflow ,哪个是已弃用的 localbroadcastmanager 的更好替代品

android - 主键约束被破坏。值已存在 : 0

java - 为什么 getWidth() 和 getHeight() 返回的值是实际图像尺寸的两倍?

java - 将小写的短工作日解析为 Java 8 的时间 DayOfWeek

android - 在 Android 中的 BaseAdapter 的弹出菜单中重命名 ListView 项后更新 ListView

安卓动态壁纸淡入淡出效果

ios - Realm 的 Swift 3.0 编译的 Swift 模块在 Swift 3.0.1 无法导入

android - 多表 Realm 查询

java - Android 预加载启动画面

java - 空安全集合包含方法