hibernate ManyToMany Map <string,entity =“”>其中map key是通过FK引用的属性</string,>

时间:2012-10-17 21:23:38

标签: hibernate many-to-many

我正在研究一个棘手的多对多映射,我想在我的实体中表示为地图。问题是,我希望map键是来自其中一个关联表的列,而不是映射表的列,通常就是这种情况。

帐户包含有关用户的基本信息,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>Map<String, Serializable>会更理想。但是,我希望map键是AccountMetadata键。

我一直在试验@MapKeyColumn@MapKeyJoinColumn而没有运气。我只能找到从连接表的列派生地图密钥的示例。

我希望那里有人做过类似的事情,或者至少对如何实现这一点有一些智慧。

谢谢!

1 个答案:

答案 0 :(得分: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%正确,但你应该抓住这个想法。