web-dev-qa-db-ja.com

JPAエンティティの列名を取得する方法

すべての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()メソッドが呼び出されたとき、どのエンティティに対して呼び出されたかがわからないことに注意してください。MyEntity1MyEntity2などの場合があります。

以下のようなことを試みました:

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つのことはできません。何か案は?

7
Aman

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();だけでそれを取得できます

5
Anatoly Shamov