基本的にいくつかのテーブルの結合であるいくつかのテーブルとビューを持つ PostgreSQL 8.4 データベースがあります。NetBeans 7.2 (ここで説明) を使用して、これらのビューとテーブルから派生した REST ベースのサービスを作成し、それらを Glassfish 3.1.2.2 サーバーにデプロイしました。
ビューの構築に使用される一部のテーブルのコンテンツを非同期的に更新する別のプロセスがあります。ビューとテーブルを直接クエリして、これらの変更が正しく行われたことを確認できます。ただし、REST ベースのサービスから取得した場合、値はデータベース内の値と同じではありません。これは、JPA がデータベース コンテンツのローカル コピーを Glassfish サーバーにキャッシュしており、JPA が関連するエンティティを更新する必要があるためだと思います。
NetBeans が生成する AbstractFacade クラスにいくつかのメソッドを追加しようとしました。
public abstract class AbstractFacade<T> {
private Class<T> entityClass;
private String entityName;
private static boolean _refresh = true;
public static void refresh() { _refresh = true; }
public AbstractFacade(Class<T> entityClass) {
this.entityClass = entityClass;
this.entityName = entityClass.getSimpleName();
}
private void doRefresh() {
if (_refresh) {
EntityManager em = getEntityManager();
em.flush();
for (EntityType<?> entity : em.getMetamodel().getEntities()) {
if (entity.getName().contains(entityName)) {
try {
em.refresh(entity);
// log success
}
catch (IllegalArgumentException e) {
// log failure ... typically complains entity is not managed
}
}
}
_refresh = false;
}
}
...
}
次に、 NetBeans が生成するdoRefresh()
各メソッドから呼び出します。find
通常何が起こるかは、次のIllegalArgumentsException
ような状態でスローされますCan not refresh not managed object: EntityTypeImpl@28524907:MyView [ javaType: class org.my.rest.MyView descriptor: RelationalDescriptor(org.my.rest.MyView --> [DatabaseTable(my_view)]), mappings: 12].
そのため、ビューに関連付けられたエンティティを正しく更新して最新の状態にする方法についての提案を探しています。
更新:根本的な問題についての私の理解が正しくなかったことが判明しました。以前に投稿した別の質問に多少関連しています。つまり、ビューには一意の識別子として使用できる単一のフィールドがありませんでした。NetBeans が必要 ID フィールドを選択したので、マルチパート キーであるべきものの一部を選択しただけです。これは、データベースに同じ ID フィールドを持つレコードがあり、残りのレコードが異なる場合でも、特定の ID フィールドを持つすべてのレコードが同一であるという動作を示しました。JPA は、一意の識別子であると私が言ったものを調べるだけで、最初に見つかったレコードを取得するだけでした。
一意の識別子フィールドを追加することでこれを解決しました (マルチパート キーを正しく機能させることはできませんでした)。