2017-02-15 11 views
2

Realmをさまざまな理由でデータベースソリューションとして検討していますが、現時点でNougatで現在TransactionTooLargeExceptionがスローされている大きな問題がありましたので、現在のデータベースアーキテクチャ、独自の厄介な制限があるActiveAndroidに基づいています。困難は、Realmが継承(https://github.com/realm/realm-java/issues/761)をサポートしていないことであり、特に急いでそれを回避するようには思われません。代わりに、継承を超えて合成を使用することをお勧めしますが、私はGson/Jsonの逆シリアル化でそれを動作させる方法を理解できません。Gsonのシリアル化によるRealmObjectsの継承オーバーコンポジション

例:

スーパークラス:サブクラス犬と動物、そしてジャーマン・シェパード

public class Animal { 

    private int numLegs; 

    private boolean hasFur; 
} 

public class Dog extends Animal { 
    private String color; 

    private boolean canDoTricks; 
} 

public class GermanShepherd extends Dog { 

    public boolean isGuardDog; 

    public boolean isAtRiskOfHipDysplasia() 
} 

(申し訳ありませんが、これは単に説明するために、超缶詰例です)。

今度は、このためのJSONのように見えると言ってみましょう:それは私にそれを与えているAPIですので、今

{ 
    "numLegs" : 4, 
    "hasFur" : true, 
    "color" : "Black & Brown", 
    "canDoTricks" : true, 
    "isGuardDog" : true, 
    "isAtRiskofHipDysplasia" : false 
} 

、私は、JSONを変更することはできません。

https://stackoverflow.com/a/41552457/4560689これを見ると、非常にハッキリなやり方で作業をすることは可能ですが、回答にはシリアル化が間違っているなどの制限があることに注意してください。サーバは狂った合成を伴わないjson形式でしか話していないので、これは問題を提示する。

これを行うには、カスタムGsonデシリアライザ/シリアライザを作成できますか?もしそうなら、どのように見えますか?私は基本的に、オブジェクトにjsonペイロードを変換することができる必要があります。N - 1オブジェクトはベースオブジェクト内にネストされています。

したがって、構成(これは必ずしも「レルム」の構成ではないことに注意してください。レルムはインタフェースの構成の奇妙な形を使用しているようです)

public class GermanShepherd { 
    public Animal animal; 
    public Dog dog; 

    // Generate a bunch of delegate methods here 
} 

私は間違った木を吠えていますか?それはRealmが私がやろうとしていることではうまくいかず、継承が複数の場所、特に永続化したいオブジェクトに組み込まれているAPIに組み込まれているように感じるので、回避策を見つけなければならないまたは別のソリューションを使用してください。 ActiveAndroid(私が今使っているもの)も理想的なソリューションではなく、デッドロック、クラッシュ、データのサイズが大きすぎるとクラッシュするバックグラウンドスレッドのクエリインテントなど... SQLiteのすべての問題。私は私の主な質問やこの問題を解決する代替案の解決策に門戸を開いています。あなたの助けを前もってありがとう!

+1

私はあなたが投稿した回答を書いた人です。さて、これを回避するには、Gsonで好きなように直列化されたGermanShepard POJO(非realmObject)を作成し、GermanShepardのrealmObjectとこのPOJOの間の何らかのマッピングを実行する方法があります。実際、この問題を回避するためにpplが行ってきたのはこれです。 [this](http://johnpetitto.com/no-more-realm)をチェックしてください。それを行う方法の例を書いてほしい場合は、私に教えてください。コードを投稿します^^。しかし、私はカスタムシリアライザをお勧めします、それはよりよいアプローチです。 – AnixPasBesoin

+0

@AnixPasBesoin、返信いただきありがとうございます!可能であれば、私はカスタムシリアライザをしたいと思います。どのように私はその仕事をするかもしれないのアイデアを持っていますか?以前にGsonを使用して、RealmObjectへのAPIの応答を逆シリアル化し、RealmObjectをAPIが期待するjson形式にシリアル化し直しますか? –

+0

Gsonや他の自動シリアライザは誰にも変わっていませんか?個人的には、手動でシリアライズ/デシリアライズする方が好きだと思います。繰り返し(シリアライザとデシリアライザに新しいフィールドを追加する必要があります)がありますが、コントロールと柔軟性を追加する抽象レイヤーが優れていると思います。オブジェクトの内部を更新する必要があります。ちょうどそれがapiに話す方法。 –

答えて

3

フラット化された具象クラスごとに新しいRealmObjectクラスを作成し、JSON表現をそれらにマップする必要があります。

継承を保持するには、相互に継承するインタフェースからgetter/setterを継承することで継承をシミュレートできます。

public interface IAnimal extends RealmModel {  
    int getNumberOfLegs(); 
    void setNumberOfLegs(int legs); 
    boolean getHasFur(); 
    void setHasFur(boolean hasFur); 
} 

public interface IDog extends IAnimal { 
    String getColor(); 
    void setColor(String color); 
    boolean getCanDoTricks(); 
    void setCanDoTricks(); 
} 

public interface IGermanShepherd extends IDog { 
    boolean getIsGuardDog(); 
    void setIsGuardDog(boolean isGuardDog); 
    boolean getIsAtRiskOfHipDysplasia(); 
    void setIsAtRiskOfHipDysplasia(boolean isAtRisk); 
} 

、あなたは

public class GermanShepard 
    extends RealmObject 
    implements IGermanShepard { 
     private int numLegs; 
     private boolean hasFur; 
     private String color; 
     private boolean canDoTricks; 
     private boolean isGuardDog; 
     private boolean isAtRiskofHipDysplasia; 

     // inherited getters/setters 
} 

を行うことができますのであなたも

public abstract class AnimalRepository<T extends IAnimal> { 
    protected Class<T> clazz; 

    public AnimalRepository(Class<T> clazz) { 
     this.clazz = clazz; 
    } 

    public RealmResults<T> findAll(Realm realm) { 
     return realm.where(clazz).findAll(); 
    } 
} 

@Singleton 
public class GermanShepardRepository extends AnimalRepository<GermanShepard> { 
     @Inject 
     public GermanShepardRepository() { 
      super(GermanShepard.class); 
     } 
} 

そして

@Inject 
GermanShepardRepository germanShepardRepository; 

RealmResults<GermanShepard> results = germanShepardRepository.findAll(realm); 

それからリポジトリクラスを作ることができます

しかし実際にはそれらを1つのクラスにマージして、String type;パラメータを与えて元の型を知ることができます。それはおそらくこれらのGermanShepardsをすべて持っているよりも優れています。

+0

私が正しく理解していれば、GermanShepherdはRealmObjectを拡張し、RealmModelを実装しています。何故ですか? –

+0

'RealmObject'の宣言は実際には' @RealmClass public abstract class RealmObjectはRealmModel'を実装しているので、これは問題ではありません。 'RealmResults 'を動物リポジトリで動かすことです。また、私は実際にこれをテストしていないが、私はそれが動作するはずだと思う。 – EpicPandaForce

+0

しかし、ユースケースのように聞こえます。 "本当に多態性が必要な場合は、インターフェイス経由でRealmObjectのフィールドを共有できます。"](https://hackernoon.com/designing-the-schema-of-realm-effectively- and-other-realm-tips-feb76c5b6072#.32hs6ed05) – EpicPandaForce

関連する問題