2016-07-11 9 views
1

最近、私はアンドロイドアプリプロジェクトを開始しました。そして、私は可能な限り構造化されたデータを管理する必要がありました。ネストされたトランザクションがなくても、レルム例外 "ネストされたトランザクションは許可されません"

だから、私はレルムを選択し、それについていくつか修正しました。

しかし、私は何らかのエラーに直面しました。しかし、私はこのエラーがなぜ起こるのか分かりません。

エラーが

ネストされたトランザクションは許可されていないです。各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(); 
    } 
} 

は、レルムがエラーを示しているのはなぜ?私はそれを正しく使用しましたか?またはそれは単にバグです? エラーが言うように、... IOI

+0

あなたがエラーに関連するコードを表示することができますか? –

+0

'beginTransaction()' **をコード内の行** **のどこか**で2回呼び出すと、ここで引用しませんでした。 – EpicPandaForce

+1

どこかにループがある場合は、ループ外でbeginTransactionを実行してから、ループが終了した後にコミットしてください。また、foreachの代わりに通常のfor()ループを使用しています – Eenvincible

答えて

2

私を助けて

ネストされたトランザクションください

これは、次のようなことができないことを意味します。

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

beginTransaction()コールはcommitTransaction()またはcancelTransaction()呼び出しのどちらかを続けなければなりません。

begin/cancel/commitの代わりにexecuteTransaction()を使用することを強くお勧めします。これは使いやすく、自動的に例外のキャンセルを処理するためです。

EDIT:トランザクションは、cancelTransaction()でロールバックされた後にコミットしないでください。

begin/cancel/commitexecuteTransaction()に置き換えて、どうなるかを確認してください。

また、copyToRealm()copyToRealmOrUpdate()に置き換えることもできます。

エラーが発生したUIスレッドで複数のトランザクションが発生したため、this issueに実行されている可能性がありますが、実際はわかりません。

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()を2回使用しませんでした。だから私はそれを混乱させるのです。 – 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午前は、私は以下の iが

を使用する方法のサンプルで、このメソッドを見つけ、あなたはこのexecuteTransactionAsync方法

を使用する場合は、データを挿入または更新している間、私も同じエラーをgetingた、トランザクション自体をコミットし、トランザクションを開始扱います

ます。public void 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(); 
     } 
    }); 
} 
関連する問題