2016-07-11 76 views
1

最近我开始了一个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

描述我试图在交易活动。但它显示错误。 :(

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

为什么境界显示错误?难道我正确地使用它?或者这只是一个错误? 请帮我IOI ..

+0

你能告诉相关的错误代码? –

+0

您在代码中调用了'beginTransaction()** **两次** **代码中的某处**,您没有在此处引用。 – EpicPandaForce

+1

如果你有一个循环的地方,请在循环之外开始事务然后在循环结束之后进行提交;也使用常规for()循环而不是foreach – Eenvincible

回答

2

由于错误说,

嵌套事务在每个beginTransaction()之后使用commitTransaction()。

这意味着你不能这样做:

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

beginTransaction()呼叫必须后跟一个commitTransaction()cancelTransaction()呼叫。

强烈建议使用executeTransaction()而不是begin/cancel/commit,因为它更易于使用,并自动处理例外情况。

编辑:你不应该提交一个交易后,它已被回滚cancelTransaction()

请尝试用executeTransaction()代替begin/cancel/commit,看看会发生什么。

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

我想你可能会遇到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(); 
     } 
    } 
} 
+0

我在commitTransaction()之前没有使用beginTrasaction()两次。所以这就是我混淆它的原因。 – csyouk

+0

谢谢!我记住这一点! – csyouk

+0

我将我的意见转移到答案 – EpicPandaForce

1

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

你的境界交易代码应类似于此:

Realm realm = Realm.getInstance(getApplicationContext()); 

        //Writing to Realm with Transaction blocks 
        realm.beginTransaction(); 

        ModelClass modelClass = realm.createObject(ModelClass.class); 

        // increment index 
        long nextID = (long) (realm.where(ModelClass.class).max("id")); 
        long primaryKeyValue = nextID + 1; 

        try { 
         modelClass.setId(primaryKeyValue); 
         //your can set other values 
         realm.commitTransaction(); 

        } catch (Exception e) { 
         Log.e("Realm Error", "error" + e.getLocalizedMessage()); 
         realm.cancelTransaction(); 
        } 
0

据我最好的解决办法是启动境界交易 realm.executeTransactionAsync方法 rel上午处理开始事务,提交事务本身,如果你使用这个executeTransactionAsync方法

我也歌厅同样的错误,而插入或更新数据,然后我发现这个方法, 下面是我如何使用

样本

公共无效saveUserInfo(最终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(); 
     } 
    }); 
}