我具有以下类定义,对于类UserAdAccount,它同时使用adAccountId和userId作为其复合主键。我需要将此复合主键用作索引的文档ID。
阅读《 Hibernate Search 5.11.5.Final:参考指南》(这是我正在使用的版本)后,我发现了以下内容: 功能更强大的TwoWayFieldBridge接口允许您将多个字段存储到索引中,这对于复合属性很有用,但实现起来较为复杂。
我不确定如何继续使用TwoWayFieldBridge在这里解决我的需求。任何帮助表示赞赏!
@Entity (name = "JHI_USER_AD_ACCOUNT")
@Indexed
@IdClass(UserAdAccountId.class)
@Getter
@Setter
public class UserAdAccount implements SearchableEntity, Serializable {
//newly added id field with two way string bridge
@DocumentId
@Column(name = "ID")
@FieldBridge(impl = UserAdAccoutPrimaryKeyBridge.class)
private UserAdAccountId id;
@Id
@Column(name = "AD_ACCOUNT_ID")
@GenericGenerator( name = "native", strategy = "native")
@Field
private Long adAccountId;
@Id
@Column(name = "USER_ID")
@GenericGenerator( name = "native", strategy = "native")
@Field
private Long userId;
@ManyToOne
@JoinColumn(name = "USER_ID", referencedColumnName = "ID", updatable = false, insertable = false)
@JsonIgnore
private User user;
@ManyToOne
@JoinColumn(name = "AD_ACCOUNT_ID", referencedColumnName = "ID", updatable = false, insertable = false)
@IndexedEmbedded(includePaths = "name")
private AdAccount adAccount;
}
@Getter
@Setter
@EqualsAndHashCode(of = {"userId", "adAccountId"})
public class UserAdAccountId implements Serializable {
private Long userId;
private Long adAccountId;
}
public class UserAdAccoutPrimaryKeyBridge implements TwoWayStringBridge {
@Override
public String objectToString(Object object) {
UserAdAccountId userAdAccountId = (UserAdAccountId) object;
StringBuilder buffer = new StringBuilder();
buffer.append(userAdAccountId.getUserId()).append("-").append(userAdAccountId.getAdAccountId());
return buffer.toString();
}
@Override
public Object stringToObject(String value) {
String[] components = value.split("-");
UserAdAccountId userAdAccountId = new UserAdAccountId();
userAdAccountId.setUserId(Long.parseLong(components[0]));
userAdAccountId.setAdAccountId(Long.parseLong(components[1]));
return userAdAccountId;
}
}
答案 0 :(得分:0)
双向过程很重要,即: [...]
- 对于TwoWayFieldBridge:对于给定的文档,get()返回的对象必须与最初传递给set()的对象相同。
此外,为了使TwoWayFieldBridge实现在文档标识符上使用时正确运行,void set(字符串名称,对象值,文档文档,LuceneOptions luceneOptions)方法必须遵循以下约定向文档添加字段:>
- 字段名称必须是name参数中提供的名称
- 该字段值必须编码为字符串
- 字段值必须与value参数的给定值唯一
- 字段值必须与给定value参数的objectToString方法返回的值匹配。
您可以找到复合主键on github的示例实现:
> var.x[1].name
second
> var.x[1]["name"]
second
或者,如果您确定ID的组成部分不包含某个字符串,则可以将该字符串用作ID索引形式的分隔符,并且可以进行转换索引形式返回到原始ID。这意味着您可以使用更简单的public class PersonPKBridge implements TwoWayFieldBridge, MetadataProvidingFieldBridge {
private static final String FIRST_NAME_SUFFIX = "_content.firstName";
private static final String LAST_NAME_SUFFIX = "_content.lastName";
@Override
public void configureFieldMetadata(String name, FieldMetadataBuilder builder) {
builder.field( name + FIRST_NAME_SUFFIX, FieldType.STRING )
.field( name + LAST_NAME_SUFFIX, FieldType.STRING );
}
@Override
public Object get(String name, Document document) {
PersonPK id = new PersonPK();
IndexableField field = document.getField( name + FIRST_NAME_SUFFIX );
id.setFirstName( field.stringValue() );
field = document.getField( name + LAST_NAME_SUFFIX );
id.setLastName( field.stringValue() );
return id;
}
@Override
public String objectToString(Object object) {
PersonPK id = (PersonPK) object;
StringBuilder sb = new StringBuilder();
sb.append( id.getFirstName() ).append( " " ).append( id.getLastName() );
return sb.toString();
}
@Override
public void set(String name, Object value, Document document, LuceneOptions luceneOptions) {
PersonPK id = (PersonPK) value;
//store each property in a unique field
luceneOptions.addFieldToDocument( name + FIRST_NAME_SUFFIX, id.getFirstName(), document );
luceneOptions.addFieldToDocument( name + LAST_NAME_SUFFIX, id.getLastName(), document );
//store the unique string representation in the named field
luceneOptions.addFieldToDocument( name, objectToString( id ), document );
}
}
并依靠串联/分割:
TwoWayStringBridge