web-dev-qa-db-ja.com

JPAの1対多のフィルタリング

いくつかのエンティティをネストしています。ただし、取得時に、アクティブなエンティティのみを取得する必要があります。

@Entity
public class System {
  @Id
  @Column(name = "ID")
  private Integer id;

  @OneToMany(mappedBy = "system")
  private Set<Systemproperty> systempropertys;
}

@Entity
public class Systemproperty {
  @Id
  @Column(name = "ID")
  private Integer id;

  @Id
  @Column(name = "ACTIVE")
  private Integer active;
}

Systempropertiesをリクエストするときは、activeactive = 1)のプロパティのみを取得したいと思います。

周りを検索すると、いくつかの hibernateアノテーションサブクエリ を使用する可能性が見つかりました。しかし、どちらも私には実際には機能しません。現在Hibernateを使用していますが、現在は積極的な読み込みを使用する必要があり、パフォーマンスの問題が発生する可能性があるため、Eclipselinkに置き換えることを検討しています。いくつかのレベルをネストしているため、サブクエリは実際にはうまく機能しません。

Eclipselinkには @ Customizer アノテーションが機能しているようですが、休止状態とは異なる概念に従っているようです@FilterDef注釈であり、切り替え時に追加のオーバーヘッドが発生します。

@JoinColumnそれ以上のフィルタリングは許可されていないようです。この問題を解決するための標準的なJPAの方法はありますか?

17
Udo Held

AFAIKには、これを行うためのポータブルJPAベースの方法はありません。クリーンですが、少し非効率的な解決策は、Java側ですべてを実行し、マップされたsystempropertysを手動で繰り返し、アクティブなプロパティの不変のセットを返すゲッターgetActiveSystemproperties()を作成することです。

6
Adam Dyga

@ Where でそれを行う別の休止状態の方法:

@Entity
public class System {
  @Id
  @Column(name = "ID")
  private Integer id;

  @OneToMany(mappedBy = "system")
  @Where(clause = "active = true")
  private Set<Systemproperty> systempropertys;
}

@Entity
public class Systemproperty {
  @Id
  @Column(name = "ID")
  private Integer id;

  @Id
  @Column(name = "ACTIVE")
  private Integer active;
}
7
danial

JPAの方法はありませんが、Hibernate filetrsを試すことができます: http://docs.jboss.org/hibernate/core/3.6/reference/en-US/html_single/#objectstate-filters

1
hurtledown

EclipseLinkで同様の問題を解決する必要がありました。特別なSessionCustomizerを使用し、OneToManyアノテーションのマッピング条件を変更しました。 MaybeeHibernateにも似たようなものがあります。

カスタマイザを永続性ユニットに追加します。

props.put(PersistenceUnitProperties.SESSION_CUSTOMIZER,MySessionCustomizer.class.getName());
EntityManagerFactory factory = new PersistenceProvider().createEntityManagerFactory(pu.getPersistenceUnitName(), props);

カスタマイザーのフラグメント:

public class MySessionCustomizer implements SessionCustomizer {
    public void customize(Session session) throws Exception {
        final Map<?, ?> descs = session.getDescriptors();
    if (descs != null)
    {
      // This code assumes single table per descriptor!
      for (final Object descObj : descs.values())
      {
        final ClassDescriptor desc = (ClassDescriptor) descObj;
        final Class<?> sourceClass = desc.getJavaClass();

        for (DatabaseMapping mapping : desc.getMappings())
        {
          if (mapping instanceof OneToManyMapping)
          {
            final OneToManyMapping collectionMapping = ((OneToManyMapping) mapping);

            // create default foreign key condition (nescessary):
            final DatabaseField sourceField = mapping.getSourceKeyFields().get(0);
            final DatabaseField targetField = mapping.getTargetForeignKeyFields().get(0);
            final Expression defaultFkExpression =  new ExpressionBuilder(mapping.getReferenceClass()).getParameter(sourceField).equal(eb.getField(targetField));

            // add filter condition "additionalExpression"
            final Expression finalExpression = defaultFkExpression.and(additionalExpression);

             // SET default foreign key condition and filter condition to mapping
             mapping.setSelectionCriteria(finalExpression);
          }
        }
      }
    }
    }
}
1
David Kacetl