我是 Hibernate Search 的新手,我將 Hibernate Search6.1.4.Final與 Spring Boot 2.6.7、 Spring Data JPA2.6.7和 PostgreSQL一起使用14。我有以下架構:
CREATE TABLE manufacturer
(
id UUID,
PRIMARY KEY (id)
);
CREATE TABLE flavor
(
id UUID,
PRIMARY KEY (id)
);
CREATE TABLE tobacco
(
id UUID,
name VARCHAR NOT NULL,
manufacturer_id UUID NOT NULL,
PRIMARY KEY (id)
);
ALTER TABLE tobacco
ADD CONSTRAINT fk_manufacturer FOREIGN KEY (manufacturer_id) REFERENCES manufacturer (id);
CREATE TABLE tobacco_flavor
(
tobacco_id UUID REFERENCES tobacco (id) ON UPDATE CASCADE ON DELETE CASCADE,
flavor_id UUID REFERENCES flavor (id) ON UPDATE CASCADE,
CONSTRAINT tobacco_flavor_pk PRIMARY KEY (tobacco_id, flavor_id)
);
我在 Tobacco 和 Manufacturer 之間有一個單向的 ManyToOne 關系,在 Tobacco 和 Flavor 之間有另一個單向的 ManyToMany 關系。索引物體是:
@Data
@Entity
@Indexed
@NoArgsConstructor
@AllArgsConstructor
@Builder(toBuilder = true)
@EqualsAndHashCode(of = "id")
@EntityListeners(AuditingEntityListener.class)
public class Tobacco {
@Id
@GeneratedValue
private UUID id;
@NotBlank
@FullTextField(analyzer = "name")
@FullTextField(name = "name_prefix", analyzer = "name_prefix", searchAnalyzer = "name")
private String name;
@ManyToOne(fetch = FetchType.EAGER) // this is EAGER because hibernate cannot serialize the proxy wrapper when using LAZY
@JoinColumn(name = "manufacturer_id", nullable = false)
private Manufacturer manufacturer;
@ManyToMany(cascade = {
CascadeType.MERGE
})
@JoinTable(name = "tobacco_flavor",
joinColumns = @JoinColumn(name = "tobacco_id", referencedColumnName = "id"),
inverseJoinColumns = @JoinColumn(name = "flavor_id", referencedColumnName = "id")
)
private Set<Flavor> flavors;
}
我正在使用以下 lucene 配置器:
@Component("luceneTobaccoAnalysisConfigurer")
public class LuceneTobaccoAnalysisConfigurer implements LuceneAnalysisConfigurer {
@Override
public void configure(LuceneAnalysisConfigurationContext context) {
context.analyzer("name").custom()
.tokenizer("standard")
.tokenFilter("lowercase")
.tokenFilter("asciiFolding");
context.analyzer("name_prefix").custom()
.tokenizer("standard")
.tokenFilter("lowercase")
.tokenFilter("asciiFolding")
.tokenFilter("edgeNGram")
.param("minGramSize", "2")
.param("maxGramSize", "7");
}
}
我正在執行以下查詢:
public List<Tobacco> find(String query) {
return Search.session(entityManager)
.search(Tobacco.class)
.where(f -> f.match()
.fields("barcode", "name").boost(2.0f)
.fields("name_prefix")
.matching(query)
.fuzzy()
)
.fetchHits(10);
}
當我執行查詢時,Hibernate 使用連接執行 5 個 SELECT 查詢而不是 1 個。我想始終按煙草名稱查詢并檢索與其關聯的所有物體(口味和制造商),有沒有辦法指示 Hibernate Search 有效地執行連接查詢?
uj5u.com熱心網友回復:
要控制 Hibernate Search 加載的內容,您可以通過在構建搜索查詢時呼叫來利用Hibernate Search 中的 JPA 物體圖。.loading( o -> o.graph( someGraph, GraphSemantic.FETCH ) )
像這樣的東西?
public List<Tobacco> find(String query) {
EntityGraph<Tobacco> graph = entityManager.createEntityGraph( Tobacco.class );
graph.addAttributeNodes( "manufacturer" );
graph.addAttributeNodes( "flavors" );
return Search.session(entityManager)
.search(Tobacco.class)
.where(f -> f.match()
.fields("barcode", "name").boost(2.0f)
.fields("name_prefix")
.matching(query)
.fuzzy()
)
.loading( o -> o.graph( graph, GraphSemantic.FETCH ) )
.fetchHits(10);
}
但是,根據您的模型和物體圖,這可能會導致執行多個查詢(由于 Hibernate ORM 中的實作限制)。在這種情況下,您可以探索這些會影響任何加載的替代解決方案,而不僅僅是在 Hibernate Search 中加載:
- 用于
@Fetch(FetchMode.JOIN)您的flavors關聯。 - 利用 Hibernate ORM 的批量獲取只觸發兩個 SQL 查詢(一個用于煙草實體,一個用于其口味):請參閱
batch_fetch_size配置屬性和@BatchSize注釋。
轉載請註明出處,本文鏈接:https://www.uj5u.com/gongcheng/473589.html
