すべてのJPAエンティティークラスは、次のように定義されているEntityと呼ばれるインターフェイスを実装しています。
public interface Entity extends Serializable {
// some methods
}
私のJPAエンティティの一部のフィールドには、その上に@Column
アノテーションがあり、一部にはありません。 MyEntity
クラスは以下のように定義されています:
@Entity
public class MyEntity implements Entity {
@Id
private Long id; // Assume that it is auto-generated using a sequence.
@Column(name="field1")
private String field1;
private SecureString field2; //SecureString is a custom class
//getters and setters
}
私の削除メソッドはエンティティを受け入れます。
@Override
public void delete(Entity baseEntity) {
em.remove(baseEntity); //em is entityManager
}
Deleteメソッドが呼び出されるときはいつでも、deleteメソッド内に3つのものが必要です。
1)MyEntity
タイプのSecureString
のフィールド
2)DB内の特定のフィールドの列名(フィールドに@Column
アノテーションがある場合とない場合があります)
3)id
フィールドの値
delete()
メソッドが呼び出されたとき、どのエンティティに対して呼び出されたかがわからないことに注意してください。MyEntity1
、MyEntity2
などの場合があります。
以下のようなことを試みました:
for (Field field : baseEntity.getClass().getFields()) {
if (SecureString.class.isAssignableFrom(field.getType())) {
// But the field doesn't have annotation @Column specified
Column column = field.getAnnotation(Column.class);
String columnName = column.name();
}
}
ただし、これはフィールドに@Column
アノテーションが付いている場合にのみ機能します。また、私が必要とする他の2つのことはできません。何か案は?
Hibernateは、さまざまな 命名戦略 を使用して、暗黙的に定義されたプロパティ名をマップできます(@Column(name = "...")なし)。 「物理」名を付けるには、Hibernateの内部に飛び込む必要があります。まず、EntityManagerFactory
をサービスに接続する必要があります。
_@Autowired
private EntityManagerFactory entityManagerFactory;
_
次に、クラスのAbstractEntityPersister
を取得する必要があります
_ SessionFactory sessionFactory = entityManagerFactory.unwrap(SessionFactory.class);
AbstractEntityPersister persister = ((AbstractEntityPersister)sessionFactory.getClassMetadata(baseEntity.getClass()));
_
第3に、コードはほぼ完成です。 @Columnアノテーションの有無にかかわらず、両方のケースを処理する必要があります。これを試して:
_for (Field field : baseEntity.getClass().getFields()) {
if (SecureString.class.isAssignableFrom(field.getType())) {
String columnName;
if (field.isAnnotationPresent(Column.class)) {
columnName = field.getAnnotation(Column.class).name();
} else {
String[] columnNames = persister.getPropertyColumnNames(field.getName());
if (columnNames.length > 0) {
columnName = columnNames[0];
}
}
}
}
_
getPropertyColumnNames()
は、主キーの一部ではない「プロパティ」フィールドのみを取得することに注意してください。キー列名を取得するには、getKeyColumnNames()
を使用します。
そして、id
フィールドについて。本当にすべての@Idを子クラスに含める必要がありますか? @IdをEntity
クラスに移動し、このクラスを@MappedSuperclassアノテーションでマークする方がいいでしょう。次に、baseEntity.getId();
だけでそれを取得できます