【发布时间】:2021-09-28 05:02:44
【问题描述】:
很好,我正在创建一个带有 spring 和 elastic 的 rest api,但是在它的构建过程中我遇到了一个技术问题,结果我需要保存点击了收藏的公司的用户,为此我有 ManyToMany 列表(以便它休眠它生成中间表并将数据保存在两个实体中),系统在休眠中完美运行并将关系正确保存在数据库中,但是当我执行时我调用弹性存储库的保存方法它返回一个堆栈溢出。
如果我添加一个标签以使其明显(在 2 个实体处)它可以正常工作,但我需要弹性以某种方式保持这种关系,我曾想过复制代码并有 2 个列表,一个带有模型,另一个带有ids(模型保存在数据库中,id 字符串保存在 elastic 中)但在我复制代码并做可能的垃圾之前,我想在这里问一下!
java.lang.StackOverflowError: null
at java.util.concurrent.ConcurrentHashMap.get(ConcurrentHashMap.java:936) ~[na:1.8.0_231]
at org.springframework.data.convert.CustomConversions$TargetTypes.computeIfAbsent(CustomConversions.java:532) ~[spring-data-commons-2.4.5.jar:2.4.5]
at org.springframework.data.convert.CustomConversions$ConversionTargetsCache.computeIfAbsent(CustomConversions.java:497) ~[spring-data-commons-2.4.5.jar:2.4.5]
at org.springframework.data.convert.CustomConversions.getCustomWriteTarget(CustomConversions.java:348) ~[spring-data-commons-2.4.5.jar:2.4.5]
at org.springframework.data.elasticsearch.core.convert.MappingElasticsearchConverter.writeInternal(MappingElasticsearchConverter.java:588) ~[spring-data-elasticsearch-4.2.3.jar:4.2.3]
at org.springframework.data.elasticsearch.core.convert.MappingElasticsearchConverter.writeCollectionInternal(MappingElasticsearchConverter.java:839) ~[spring-data-elasticsearch-4.2.3.jar:4.2.3]
at org.springframework.data.elasticsearch.core.convert.MappingElasticsearchConverter.createCollection(MappingElasticsearchConverter.java:753) ~[spring-data-elasticsearch-4.2.3.jar:4.2.3]
at org.springframework.data.elasticsearch.core.convert.MappingElasticsearchConverter.writeProperty(MappingElasticsearchConverter.java:713) ~[spring-data-elasticsearch-4.2.3.jar:4.2.3]
at org.springframework.data.elasticsearch.core.convert.MappingElasticsearchConverter.writeProperties(MappingElasticsearchConverter.java:674) ~[spring-data-elasticsearch-4.2.3.jar:4.2.3]
at org.springframework.data.elasticsearch.core.convert.MappingElasticsearchConverter.writeInternal(MappingElasticsearchConverter.java:633) ~[spring-data-elasticsearch-4.2.3.jar:4.2.3]
at org.springframework.data.elasticsearch.core.convert.MappingElasticsearchConverter.writeInternal(MappingElasticsearchConverter.java:611) ~[spring-data-elasticsearch-4.2.3.jar:4.2.3]
at org.springframework.data.elasticsearch.core.convert.MappingElasticsearchConverter.writeCollectionInternal(MappingElasticsearchConverter.java:839) ~[spring-data-elasticsearch-4.2.3.jar:4.2.3]
at org.springframework.data.elasticsearch.core.convert.MappingElasticsearchConverter.createCollection(MappingElasticsearchConverter.java:753) ~[spring-data-elasticsearch-4.2.3.jar:4.2.3]
at org.springframework.data.elasticsearch.core.convert.MappingElasticsearchConverter.writeProperty(MappingElasticsearchConverter.java:713) ~[spring-data-elasticsearch-4.2.3.jar:4.2.3]
at org.springframework.data.elasticsearch.core.convert.MappingElasticsearchConverter.writeProperties(MappingElasticsearchConverter.java:674) ~[spring-data-elasticsearch-4.2.3.jar:4.2.3]
at org.springframework.data.elasticsearch.core.convert.MappingElasticsearchConverter.writeInternal(MappingElasticsearchConverter.java:633) ~[spring-data-elasticsearch-4.2.3.jar:4.2.3]
at org.springframework.data.elasticsearch.core.convert.MappingElasticsearchConverter.writeInternal(MappingElasticsearchConverter.java:611) ~[spring-data-elasticsearch-4.2.3.jar:4.2.3]
at org.springframework.data.elasticsearch.core.convert.MappingElasticsearchConverter.writeCollectionInternal(MappingElasticsearchConverter.java:839) ~[spring-data-elasticsearch-4.2.3.jar:4.2.3]
我把模型的两个属性传给你
商务舱
@Builder.Default
@ManyToMany(mappedBy = "commercesFav", cascade = CascadeType.ALL, fetch = FetchType.LAZY, targetEntity = UserImpl.class)
private List<User> usersFav = new ArrayList<>();
类用户
@Builder.Default
@ManyToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY, targetEntity = CommerceImpl.class)
@JoinTable(name="favorites",
joinColumns=@JoinColumn(name="user_id", referencedColumnName="id"),
inverseJoinColumns=@JoinColumn(name="commerce_id", referencedColumnName="id"))
private List<Commerce> commercesFav = new ArrayList<>();
我正在使用龙目岛,但我认为这无关紧要
顺便说一句,弹性存储库是基本的、空的,它们什么都没有。我尝试在其中一些、Commerce 和 User 中包含 Transient 标签,但它不起作用
如何让 elasticsearch 正确保存对象?
谢谢!
我最终从项目中删除了所有lombok,我无法调试代码,现在代码更稳定,更可控,如果您对复杂代码有同样的问题,我建议删除像lombok这样的库
尽我所能,感谢 JsonManagedReference 和 JsonBackReference,我只能正确返回双向列表
@ManyToMany(targetEntity = CommerceImpl.class)
@JsonBackReference
@JoinTable(name = "favorites",
joinColumns = @JoinColumn(name = "user_id", referencedColumnName = "id"),
inverseJoinColumns = @JoinColumn(name = "commerce_id", referencedColumnName = "id"))
@org.springframework.data.annotation.Transient
private Set<Commerce> commercesFav = new HashSet<>();
@ManyToMany(targetEntity = UserImpl.class, mappedBy = "commercesFav")
@JsonManagedReference
@org.springframework.data.annotation.Transient
private Set<User> usersFav = new HashSet<>();
我正在从控制器中保存 2 个模型,它们只能从商店中恢复(我认为按照设计,最好将其反转并从用户那里返回)
@PostMapping("/commerce/fav/{identifier}")
public ResponseEntity addFavoriteCommerceToUser(@PathVariable String identifier, @AuthenticationPrincipal UserDetails userDetails, HttpServletRequest request) {
ResponseEntity<Object> responseEntity = ResponseEntity.status(HttpStatus.NOT_FOUND)
.headers(RequestCustomUtil.getHeader(request)).body(ResponseUtil.beanNotFound(Commerce.class.getName()));
try {
Optional<Commerce> commerce = commerceHandle.get(identifier);
if (commerce.isPresent()) {
User user = userHandle.findByUsername(userDetails.getUsername());
Commerce commerceEntity = commerce.get();
commerceEntity.getUsersFav().add(user);
user.getCommercesFav().add(commerce.get());
commerce = commerceHandle.create(commerceEntity);
userHandle.save(user);
boolean isActualUser = commerce.get().getUser().getIdentifier().equals(user.getIdentifier());
responseEntity = ResponseEntity.ok(CommerceBean.CommerceBeanComplete(commerce.get(), isActualUser));
}
} catch (CommerceException e) {
LOG.error(e.getMessage());
}
return responseEntity;
}
【问题讨论】:
-
Elasticsearch 不是关系数据库。在 Elasticsearch 中,索引中的文档之间没有 n-to-m 关系这样的概念(这不是 Spring Data Elasticsearch 特有的)。
标签: spring-boot rest elasticsearch spring-data-elasticsearch