Realm异常“嵌套事务不允许”,即使没有嵌套事务

时间:2016-07-11 11:53:33

标签: android realm

最近我开始了一个Android应用程序项目。我需要尽可能地管理数据。

所以我选择了Realm并对它进行了一些修补。

但我遇到了一些错误。但我不知道为什么会发生这种错误。

错误是

不允许嵌套交易。在每个beginTransaction()之后使用commitTransaction()。

我的代码在下面。

public class CuratorApplication extends Application {

    private Realm realm;

    @Override
    public void onCreate() {
        super.onCreate();
        Log.e("debug", "Application class create!!");
        configureRealmDatabase(this);
    }

    private void configureRealmDatabase(Context context){
        RealmConfiguration config = new RealmConfiguration.Builder(context)
                .name("curator.realm")
                .build();
        Realm.setDefaultConfiguration(config);
    }
}

我按照here

中的描述在Application类中注册域

我试图在活动中进行交易。但它显示错误。 :(

package com.nolgong.curator.screen;

import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;

import com.nolgong.curator.R;
import com.nolgong.curator.model.retrofit.Game;
import com.nolgong.curator.model.retrofit.GameInformation;
import com.nolgong.curator.model.retrofit.Team;
import com.nolgong.curator.network.NetworkClient;

import java.io.IOException;
import java.util.Properties;

import io.realm.Realm;
import io.realm.exceptions.RealmPrimaryKeyConstraintException;
import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;

public class IntroActivity extends AppCompatActivity {

    private Button confirmBtn;
    private EditText confirmText;
    private Realm realm;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_intro);
        setUp();
        registerListener();
    }

    private String getProperty() throws IOException{
        Properties properties = new Properties();
        properties.load(getResources().openRawResource(R.raw.config));
        String property = properties.getProperty("serverAddress");
        Log.e("debug", "Property : " + property);
        return property;
    }

    private void setNetworkClient(String serverAddress){
        Log.e("debug", "Address : " + serverAddress);
        NetworkClient.getInstance(serverAddress);
    }

    private void setUp(){
        try {
            setNetworkClient(getProperty());
        } catch (IOException e){
            Log.e("debug", "set network" + e);
        }
        confirmBtn = (Button)findViewById(R.id.intro_confirm);
        confirmText = (EditText)findViewById(R.id.intro_input);
        realm = Realm.getDefaultInstance();
        Log.e("debug", "transaction state : " + realm.isInTransaction());
        Log.e("debug", "CONFIGURATION : \n" + realm.getConfiguration());
    }

    private void registerListener(){
        confirmBtn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                String teamId = confirmText.getText().toString();
                Integer digit = Integer.valueOf(teamId);
                Log.e("debug", digit + "");
                NetworkClient.getInstance().login(digit, new Callback<GameInformation>() {
                    @Override
                    public void onResponse(Call<GameInformation> call, Response<GameInformation> response) {
                        int responseCode = response.code();
                        switch (responseCode){
                            case 200:
                                GameInformation gameInformation = response.body();

                                Log.e("debug", "game information " + gameInformation.toString());

                                Game game = gameInformation.getGame();
                                Team team = gameInformation.getTeam();

                                updateGameToRealm(game);
                                updateTeamToRealm(team);
                                break;
                            default:
                                Log.e("debug", "Maybe something happened.");
                                break;
                        }
                    }

                    @Override
                    public void onFailure(Call<GameInformation> call, Throwable t) {
                        Log.e("debug", "Login fail :" + t.toString());
                    }
                });
            }
        });
    }

    private void updateGameToRealm(Game game){

        com.nolgong.curator.model.database.Game rGame = new com.nolgong.
                curator.model.database.Game(game.getId(), game.getDate(),
                game.getSession(), game.getRunningTime());
        realm.beginTransaction();

        try {
            realm.copyToRealm(rGame);
        } catch (RealmPrimaryKeyConstraintException e){
            Log.e("debug", e.toString());
            realm.cancelTransaction();
        } finally {
            realm.commitTransaction();
        }
    }

    private void updateTeamToRealm(Team team){
        com.nolgong.curator.model.database.Team rTeam = new com.nolgong.
                curator.model.database.Team(team.getId(), team.getMembers(),
                team.getGameId(), team.isClientDataSynced(),
                team.getJob(), team.getDigit(),
                team.getPoint());
        realm.beginTransaction();
        try {
            realm.copyToRealm(rTeam);
        } catch (RealmPrimaryKeyConstraintException e){
            Log.e("debug", e.toString());
            realm.cancelTransaction();
        } finally {
            realm.commitTransaction();
        }
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        realm.close();
    }
}

