私見、そのクラスに @Version アノテーションが付けられたフィールドのタイプを配置する必要があります。これはそのままで、継承でも機能すると思います。
タイプが事前にわからない場合は、標準のリフレクションを使用します。宣言されたすべてのフィールドを繰り返し処理し、注釈に @Version 注釈が含まれているかどうかを確認します。見つからない場合は、見つかるまでスーパークラスを確認してください...
public static Field getVersionField(Object entity) {
Class<?> myClass = entity.getClass();
do {
Field[] fields = myClass.getDeclaredFields();
for(Field field:fields) {
if(field.getAnnotation(Version.class)!=null) {
return field;
}
}
} while((myClass=myClass.getSuperclass())!=null);
return null;
}
注意: Class.getFields()はパブリック フィールドのみを返すため、より優れた代替手段のように見えますが、機能しません。
この Class オブジェクトによって表されるクラスまたはインターフェイスのすべてのアクセス可能なパブリック フィールドを反映する Field オブジェクトを含む配列を返します。
編集上記は、フィールドで @Version アノテーションが厳密に使用されている場合にのみ機能します。ただし、Konstantin Pribluda が指摘したように、この注釈はメソッドにも付けることができます。これは、次の 2 つのことを意味します。
- メソッドもチェックする必要があります
- メソッドはインターフェースによって定義できるため、インターフェースもチェックする必要があります...
これは、単純なサイクルを再帰的なグラフ トラバーサルに変換する必要があることも意味します...
public static Method getVersionMethod(Class<?> myClass) {
Method[] methods = myClass.getDeclaredMethods();
for(Method method : methods) {
if(method.getAnnotation(Version.class)!=null) {
return method;
}
}
if(myClass.getSuperclass()!=null) {
Class<?> returned = getVersionMethod(myClass.getSuperclass());
if(returned!=null) {
return returned;
}
}
for(Class<?> interfaceToCheck : myClass.getInterfaces()) {
Class<?> returned = getVersionMethod(interfaceToCheck);
if(returned!=null) {
return returned;
}
}
return null;
}