2016-12-21 14 views
0

多対多の関係を持ついくつかのBeanを永続化するためにHybernateを使用しています。ここでは、2つの豆は、次のとおりです。Hibernate多対多およびJSON直列化

Email.java

@Entity 
@NamedQuery(name = "Email.findAll", query = "SELECT e FROM Email e") 
public class Email implements Serializable { 
    private static final long serialVersionUID = 1L; 

    //... other fields ... 

    // bi-directional many-to-many association to Pratica 
    @ManyToMany() 
    @JoinTable(name = "email_pratica", joinColumns = { 
      @JoinColumn(name = "fk_email_id") 
    }, inverseJoinColumns = { 
      @JoinColumn(name = "fk_pratica_id") 
    }) 
    private List<Pratica> pratiche; 

    public List<Pratica> getPratiche() { 
     return this.pratiche; 
    } 

    public void setPratiche(List<Pratica> pratiche) { 
     this.pratiche = pratiche; 
    } 

} 

Pratica.java

@Entity 
@NamedQuery(name = "Pratica.findAll", query = "SELECT p FROM Pratica p") 
public class Pratica extends AtstTable implements Serializable { 
    private static final long serialVersionUID = 1L; 

    //... other fields ... 

    // bi-directional many-to-many association to Email 
    @ManyToMany(mappedBy = "pratiche", fetch = FetchType.EAGER, cascade = {CascadeType.MERGE, CascadeType.PERSIST}) 
    private List<Email> emails; 

    public List<Email> getEmails() { 
     return this.emails; 
    } 

    public void setEmails(List<Email> emails) { 
     this.emails = emails; 
    } 

} 

これは、しかし、問題は、私はその後、シリアライズする必要があるということです、正常に動作します/デシリアライズこれらの豆はJSONを使用しています。各オブジェクトEmailは、すべてのオブジェクトPraticaをシリアル化しようとします。Emailなどをシリアル化しようとします(StackOverflow例外が発生するまで)。

私はこれをオンラインで検索しましたが、この問題の解決策はいくつか見つかりましたが、私のプロジェクトの構成上、この問題は解決されていません。特に、ここで私が試したものです:

ソリューション1:これは、ほとんどの提案された解決策であるように思わ@JsonManagedReference/@JsonBackReference

使用。しかし、@JsonBackReferenceアノテーションはコレクション(リスト、配列、セットなど)をサポートしていないため、これは(一対一の関係または多対1の関係について)(私が言う限りでは)動作します。あるいは、少なくとも、これはドキュメンテーションが言っていることであり、試してみると、これを確認するような例外があります。私はリスト上でこのアノテーションを使用するオンラインの例をいくつか見つけましたが、私にとってはうまくいきませんでした。誰かがこれについて何か手がかりがある場合は、詳しく説明してください。

解決方法2:

@ManyToMany() 
@JoinTable(name = "email_pratica", joinColumns = { 
     @JoinColumn(name = "fk_email_id") 
}, inverseJoinColumns = { 
     @JoinColumn(name = "fk_pratica_id") 
}) 
@JsonIgnore 
private List<Pratica> pratiche; 

は無限ループを壊すので、動作します。このように、フィールドのいずれかに@JsonIgnoreを追加@JsonIgnore

を使用して関係の一の側面を保持されません。それはEmailオブジェクトにPraticaのリストが本当に必要なわけではないので、私にも合っています。決して使っていません。 しかし、これは別の大きな問題を引き起こします。オブジェクトをデータベースに保存するたびに、Praticaのリストは空になります(JSONシリアライゼーション中に失われてしまいます)。そのため、Hibernateは結合テーブルから関連レコードを削除します。

解決策3:提供@JsonIdentityInfo
RESTeasyresteasy-jackson-provider 2.3.6)が提供するジャクソンのバージョンをこのソリューションはJackson 2.x必要がありますが、残念ながら、私のコントロールを超えているサーバー上の制約のために、私は使用することができます使用して@JsonSerialize/@JsonDeserialize注釈が私であってもカントーカスタム・シリアライザ/デシリアライザを使用すると
を参照してくださいソリューション3:Jackson 1.x

溶液4のサブセットJackson 1.1にncluded、それはRESTeasyが提供するバージョンに含まれていないか、少なくともコンパイラが参照を見つけることができないと思われるので、私はこれが当てはまると仮定します。

だからこそ、この問題には、私が持っている制限がありますか?それは非ハッキーな方法で行うことができますか?それができないのであれば、「ハッピーでない」ハッキーではない方法は何ですか?

+0

一方の側で '@JsonIgnore'を使用している場合と、永続化/更新を手動で(再)接続する必要がある場合は、唯一の方法です。特にコレクション上で '@ JsonBackReference'をサポートしているかもしれない新しいバージョンに更新することはできません(私はそれをチェックしていませんが、それは良い考えです)。この問題は、JSONが自然に内部参照をサポートする形式ではないという事実から発生します。 – coladict

+0

@coladict:そうです、それは私が現在やっていることです。他のクリーンな方法があるかどうかを確認するために質問を投稿しました。 –

答えて

-1

あなたはjsonとデータベースオブジェクトを混在させていますが、それは私の意見では主な問題、主な設計上の欠陥です。

json以外のデータでシリアル化する場合は、永続性レイヤーを変更する必要があります。パーシスタンスレイヤーを変更したい場合は、jsonも変更する必要があります。

さらに悪い:フロントエンドでjsonを使用していると仮定して、プレゼンテーションレイヤーを単体テストしたいとします。どのようにしてパーシステントレイヤーを使わずにやっていますか?

私の答えは次のとおりです。懸念を分け、jsonと永続性を切り離します。

+0

私は明示的にJSONを使用していません。それは問題の内容を過度に複雑化しないことでした。私の実際のセットアップはこれです:私は、hibernateを使用してdbオブジェクトを持続するバックエンドサーバーを持っています。これらのオブジェクトは、REST Webサービス経由でフロントエンドに送信されます。このWebサービスはrestEasyを使用して実装され、JSON(内部的に)を使用して通過するオブジェクトをシリアライズ/デシリアライズします。残念ながら、これは変更できないアーキテクチャの1つの側面です。 –

+0

同じ答え:言い換えれば、あなたのプレゼンテーション層はその仕事をするためにあなたの永続性タイプを必要とします。パーシスタンスレイヤーにはプレゼンテーションレイヤーの注釈が必要です。プレゼンテーションレイヤーを機能させるのではなく、プレゼンテーションレイヤーを機能させるためです。どちらも独立して働くことはできません。コンポーネント間に双方向の依存関係があります。ソフトウェアのテクノロジースタックを変更し、ソフトウェアのすべてのコードをタッチしてテストします。結合を失う、高い凝集力、私はそれらの用語を発明しなかった;) – slowy

+0

注釈は、「プレゼンテーション層から」ではなく、バックエンドのDBオブジェクト上にある。このような関係を持つオブジェクトは、回避策を取らずにJSONに正しく保持されません。これはよく文書化されており(オンラインで検索)、既知の解決策がありますが、これは私が強制する一部のライブラリの古いバージョンのために失敗しました。あなたの "答え"は、基本的に "既存の依存関係のために私があなたにはすでに言いましたが、何か違うことをするためにプロジェクト全体を再設計"することになります。それは全く役に立たない。 –

関連する問題