为什么领域显示错误?我使用得当吗?或者这只是一个错误? 请帮帮我..

3 个答案:

答案 0 :(得分:2)

正如错误所说,

  

不允许嵌套交易。在每个beginTransaction()之后使用commitTransaction()。

这意味着你不能做这样的事情:

realm.beginTransaction();
...
realm.beginTransaction();
realm.commitTransaction();

beginTransaction()来电之后必须是commitTransaction()cancelTransaction()来电。

强烈建议您使用executeTransaction()代替begin/cancel/commit,因为它更易于使用,并自动处理异常取消。

编辑:在使用cancelTransaction()回滚后,您不应提交交易。

请尝试将begin/cancel/commit替换为executeTransaction(),看看会发生什么。

此外,您可以尝试将copyToRealm()替换为copyToRealmOrUpdate()

我认为您可能会遇到this issue因为您遇到故障的UI线程上的多个事务,但我实际上并不确定。

<强> EDIT2:

private void updateGameToRealm(Game game){
    Realm realm = null;
    try {
        realm = Realm.getDefaultInstance();
        final com.nolgong.curator.model.database.Game rGame = new com.nolgong.
            curator.model.database.Game(game.getId(), game.getDate(),
            game.getSession(), game.getRunningTime());
        realm.executeTransaction(new Realm.Transaction() {
            @Override
            public void execute(Realm realm) {
                realm.copyToRealmOrUpdate(rGame);
            }
        });
    } finally {
        if(realm != null) {
            realm.close();
        }
    }
}

private void updateTeamToRealm(Team team){
    Realm realm = null;
    try {      
        realm = Realm.getDefaultInstance();
        final com.nolgong.curator.model.database.Team rTeam = new com.nolgong.
            curator.model.database.Team(team.getId(), team.getMembers(),
            team.getGameId(), team.isClientDataSynced(),
            team.getJob(), team.getDigit(),
            team.getPoint());
        realm.executeTransaction(new Realm.Transaction() {
            @Override
            public void execute(Realm realm) {
                realm.copyToRealmOrUpdate(rTeam);
            }
        });
    } finally {
        if(realm != null) {
            realm.close();
        }
    }
}

答案 1 :(得分:1)

问题在这里:https://github.com/realm/realm-java/issues/542

您的领域交易代码应与此类似:

WebDriverWait wait = new WebDriverWait(driver, 10);
WebElement spanElement = wait.until(ExpectedConditions.presenceOfElementLocated(By.xpath("//span[text() = 'History']")));
Actions builder = new Actions(driver);    
builder.moveToElement(spanElement).perform();  

答案 2 :(得分:0)

根据我的最佳解决方案是启动领域交易 realm.executeTransactionAsync方法 如果使用此executeTransactionAsync方法,则relam处理begin事务,提交事务本身

我在插入或更新数据时也遇到了同样的错误,然后我找到了这个方法, 下面是我如何使用的样本

public void saveUserInfo(final UserDto userDto){

    realm = Realm.getDefaultInstance();
    realm.executeTransactionAsync(new Realm.Transaction() {
        @Override
        public void execute(Realm realm) {
            realm = Realm.getDefaultInstance();
            realm.copyToRealmOrUpdate(userDto);
            //realm.commitTransaction();
        }
    }, new Realm.Transaction.OnSuccess() {
        @Override
        public void onSuccess() {
            EventBus.getDefault().post(new OnUserSaveEvent(true));
            realm.close();
        }
    }, new Realm.Transaction.OnError() {
        @Override
        public void onError(Throwable error) {
            realm.close();
        }
    });
}