1

抽象クラスの特定の注釈を指定して、実行時に抽象クラスの特殊化クラスを生成するライブラリを開発しました。したがって、私のライブラリは次のように使用されます。

X x = newInstance(X.class) //X is an abstract class

このライブラリは Javassist を使用して、実行時にメソッドによってインスタンス化されるサブクラスを生成しますnewInstance

私が理解している限りでは、Hibernate は Javassist を使用して実行時のエンティティ クラスを計測することもできます (そうでない場合は、誰かが私を修正してください)。

私の質問は、2 つのフレームワークを連携させることが可能かどうかです。つまり、エンティティ クラス (抽象クラス) のインスタンスが必要になるたびに、ライブラリから特定のファクトリ メソッドを使用するように Hibernate に指示できますか?

Hibernate がエンティティ クラスの実行時にサブクラスを生成することによって、コーテインの背後で動作するかどうかはわかりません (Hibernate もそれらを計測する必要があると仮定します)。その場合、特定のクラスのファクトリを Hibernate に渡すソリューションは機能しません。その場合、Hibernate は抽象エンティティ クラスの操作をサポートしていますか? つまり、抽象 (またはインターフェース?) エンティティ クラスを操作して、これらの抽象エンティティ クラスの 1 つを操作する必要がある場合に、Hibernate がどの具体的なクラスを装備する必要があるかを何らかの方法で伝えることができるはずです。

しかし、さらに複雑なのは、抽象エンティティ クラスを特別化する具象クラスがコンパイル時に存在しないことです。

4

1 に答える 1

4

あなたの答えに向かう前に:

  • はい、その通りです。現在、Hibernate は Javassist (以前は GCLib を使用していましたが、廃止されました) を使用して、実行時にクラスを計測します。
  • Hibernate は実行時にサブクラスを作成し、永続エンティティのプロキシを使用します。

簡潔な答え

残念ながら、独自のファクトリを使用するように Hibernate を構成することはできないと思います。詳細については、長い回答の部分をお読みください。

長い答え

私が知っている限りでは、現在、Hibernate 4.x はバイトコード操作プロバイダーとして Javassist のみをサポートしています。ただし、3.x バージョンでは GClib と Javassist を切り替えることができました。これらのバージョンに戻ると、hibernate.bytecode.provider.

この設定は、Hibernate 4.1 のドキュメントには表示されなくなりましたが、Hibernate 3.2 のドキュメントのオプションの構成プロパティの下に少し記載されています。

私自身が開発者であるため、時々私たちはトリッキーな仲間であり、何かがドキュメントから外れているからといって、それがコードから外れているとは限らないことを知っています:-)したがって、設定がまだ存在する場合は、悪用を試みることができるかもしれませんあなたが望むことをするためにそれを(ただし、サポートされていない方法で)。

Hibernate 4.0.1 のコード (最新ではないことに注意してください) が私のマシンにあったので、好奇心のためにいくつか掘り下げてみました...そして驚いたことに、そのプロパティがまだ存在していたことに驚きました! 使用された参照を追跡した後 (Eclipse に感謝)、クラス org.hibernate.cfg.Environment (バージョン 4.2.0.CR2 のコード) にたどり着き、次のコードを見つけました (コードは私のバージョンと 4.2 の両方で同じでした) .0CR2):

 public static BytecodeProvider buildBytecodeProvider(Properties properties) {
    String provider = ConfigurationHelper.getString( BYTECODE_PROVIDER, properties, "javassist" );
    LOG.bytecodeProvider( provider );
    return buildBytecodeProvider( provider );
}

private static BytecodeProvider buildBytecodeProvider(String providerName) {
    if ( "javassist".equals( providerName ) ) {
        return new org.hibernate.bytecode.internal.javassist.BytecodeProviderImpl();
    }

    LOG.unknownBytecodeProvider( providerName );
    return new org.hibernate.bytecode.internal.javassist.BytecodeProviderImpl();
}

したがって、私が知る限り、それはプロキシ ファクトリの Javassist 実装であり、それを変更する標準的な方法はありません。


狂人の補足

私が言おうとしているのは純粋な狂気であり、それは本番コードでは考慮されるべきではなく、実際に機能するか、学術的であるか、物事を曲げることができるかというシナリオでのみ考慮されるべきです。

<ハンマーハッキング>

  • 必要に応じてバイトコードを追加するだけでなく、休止状態に必要なバイトコードも追加するために、独自のフレームワークを拡張してクラスをインストルメント化することができます。これは、操作とorg.hibernate.bytecode.internal.javassist.BytecodeProviderImpl操作をマージするようなものです。
  • 次に、拡張クラスの名前を変更BytecodeProviderImplして同じパッケージorg.hibernate.bytecode.internal.javassistに配置し、最終的に、クラスローダーがjar内のクラスの前に見つけるクラスパスのどこかに配置できます(または、カスタムクラスローダーを使用する場合もあります)。

次に、Hibernate、フレームワーク、そしておそらくJVM全体が何をすべきかわからないパニックで悲鳴を上げたり、うまくいくかもしれません...

</ハンマーハッキング>

とにかく、もしあなたがそれを試す時間と意志があれば、それがうまくいったかどうか私に知らせてください.


アップデート

コメント セクションで少し話した後、カスタムEntityPersisterを使用するというアイデアがありました。私はこれについてあまり確信が持てなかったので、私が考えていたことがうまくいくかどうかを教えてくれる何かを見つけることができるかどうかを少しグーグルで調べました.

私の直感が正しかったかどうかを調べるよりもさらに良いのは、Stackoverflow であなたの質問にかなり似ている質問を見つけたことです。残念ながら、そこには受け入れられた答えはありません。

しかし、その質問に対する最初の答えは、私が考えていたことに似たものへのリンクを提供します. Pascal Thivent の引用:

カスタム EntityPersister 実装 (カスタム Configuration を使用して Hibernate の初期化中に特定のエンティティを登録できます)

この例が Grails の Hibernate の例であることは事実ですが、プレーンな Java でもほぼ同じです。

 public void registerCustomEntityPersister(Configuration configuration) {
     final Iterator<PersistentClass> classesIterator = configuration.getClassMappings();
 while (classesIterator.hasNext()) {
    final PersistentClass persistentClass = classesIterator.next();
        if (checkIfIsOneTheClassesThatMatters(persistentClass)) {
          persistentClass.etEntityPersisterClass(CustomEntityPersister.class); 
        }
 }

これは実行可能に見えますが、EntityPersister の実装はそれほど簡単ではないように見えるため、あまりにも多くの作業が行われているように見えます。Hibernate が使用するデフォルトのもの (どれがどれかはわかりません) を拡張して、計測されたクラスの 1 つを返すために getProxy() メソッドをオーバーライドしようとすることができます。

まだ答えが見つからない場合は申し訳ありませんが、悲しいことに、私はHibernateの専門家ではありません。通常は箱から出してすぐに使用するだけです.javassistタグのために実際にあなたの質問にたどり着き、非常に興味深い.

少しでもお役に立てる情報をお伝えできれば幸いです。

于 2013-03-26T09:27:23.853 に答える