4

私は自分のエンティティでマップとして表現したいトリッキーな多対多のマッピングに取り組んでいます。キャッチは、マップキーを、通常のようにマッピングテーブルの列ではなく、関連付けられたテーブルの1つの列にしたいということです。

Account はユーザーに関する基本情報を保持し、AccountMetadata はアカウントが持つ可能性のあるすべての属性を定義し、Account_MetadataAccount は考えられる AccountMetadata ごとに特定のアカウントの値を定義します。

これらを次のエンティティにマッピングしました。

@Entity
@Table(name = "ACCOUNT")
public class Account implements Serializable
{
  @Id
  @Column(name = "ACCOUNT_ID")
  private Long accountId;

  @OneToMany(fetch = FetchType.LAZY, cascade = CascadeType.ALL, mappedBy = "pk.account")
  private Set<AccountMetadataAccount> metadata = new HashSet<AccountMetadataAccount>();
...
}

@Entity
@Table(name = "ACCOUNT_METADATA")
public class AccountMetadata implements Serializable
{
  @Id
  @Column(name = "ACCOUNT_METADATA_ID")
  private Long accountMetadataId;

  @Column(name = "KEY", unique = true)
  private String key;

  @Column(name = "TYPE")
  private Class<?> type;
...
}

@Entity
@Table(name = "ACCOUNT_METADATA_ACCOUNT")
@AssociationOverrides({
                @AssociationOverride(name = "pk.account",
                  joinColumns = @JoinColumn(name = "ACCOUNT_ID")),
                @AssociationOverride(name = "pk.metadata",
                  joinColumns = @JoinColumn(name = "ACCOUNT_METADATA_ID"))
              })
public class AccountMetadataAccount implements Serializable
{
  @EmbeddedId
  private AccountMetadataAccountId pk;

  @Column(name = "VALUE")
  private Serializable value;
...
}

@Embeddable
public class AccountMetadataAccountId implements Serializable
{
  @ManyToOne
  private AccountInfo account;

  @ManyToOne
  private AccountMetadataInfo metadata;
...
}

これはすべてうまくいきます。私の問題は、アカウントのメタデータ セットです。これは理想的ではありません。値を調べたいメタデータ キーがある場合は、正しいエントリが見つかるまで Set 全体を反復処理する必要があります。私たちのシステムでは、これらが何百もある可能性があります。Map<String, AccountMetadataAccount>orのMap<String, Serializable>方が理想的だと思いました。ただし、マップ キーを AccountMetadata キーにしたいと思います。

私は実験してきましたが、運がありません@MapKeyColumn@MapKeyJoinColumnマップ キーが結合テーブルの列から派生している例しか見つかりません。

誰かが似たようなことをしたか、少なくともこれを達成する方法についての知恵の言葉を持っていることを願っています。

ありがとう!

4

1 に答える 1

0

メンバー変数の代わりにgetterとsetterを使用するのはどうですか?このような:

@Transient
private Map<String, AccountMetadataAccount> metadata = new HashMap<>();

@OneToMany(fetch = FetchType.LAZY, cascade = CascadeType.ALL, mappedBy = "pk.account")
private Collection<AccountMetadataAccount> getMetadata() {
  return metadata.values();
}

private void setMetadata(Collection<AccountMetadataAccount> metaSet) {
   metadata.clear();
   for (AccountMetadataAccount meta : metaSet) {
     metadata.put(meta.key, meta);
   }
}

アノテーションの代わりにxmlマッピングファイルを使用していますが、コードをテストしなかったため、100%正しくない可能性がありますが、アイデアを理解する必要があります。

于 2012-10-18T06:58:36.893 に答える