我有一个规则实体和一个测试实体(一对多相关),当创建一个规则时,会生成一个ruleId,我想使用ruleId进行测试。实体:
package io.avalor.webserver.rule;
import com.vladmihalcea.hibernate.type.array.EnumArrayType;
import com.vladmihalcea.hibernate.type.array.ListArrayType;
import com.vladmihalcea.hibernate.type.json.JsonBinaryType;
import io.avalor.webserver.account.Account;
import io.avalor.webserver.customquery.CustomQuery;
import io.avalor.webserver.persistency.AbstractEntity;
import io.avalor.webserver.rule.ruletest.RuleTest;
import io.avalor.webserver.rule.unittest.RuleUnitTest;
import lombok.Getter;
import lombok.Setter;
import org.hibernate.annotations.*;
import javax.persistence.*;
import javax.persistence.Entity;
import javax.persistence.Table;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
import java.util.List;
import java.util.Set;
@Entity
@Table
@SQLDelete(sql = "UPDATE rule SET deleted = true WHERE rule_id=?")
@Where(clause = "deleted=false")
@TypeDef(name = "list-array", typeClass = EnumArrayType.class, parameters = {@org.hibernate.annotations.Parameter(name = EnumArrayType.SQL_ARRAY_TYPE, value = "varchar")})
@TypeDef(name = "json", typeClass = JsonBinaryType.class)
@TypeDef(name = "list", typeClass = ListArrayType.class)
@Getter
@Setter
public class Rule extends AbstractEntity {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "rule_id")
private String id;
@Column
@NotBlank
private String name;
@OneToMany(fetch = FetchType.EAGER)
@Fetch(value = FetchMode.SUBSELECT)
@JoinTable(
name = "rule_unit_test",
joinColumns = {@JoinColumn(name = "rule_id", updatable = false)},
inverseJoinColumns = {@JoinColumn(name = "test_id", updatable = false)}
)
private List<RuleUnitTest> unitTests;
}
package io.avalor.webserver.rule.unittest;
import com.fasterxml.jackson.databind.JsonNode;
import io.avalor.webserver.persistency.AbstractEntity;
import io.avalor.webserver.rule.Rule;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import org.hibernate.annotations.*;
import javax.persistence.*;
import javax.persistence.Entity;
import javax.persistence.Table;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.NotNull;
import java.util.List;
@Entity
@Table
@Where(clause = "deleted=false")
@SQLDelete(sql = "UPDATE rule_unit_test SET deleted = true WHERE test_id=?")
@Getter
@Setter
@AllArgsConstructor
@NoArgsConstructor
public class RuleUnitTest {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "test_id")
private String id;
@NotNull
@JoinColumn(name = "rule_id", updatable = false)
@ManyToOne(fetch = FetchType.LAZY)
private Rule rule;
@Column
@NotBlank
private String name;
@NotEmpty
@Type(type = "json")
@Column(name = "test_data")
private List<JsonNode> testData;
}
我有一个具有以下方法的规则服务:
@Transactional
public RuleDto create(RuleDto ruleDto) {
Rule rule = ruleMapper.dtoToEntity(ruleDto);
Rule savedRule = ruleRepository.save(rule);
savedRule = saveUnitTestsIfExists(savedRule,ruleDto.getUnitTests());
// ruleRepository.save(savedRule);
return ruleMapper.entityToDto(savedRule);
}
private Rule saveUnitTestsIfExists(Rule rule, List<RuleUnitTestDto> unitTestsDto) {
if (CollectionUtils.isNotEmpty(unitTestsDto)) {
return unitTestService.create(rule,unitTestsDto);
}
return rule;
}
下面是unittestService中的代码:
public Rule create(Rule rule, List<RuleUnitTestDto> unitTestsDto) {
List<RuleUnitTestDto> limitedRuleUnitTestDtos = unitTestsDto;
if (unitTestsDto.size() > MAX_TESTS_PER_RULE) {
limitedRuleUnitTestDtos = unitTestsDto.subList(0, MAX_TESTS_PER_RULE);
}
List<RuleUnitTest> unitTests = ruleUnitTestMapper.buildBuildUnitTestFromUnitTest(rule, limitedRuleUnitTestDtos);
rule.setUnitTests(unitTestRepository.saveAll(unitTests));
return rule;
}
制图员:
package io.avalor.webserver.rule;
import io.avalor.webserver.rule.unittest.RuleUnitTest;
import io.avalor.webserver.rule.unittest.RuleUnitTestDto;
import org.mapstruct.*;
import java.util.*;
@Mapper(componentModel = "spring", unmappedTargetPolicy = ReportingPolicy.IGNORE)
public abstract class RuleMapper {
@Mapping(source = "account.id", target = "accountId")
@Mapping(target = "dataSourceTypes", ignore = true)
public abstract RuleDto entityToDto(Rule rule);
@Mapping(target = "account.id", source = "accountId")
@Mapping(target = "dataSourceTypes", ignore = true)
public abstract Rule dtoToEntity(RuleDto ruleDto);
@AfterMapping
public void setRuleProperties(@MappingTarget Rule rule, RuleDto ruleDto) {
if (rule.getId() != null) {
rule.setUnitTests(buildBuildUnitTestFromUnitTest(rule, ruleDto.getUnitTests()));
} else {
rule.setUnitTests(null);
}
}
@AfterMapping
public RuleDto enrichDto(@MappingTarget RuleDto ruleDto, Rule rule) {
if (rule.getUnitTests() != null) {
ruleDto.setUnitTests(rule.getUnitTests().stream().map(unitTest -> {
RuleUnitTestDto unitTestDto = new RuleUnitTestDto();
unitTestDto.setId(unitTest.getId());
unitTestDto.setName(unitTest.getName());
unitTestDto.setTestData(unitTest.getTestData());
unitTestDto.setRuleId(rule.getId());
return unitTestDto;
}).toList());
}
return ruleDto;
}
public List<RuleUnitTest> buildBuildUnitTestFromUnitTest(Rule rule, List<RuleUnitTestDto> unitTestDtos) {
if (unitTestDtos == null)
return Collections.emptyList();
List<RuleUnitTest> unitTestsList = new ArrayList<>();
for (RuleUnitTestDto unitTestDto : unitTestDtos) {
unitTestsList.add(new RuleUnitTest(null, rule, unitTestDto.getName(), unitTestDto.getTestData()));
}
return unitTestsList;
}
}
我正在尝试发送以下身体请求:
{
"name": "rule1",
"unitTests":[{
"name":"blah blah",
"testData":[{"a":"b"}]
}]
}
当尝试保存一个规则和一个单元测试时,我得到以下错误(说name和testData是null,这在调试时不是真的):
ERROR: null value in column "name" of relation "rule_unit_test" violates not-null constraint
Detail: Failing row contains (p0n9vr, 07rplw, null, null).
我真的不知道为什么会这样,有什么想法吗?
1条答案
按热度按时间jtw3ybtb1#
你可能想看看JPA教程,了解双向OneToMany和ManyToOneMap是如何工作的,但你可能应该在Rule->RuleUnitTestMap中使用'mappedby':
还要注意的是,在格式化JSON数据时,您需要确保此关系的两端都已设置-或者更重要的是,每个RuleUnitTest.rule引用都已正确设置,因为这是拥有(因此控制)外键列值的关系。