feat(jpa): 补充方法查询的测试用例
This commit is contained in:
@@ -94,6 +94,10 @@
|
||||
</compilerArgs>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-maven-plugin</artifactId>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</project>
|
||||
@@ -56,7 +56,7 @@ public class TestApplication extends AbstractTestApplication {
|
||||
testCrud();
|
||||
testDelete();
|
||||
testQuery();
|
||||
testNative();
|
||||
testMethodQuery();
|
||||
|
||||
System.exit(0);
|
||||
}
|
||||
@@ -910,7 +910,383 @@ public class TestApplication extends AbstractTestApplication {
|
||||
companyRepository.deleteAllInBatch();
|
||||
}
|
||||
|
||||
private void testNative() {
|
||||
private void testMethodQuery() {
|
||||
formatLog("准备 Query Method 测试数据");
|
||||
var company1 = companyRepository.save(Company.builder().name("TechCorp").members(100).build());
|
||||
var company2 = companyRepository.save(Company.builder().name("DataInc").members(50).build());
|
||||
var company3 = companyRepository.save(Company.builder().name("CloudSys").members(150).build());
|
||||
|
||||
var skill1 = Skill.builder().name("Java").description("Java 编程语言").build();
|
||||
var skill2 = Skill.builder().name("Python").description("Python 编程语言").build();
|
||||
var skill3 = Skill.builder().name("Spring").description("Spring 框架").build();
|
||||
var skill4 = Skill.builder().name("MySQL").description("MySQL 数据库").build();
|
||||
|
||||
var emp1 = employeeRepository.save(Employee.builder()
|
||||
.name("Alice").age(30).role(Employee.Role.ADMIN).code("E001")
|
||||
.salary(new BigDecimal("50000.00")).bonus(new BigDecimal("5000.00"))
|
||||
.active(true).company(company1)
|
||||
.address(Address.builder().street("Main St").city("Beijing").state("Beijing").zipCode("100000").country("China").build())
|
||||
.skills(Set.of(skill1, skill3))
|
||||
.hobbies(List.of("Reading", "Swimming"))
|
||||
.properties(Map.of("department", "Engineering", "level", "Senior"))
|
||||
.connections(Map.of(Employee.ConnectionType.EMAIL, "alice@example.com"))
|
||||
.build());
|
||||
|
||||
var emp2 = employeeRepository.save(Employee.builder()
|
||||
.name("Bob").age(25).role(Employee.Role.USER).code("E002")
|
||||
.salary(new BigDecimal("40000.00")).bonus(new BigDecimal("4000.00"))
|
||||
.active(true).company(company2)
|
||||
.address(Address.builder().street("Oak Ave").city("Shanghai").state("Shanghai").zipCode("200000").country("China").build())
|
||||
.skills(Set.of(skill2))
|
||||
.hobbies(List.of("Gaming"))
|
||||
.properties(Map.of("department", "Marketing", "level", "Junior"))
|
||||
.connections(Map.of(Employee.ConnectionType.PHONE, "1234567890"))
|
||||
.build());
|
||||
|
||||
var emp3 = employeeRepository.save(Employee.builder()
|
||||
.name("Charlie").age(35).role(Employee.Role.ADMIN).code("E003")
|
||||
.salary(new BigDecimal("60000.00")).bonus(new BigDecimal("6000.00"))
|
||||
.active(false).company(company1)
|
||||
.address(Address.builder().street("Pine Rd").city("Shenzhen").state("Guangdong").zipCode("518000").country("China").build())
|
||||
.skills(Set.of(skill1, skill2, skill3))
|
||||
.hobbies(List.of("Reading", "Gaming", "Music"))
|
||||
.properties(Map.of("department", "Engineering", "level", "Lead"))
|
||||
.connections(Map.of(Employee.ConnectionType.EMAIL, "charlie@example.com", Employee.ConnectionType.PHONE, "0987654321"))
|
||||
.build());
|
||||
|
||||
var emp4 = employeeRepository.save(Employee.builder()
|
||||
.name("David").age(28).role(Employee.Role.USER).code("E004")
|
||||
.salary(new BigDecimal("45000.00")).bonus(null)
|
||||
.active(true).company(company3)
|
||||
.address(Address.builder().street("Elm Ln").city("Guangzhou").state("Guangdong").zipCode("510000").country("China").build())
|
||||
.skills(Set.of(skill4))
|
||||
.hobbies(List.of())
|
||||
.properties(Map.of())
|
||||
.connections(Map.of())
|
||||
.build());
|
||||
|
||||
var emp5 = employeeRepository.save(Employee.builder()
|
||||
.name("Alice Smith").age(32).role(Employee.Role.USER).code("E005")
|
||||
.salary(new BigDecimal("55000.00")).bonus(new BigDecimal("5500.00"))
|
||||
.active(true).company(company2)
|
||||
.address(Address.builder().street("Maple Dr").city("Hangzhou").state("Zhejiang").zipCode("310000").country("China").build())
|
||||
.skills(Set.of(skill1, skill4))
|
||||
.hobbies(List.of("Swimming", "Music"))
|
||||
.properties(Map.of("department", "Sales", "level", "Middle"))
|
||||
.connections(Map.of(Employee.ConnectionType.EMAIL, "alicesmith@example.com"))
|
||||
.build());
|
||||
|
||||
// ==================== 1. 基本字段查询测试 ====================
|
||||
|
||||
formatLog("1.1 单字段精确匹配查询");
|
||||
var r1_1 = employeeRepository.findByName("Bob");
|
||||
Assert.isTrue(!r1_1.isEmpty(), "findByName failed");
|
||||
Assert.isTrue(r1_1.get(0).getName().equals("Bob"), "findByName 结果不正确");
|
||||
|
||||
var r1_2 = employeeRepository.findByCode("E003");
|
||||
Assert.isTrue(r1_2.isPresent(), "findByCode failed");
|
||||
Assert.isTrue(r1_2.orElseThrow().getCode().equals("E003"), "findByCode 结果不正确");
|
||||
|
||||
var r1_3 = employeeRepository.findByRole(Employee.Role.ADMIN);
|
||||
Assert.isTrue(r1_3.size() == 2, "findByRole 结果数量应为2,实际:" + r1_3.size());
|
||||
|
||||
formatLog("1.2 布尔值查询");
|
||||
var r1_4 = employeeRepository.findByActiveTrue();
|
||||
Assert.isTrue(r1_4.size() == 4, "findByActiveTrue 结果数量应为4,实际:" + r1_4.size());
|
||||
|
||||
var r1_5 = employeeRepository.findByActiveFalse();
|
||||
Assert.isTrue(r1_5.size() == 1, "findByActiveFalse 结果数量应为1,实际:" + r1_5.size());
|
||||
|
||||
var r1_6 = employeeRepository.countByActiveTrue();
|
||||
Assert.isTrue(r1_6 == 4, "countByActiveTrue 结果应为4,实际:" + r1_6);
|
||||
|
||||
// ==================== 2. 比较运算符查询测试 ====================
|
||||
|
||||
formatLog("2.1 大于/小于/等于/不等于查询");
|
||||
var r2_1 = employeeRepository.findByAgeGreaterThan(30);
|
||||
Assert.isTrue(r2_1.size() == 2, "findByAgeGreaterThan(30) 结果数量应为2,实际:" + r2_1.size());
|
||||
|
||||
var r2_2 = employeeRepository.findByAgeLessThan(30);
|
||||
Assert.isTrue(r2_2.size() == 2, "findByAgeLessThan(30) 结果数量应为2,实际:" + r2_2.size());
|
||||
|
||||
var r2_3 = employeeRepository.findByAgeGreaterThanEqual(30);
|
||||
Assert.isTrue(r2_3.size() == 3, "findByAgeGreaterThanEqual(30) 结果数量应为3,实际:" + r2_3.size());
|
||||
|
||||
var r2_4 = employeeRepository.findByAgeLessThanEqual(30);
|
||||
Assert.isTrue(r2_4.size() == 3, "findByAgeLessThanEqual(30) 结果数量应为3,实际:" + r2_4.size());
|
||||
|
||||
var r2_5 = employeeRepository.findByAgeBetween(25, 35);
|
||||
Assert.isTrue(r2_5.size() == 4, "findByAgeBetween(25,35) 结果数量应为4,实际:" + r2_5.size());
|
||||
|
||||
formatLog("2.2 薪资范围查询");
|
||||
var r2_6 = employeeRepository.findBySalaryGreaterThan(new BigDecimal("50000.00"));
|
||||
Assert.isTrue(r2_6.size() == 3, "findBySalaryGreaterThan 结果数量应为3,实际:" + r2_6.size());
|
||||
|
||||
var r2_7 = employeeRepository.findBySalaryLessThan(new BigDecimal("50000.00"));
|
||||
Assert.isTrue(r2_7.size() == 2, "findBySalaryLessThan 结果数量应为2,实际:" + r2_7.size());
|
||||
|
||||
var r2_8 = employeeRepository.findBySalaryBetween(new BigDecimal("40000.00"), new BigDecimal("55000.00"));
|
||||
Assert.isTrue(r2_8.size() == 4, "findBySalaryBetween 结果数量应为4,实际:" + r2_8.size());
|
||||
|
||||
// ==================== 3. 字符串匹配查询测试 ====================
|
||||
|
||||
formatLog("3.1 字符串包含/开头/结尾查询");
|
||||
var r3_1 = employeeRepository.findByNameContaining("Alice");
|
||||
Assert.isTrue(r3_1.size() == 2, "findByNameContaining('Alice') 结果数量应为2,实际:" + r3_1.size());
|
||||
|
||||
var r3_2 = employeeRepository.findByNameStartingWith("A");
|
||||
Assert.isTrue(r3_2.size() == 2, "findByNameStartingWith('A') 结果数量应为2,实际:" + r3_2.size());
|
||||
|
||||
var r3_3 = employeeRepository.findByNameEndingWith("e");
|
||||
Assert.isTrue(r3_3.size() == 3, "findByNameEndingWith('e') 结果数量应为3,实际:" + r3_3.size());
|
||||
|
||||
var r3_4 = employeeRepository.findByNameLike("%ar%");
|
||||
Assert.isTrue(r3_4.size() == 1, "findByNameLike('%ar%') 结果数量应为1,实际:" + r3_4.size());
|
||||
|
||||
formatLog("3.2 忽略大小写查询");
|
||||
var r3_5 = employeeRepository.findByNameContainingIgnoreCase("ALICE");
|
||||
Assert.isTrue(r3_5.size() == 2, "findByNameContainingIgnoreCase('ALICE') 结果数量应为2,实际:" + r3_5.size());
|
||||
|
||||
var r3_6 = employeeRepository.findByNameStartingWithIgnoreCase("B");
|
||||
Assert.isTrue(r3_6.size() == 1, "findByNameStartingWithIgnoreCase('B') 结果数量应为1,实际:" + r3_6.size());
|
||||
|
||||
var r3_7 = employeeRepository.findByNameIgnoreCase("BOB");
|
||||
Assert.notNull(r3_7, "findByNameIgnoreCase('BOB') 返回null");
|
||||
|
||||
// ==================== 4. NULL值和空值查询测试 ====================
|
||||
|
||||
formatLog("4.1 NULL值查询");
|
||||
var r4_1 = employeeRepository.findByBonusIsNull();
|
||||
Assert.isTrue(r4_1.size() == 1, "findByBonusIsNull 结果数量应为1,实际:" + r4_1.size());
|
||||
Assert.isTrue(r4_1.get(0).getName().equals("David"), "findByBonusIsNull 结果应为David");
|
||||
|
||||
var r4_2 = employeeRepository.findByBonusIsNotNull();
|
||||
Assert.isTrue(r4_2.size() == 4, "findByBonusIsNotNull 结果数量应为4,实际:" + r4_2.size());
|
||||
|
||||
var r4_3 = employeeRepository.findByResumeIsNull();
|
||||
Assert.isTrue(r4_3.size() == 5, "findByResumeIsNull 结果数量应为5,实际:" + r4_3.size());
|
||||
|
||||
formatLog("4.2 空集合查询");
|
||||
var r4_4 = employeeRepository.findByHobbiesEmpty();
|
||||
Assert.isTrue(r4_4.size() == 1, "findByHobbiesEmpty 结果数量应为1,实际:" + r4_4.size());
|
||||
|
||||
var r4_5 = employeeRepository.findByHobbiesIsNotEmpty();
|
||||
Assert.isTrue(r4_5.size() == 4, "findByHobbiesIsNotEmpty 结果数量应为4,实际:" + r4_5.size());
|
||||
|
||||
// ==================== 5. 集合成员查询测试 ====================
|
||||
|
||||
formatLog("5.1 IN/NOT IN 查询");
|
||||
var r5_1 = employeeRepository.findByRoleIn(Set.of(Employee.Role.ADMIN));
|
||||
Assert.isTrue(r5_1.size() == 2, "findByRoleIn 结果数量应为2,实际:" + r5_1.size());
|
||||
|
||||
var r5_2 = employeeRepository.findByRoleNotIn(Set.of(Employee.Role.ADMIN));
|
||||
Assert.isTrue(r5_2.size() == 3, "findByRoleNotIn 结果数量应为3,实际:" + r5_2.size());
|
||||
|
||||
var r5_3 = employeeRepository.findByNameIn(List.of("Alice", "Bob"));
|
||||
Assert.isTrue(r5_3.size() == 2, "findByNameIn 结果数量应为2,实际:" + r5_3.size());
|
||||
|
||||
var r5_4 = employeeRepository.findByNameNotIn(List.of("Charlie", "David"));
|
||||
Assert.isTrue(r5_4.size() == 3, "findByNameNotIn 结果数量应为3,实际:" + r5_4.size());
|
||||
|
||||
var r5_5 = employeeRepository.findByAgeIn(List.of(25, 30, 35));
|
||||
Assert.isTrue(r5_5.size() == 3, "findByAgeIn 结果数量应为3,实际:" + r5_5.size());
|
||||
|
||||
// ==================== 6. 逻辑运算查询测试 ====================
|
||||
|
||||
formatLog("6.1 AND 组合查询");
|
||||
var r6_1 = employeeRepository.findByNameAndRole("Alice", Employee.Role.ADMIN);
|
||||
Assert.isTrue(r6_1.size() == 1, "findByNameAndRole 结果数量应为1,实际:" + r6_1.size());
|
||||
|
||||
var r6_2 = employeeRepository.findByAgeAndActive(30, true);
|
||||
Assert.isTrue(r6_2.size() == 1, "findByAgeAndActive 结果数量应为1,实际:" + r6_2.size());
|
||||
|
||||
var r6_3 = employeeRepository.findByNameAndSalaryGreaterThan("Alice", new BigDecimal("40000.00"));
|
||||
Assert.isTrue(r6_3.size() == 1, "findByNameAndSalaryGreaterThan 结果数量应为1,实际:" + r6_3.size());
|
||||
|
||||
formatLog("6.2 OR 组合查询");
|
||||
var r6_4 = employeeRepository.findByNameOrRole("Alice", Employee.Role.USER);
|
||||
Assert.isTrue(r6_4.size() == 4, "findByNameOrRole 结果数量应为4,实际:" + r6_4.size());
|
||||
|
||||
var r6_5 = employeeRepository.findByAgeLessThanOrSalaryGreaterThan(30, new BigDecimal("55000.00"));
|
||||
Assert.isTrue(r6_5.size() == 3, "findByAgeLessThanOrSalaryGreaterThan 结果数量应为3,实际:" + r6_5.size());
|
||||
|
||||
var r6_6 = employeeRepository.findByNameOrCode("Alice", "E003");
|
||||
Assert.isTrue(r6_6.size() == 2, "findByNameOrCode 结果数量应为2,实际:" + r6_6.size());
|
||||
|
||||
formatLog("6.3 NOT 查询");
|
||||
var r6_7 = employeeRepository.findByRoleNot(Employee.Role.ADMIN);
|
||||
Assert.isTrue(r6_7.size() == 3, "findByRoleNot 结果数量应为3,实际:" + r6_7.size());
|
||||
|
||||
var r6_8 = employeeRepository.findByNameNot("Alice");
|
||||
Assert.isTrue(r6_8.size() == 4, "findByNameNot 结果数量应为4,实际:" + r6_8.size());
|
||||
|
||||
// ==================== 7. 排序查询测试 ====================
|
||||
|
||||
formatLog("7.1 单字段排序查询");
|
||||
var r7_1 = employeeRepository.findByActiveTrueOrderByAgeAsc();
|
||||
Assert.isTrue(r7_1.size() == 4, "findByActiveTrueOrderByAgeAsc 结果数量应为4");
|
||||
Assert.isTrue(r7_1.get(0).getAge() == 25, "findByActiveTrueOrderByAgeAsc 第一条年龄应为25");
|
||||
|
||||
var r7_2 = employeeRepository.findByActiveTrueOrderByAgeDesc();
|
||||
Assert.isTrue(r7_2.size() == 4, "findByActiveTrueOrderByAgeDesc 结果数量应为4");
|
||||
Assert.isTrue(r7_2.get(0).getAge() == 32, "findByActiveTrueOrderByAgeDesc 第一条年龄应为32");
|
||||
|
||||
var r7_3 = employeeRepository.findByActiveTrueOrderBySalaryDesc();
|
||||
Assert.isTrue(r7_3.size() == 4, "findByActiveTrueOrderBySalaryDesc 结果数量应为4");
|
||||
Assert.isTrue(r7_3.get(0).getSalary().compareTo(new BigDecimal("55000.00")) == 0, "findByActiveTrueOrderBySalaryDesc 第一条薪资应为55000");
|
||||
|
||||
formatLog("7.2 多字段排序查询");
|
||||
var r7_4 = employeeRepository.findByRoleOrderByAgeDescNameAsc(Employee.Role.ADMIN);
|
||||
Assert.isTrue(r7_4.size() == 2, "findByRoleOrderByAgeDescNameAsc 结果数量应为2");
|
||||
|
||||
// ==================== 8. 分页查询测试 ====================
|
||||
|
||||
formatLog("8.1 分页查询");
|
||||
var r8_1 = employeeRepository.findByActiveTrue(PageRequest.of(0, 2));
|
||||
Assert.isTrue(r8_1.getContent().size() == 2, "分页结果数量应为2,实际:" + r8_1.getContent().size());
|
||||
Assert.isTrue(r8_1.getTotalElements() == 4, "总元素数应为4,实际:" + r8_1.getTotalElements());
|
||||
|
||||
var r8_2 = employeeRepository.findByRole(Employee.Role.USER, PageRequest.of(0, 10));
|
||||
Assert.isTrue(r8_2.getContent().size() == 3, "findByRole 分页结果数量应为3,实际:" + r8_2.getContent().size());
|
||||
|
||||
var r8_3 = employeeRepository.findBySalaryGreaterThan(new BigDecimal("45000.00"), PageRequest.of(0, 2));
|
||||
Assert.isTrue(r8_3.getContent().size() == 2, "findBySalaryGreaterThan 分页结果数量应为2");
|
||||
|
||||
// ==================== 9. 关联查询测试 ====================
|
||||
|
||||
formatLog("9.1 公司关联查询");
|
||||
var r9_1 = employeeRepository.findByCompany(company1);
|
||||
Assert.isTrue(r9_1.size() == 2, "findByCompany 结果数量应为2,实际:" + r9_1.size());
|
||||
|
||||
var r9_2 = employeeRepository.findByCompanyName("TechCorp");
|
||||
Assert.isTrue(r9_2.size() == 2, "findByCompanyName 结果数量应为2,实际:" + r9_2.size());
|
||||
|
||||
var r9_3 = employeeRepository.findByCompanyNameContaining("Corp");
|
||||
Assert.isTrue(r9_3.size() == 2, "findByCompanyNameContaining 结果数量应为2,实际:" + r9_3.size());
|
||||
|
||||
var r9_4 = employeeRepository.findByCompanyMembersGreaterThan(75);
|
||||
Assert.isTrue(r9_4.size() == 2, "findByCompanyMembersGreaterThan 结果数量应为2,实际:" + r9_4.size());
|
||||
|
||||
formatLog("9.2 技能关联查询");
|
||||
var r9_5 = employeeRepository.findBySkillsContaining(skill1);
|
||||
Assert.isTrue(r9_5.size() == 3, "findBySkillsContaining 结果数量应为3,实际:" + r9_5.size());
|
||||
|
||||
var r9_6 = employeeRepository.findBySkillsName("Java");
|
||||
Assert.isTrue(r9_6.size() == 3, "findBySkillsName 结果数量应为3,实际:" + r9_6.size());
|
||||
|
||||
var r9_7 = employeeRepository.findBySkillsNameContaining("Pyt");
|
||||
Assert.isTrue(r9_7.size() == 2, "findBySkillsNameContaining 结果数量应为2,实际:" + r9_7.size());
|
||||
|
||||
var r9_8 = employeeRepository.findBySkillsNameIn(List.of("Java", "Python"));
|
||||
Assert.isTrue(r9_8.size() == 3, "findBySkillsNameIn 结果数量应为3,实际:" + r9_8.size());
|
||||
|
||||
// ==================== 10. 嵌入式对象查询测试 ====================
|
||||
|
||||
formatLog("10.1 嵌入式对象查询");
|
||||
var r10_1 = employeeRepository.findByAddressCity("Beijing");
|
||||
Assert.isTrue(r10_1.size() == 1, "findByAddressCity 结果数量应为1,实际:" + r10_1.size());
|
||||
Assert.isTrue(r10_1.get(0).getName().equals("Alice"), "findByAddressCity 结果应为Alice");
|
||||
|
||||
var r10_2 = employeeRepository.findByAddressCityContaining("ang");
|
||||
Assert.isTrue(r10_2.size() == 2, "findByAddressCityContaining 结果数量应为2,实际:" + r10_2.size());
|
||||
|
||||
var r10_3 = employeeRepository.findByAddressState("Guangdong");
|
||||
Assert.isTrue(r10_3.size() == 2, "findByAddressState 结果数量应为2,实际:" + r10_3.size());
|
||||
|
||||
var r10_4 = employeeRepository.findByAddressCountry("China");
|
||||
Assert.isTrue(r10_4.size() == 5, "findByAddressCountry 结果数量应为5,实际:" + r10_4.size());
|
||||
|
||||
var r10_5 = employeeRepository.findByAddressCityAndAddressState("Shenzhen", "Guangdong");
|
||||
Assert.isTrue(r10_5.size() == 1, "findByAddressCityAndAddressState 结果数量应为1");
|
||||
|
||||
// ==================== 11. 复合复杂查询测试 ====================
|
||||
|
||||
formatLog("11.1 多条件组合查询");
|
||||
var r11_1 = employeeRepository.findByNameAndRoleAndAgeGreaterThan("Alice", Employee.Role.ADMIN, 25);
|
||||
Assert.isTrue(r11_1.size() == 1, "findByNameAndRoleAndAgeGreaterThan 结果数量应为1");
|
||||
|
||||
var r11_2 = employeeRepository.findByRoleAndActiveTrueAndSalaryGreaterThan(Employee.Role.USER, new BigDecimal("40000.00"));
|
||||
Assert.isTrue(r11_2.size() == 2, "findByRoleAndActiveTrueAndSalaryGreaterThan 结果数量应为2");
|
||||
|
||||
var r11_3 = employeeRepository.findByNameContainingIgnoreCaseAndActiveTrueAndAgeBetween("a", 25, 35);
|
||||
Assert.isTrue(r11_3.size() == 3, "findByNameContainingIgnoreCaseAndActiveTrueAndAgeBetween 结果数量应为3");
|
||||
|
||||
formatLog("11.2 EXISTS语义查询");
|
||||
var r11_4 = employeeRepository.findByCompanyNameContainingAndActiveTrue("Corp");
|
||||
Assert.isTrue(r11_4.size() == 2, "findByCompanyNameContainingAndActiveTrue 结果数量应为2");
|
||||
|
||||
var r11_5 = employeeRepository.findBySkillsNameContainingAndAgeGreaterThan("Java", 25);
|
||||
Assert.isTrue(r11_5.size() == 2, "findBySkillsNameContainingAndAgeGreaterThan 结果数量应为2");
|
||||
|
||||
// ==================== 12. DISTINCT 查询测试 ====================
|
||||
|
||||
formatLog("12.1 DISTINCT 查询");
|
||||
var r12_1 = employeeRepository.findDistinctByRole(Employee.Role.ADMIN);
|
||||
Assert.isTrue(r12_1.size() == 2, "findDistinctByRole 结果数量应为2");
|
||||
|
||||
// ==================== 13. TOP/LIMIT 查询测试 ====================
|
||||
|
||||
formatLog("13.1 TOP/LIMIT 查询");
|
||||
var r13_1 = employeeRepository.findTop5BySalaryGreaterThan(new BigDecimal("40000.00"));
|
||||
Assert.isTrue(r13_1.size() == 4, "findTop5BySalaryGreaterThan 结果数量应为4");
|
||||
|
||||
var r13_3 = employeeRepository.findFirstByRoleOrderBySalaryDesc(Employee.Role.ADMIN);
|
||||
Assert.notNull(r13_3, "findFirstByRoleOrderBySalaryDesc 返回null");
|
||||
Assert.isTrue(r13_3.orElseThrow().getSalary().compareTo(new BigDecimal("60000.00")) == 0, "findFirstByRoleOrderBySalaryDesc 最高薪资应为60000");
|
||||
|
||||
// ==================== 14. LIKE 模式查询测试 ====================
|
||||
|
||||
formatLog("14.1 LIKE 模式查询");
|
||||
var r14_1 = employeeRepository.findByNameLikeIgnoreCase("%ALICE%");
|
||||
Assert.isTrue(r14_1.size() == 2, "findByNameLikeIgnoreCase 结果数量应为2");
|
||||
|
||||
var r14_2 = employeeRepository.findByNameStartingWithAndRole("A", Employee.Role.ADMIN);
|
||||
Assert.isTrue(r14_2.size() == 1, "findByNameStartingWithAndRole 结果数量应为1");
|
||||
|
||||
var r14_3 = employeeRepository.findByNameEndingWithAndAgeLessThan("e", 30);
|
||||
Assert.isTrue(r14_3.size() == 1, "findByNameEndingWithAndAgeLessThan 结果数量应为1");
|
||||
|
||||
// ==================== 15. 其他未覆盖的有用方法测试 ====================
|
||||
|
||||
formatLog("15.1 聚合计数查询");
|
||||
var r15_1 = employeeRepository.countByActiveTrue();
|
||||
Assert.isTrue(r15_1 == 4, "countByActiveTrue 结果应为4,实际:" + r15_1);
|
||||
|
||||
var r15_2 = employeeRepository.countByActiveFalse();
|
||||
Assert.isTrue(r15_2 == 1, "countByActiveFalse 结果应为1,实际:" + r15_2);
|
||||
|
||||
formatLog("15.2 技能和简历查询");
|
||||
var r15_3 = employeeRepository.findByResumeIsNotNull();
|
||||
Assert.isTrue(r15_3.size() == 5, "findByResumeIsNotNull 结果数量应为5,实际:" + r15_3.size());
|
||||
|
||||
var r15_4 = employeeRepository.findBySkillsEmpty();
|
||||
Assert.isTrue(r15_4.isEmpty(), "findBySkillsEmpty 结果应该为空,实际:" + r15_4.size());
|
||||
|
||||
formatLog("15.3 公司成员数查询");
|
||||
var r15_5 = employeeRepository.findByCompanyMembersGreaterThan(100);
|
||||
Assert.isTrue(r15_5.size() == 1, "findByCompanyMembersGreaterThan(100) 结果数量应为1,实际:" + r15_5.size());
|
||||
|
||||
var r15_6 = employeeRepository.findByCompanyMembersGreaterThan(50);
|
||||
Assert.isTrue(r15_6.size() == 3, "findByCompanyMembersGreaterThan(50) 结果数量应为3,实际:" + r15_6.size());
|
||||
|
||||
formatLog("15.4 城市包含查询");
|
||||
var r15_7 = employeeRepository.findByAddressCityContaining("ang");
|
||||
Assert.isTrue(r15_7.size() == 2, "findByAddressCityContaining('ang') 结果数量应为2,实际:" + r15_7.size());
|
||||
|
||||
formatLog("15.5 DISTINCT 查询");
|
||||
var r15_8 = employeeRepository.findDistinctByRole(Employee.Role.USER);
|
||||
Assert.isTrue(r15_8.size() == 3, "findDistinctByRole 结果数量应为3,实际:" + r15_8.size());
|
||||
|
||||
formatLog("15.6 TOP/LIMIT 查询");
|
||||
var r15_9 = employeeRepository.findTop5BySalaryGreaterThan(new BigDecimal("40000.00"));
|
||||
Assert.isTrue(r15_9.size() == 4, "findTop5BySalaryGreaterThan 结果数量应为4,实际:" + r15_9.size());
|
||||
|
||||
var r15_10 = employeeRepository.findFirstByRoleOrderBySalaryDesc(Employee.Role.ADMIN);
|
||||
Assert.isTrue(r15_10.isPresent(), "findFirstByRoleOrderBySalaryDesc 返回null");
|
||||
Assert.isTrue(r15_10.orElseThrow().getSalary().compareTo(new BigDecimal("60000.00")) == 0, "findFirstByRoleOrderBySalaryDesc 最高薪资应为60000");
|
||||
|
||||
formatLog("清理测试数据");
|
||||
employeeRepository.deleteAllInBatch();
|
||||
companyRepository.deleteAllInBatch();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,14 @@
|
||||
package com.lanyuanxiaoyao.service.template.database.jpa.repository;
|
||||
|
||||
import com.lanyuanxiaoyao.service.template.database.jpa.entity.Company;
|
||||
import com.lanyuanxiaoyao.service.template.database.jpa.entity.Employee;
|
||||
import com.lanyuanxiaoyao.service.template.database.jpa.entity.Skill;
|
||||
import java.math.BigDecimal;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.data.jpa.domain.Specification;
|
||||
import org.springframework.data.jpa.repository.EntityGraph;
|
||||
import org.springframework.stereotype.Repository;
|
||||
@@ -12,4 +19,194 @@ public interface EmployeeRepository extends SimpleRepository<Employee> {
|
||||
@EntityGraph(attributePaths = {"company"})
|
||||
@Override
|
||||
Optional<Employee> findOne(Specification<Employee> specification);
|
||||
|
||||
// ==================== 1. 基本字段查询 ====================
|
||||
|
||||
// 单字段精确匹配
|
||||
List<Employee> findByName(String name);
|
||||
|
||||
Optional<Employee> findByCode(String code);
|
||||
|
||||
List<Employee> findByRole(Employee.Role role);
|
||||
|
||||
// 布尔值查询
|
||||
List<Employee> findByActiveTrue();
|
||||
|
||||
List<Employee> findByActiveFalse();
|
||||
|
||||
long countByActiveTrue();
|
||||
|
||||
long countByActiveFalse();
|
||||
|
||||
// ==================== 2. 比较运算符查询 ====================
|
||||
|
||||
List<Employee> findByAgeGreaterThan(Integer age);
|
||||
|
||||
List<Employee> findByAgeLessThan(Integer age);
|
||||
|
||||
List<Employee> findByAgeGreaterThanEqual(Integer age);
|
||||
|
||||
List<Employee> findByAgeLessThanEqual(Integer age);
|
||||
|
||||
List<Employee> findByAgeBetween(Integer startAge, Integer endAge);
|
||||
|
||||
List<Employee> findBySalaryGreaterThan(BigDecimal salary);
|
||||
|
||||
List<Employee> findBySalaryLessThan(BigDecimal salary);
|
||||
|
||||
List<Employee> findBySalaryGreaterThanEqual(BigDecimal salary);
|
||||
|
||||
List<Employee> findBySalaryLessThanEqual(BigDecimal salary);
|
||||
|
||||
List<Employee> findBySalaryBetween(BigDecimal minSalary, BigDecimal maxSalary);
|
||||
|
||||
// ==================== 3. 字符串匹配查询 ====================
|
||||
|
||||
// 精确匹配
|
||||
List<Employee> findByNameContaining(String name);
|
||||
|
||||
List<Employee> findByNameStartingWith(String prefix);
|
||||
|
||||
List<Employee> findByNameEndingWith(String suffix);
|
||||
|
||||
List<Employee> findByNameLike(String pattern);
|
||||
|
||||
// 忽略大小写
|
||||
List<Employee> findByNameContainingIgnoreCase(String name);
|
||||
|
||||
List<Employee> findByNameStartingWithIgnoreCase(String prefix);
|
||||
|
||||
List<Employee> findByNameEndingWithIgnoreCase(String suffix);
|
||||
|
||||
List<Employee> findByNameIgnoreCase(String name);
|
||||
|
||||
// ==================== 4. NULL值和空值查询 ====================
|
||||
|
||||
List<Employee> findByBonusIsNull();
|
||||
|
||||
List<Employee> findByBonusIsNotNull();
|
||||
|
||||
List<Employee> findByResumeIsNull();
|
||||
|
||||
List<Employee> findByResumeIsNotNull();
|
||||
|
||||
List<Employee> findByHobbiesEmpty();
|
||||
|
||||
List<Employee> findByHobbiesIsNotEmpty();
|
||||
|
||||
List<Employee> findBySkillsEmpty();
|
||||
|
||||
List<Employee> findBySkillsIsNotEmpty();
|
||||
|
||||
// ==================== 5. 集合成员查询 (IN/NOT IN) ====================
|
||||
|
||||
List<Employee> findByRoleIn(Set<Employee.Role> roles);
|
||||
|
||||
List<Employee> findByRoleNotIn(Set<Employee.Role> roles);
|
||||
|
||||
List<Employee> findByNameIn(List<String> names);
|
||||
|
||||
List<Employee> findByNameNotIn(List<String> names);
|
||||
|
||||
List<Employee> findByAgeIn(List<Integer> ages);
|
||||
|
||||
List<Employee> findByAgeNotIn(List<Integer> ages);
|
||||
|
||||
// ==================== 6. 逻辑运算查询 (AND/OR/NOT) ====================
|
||||
|
||||
List<Employee> findByNameAndRole(String name, Employee.Role role);
|
||||
|
||||
List<Employee> findByAgeAndActive(Integer age, Boolean active);
|
||||
|
||||
List<Employee> findByNameAndSalaryGreaterThan(String name, BigDecimal salary);
|
||||
|
||||
List<Employee> findByRoleAndActiveAndAgeGreaterThan(Employee.Role role, Boolean active, Integer age);
|
||||
|
||||
List<Employee> findByNameOrRole(String name, Employee.Role role);
|
||||
|
||||
List<Employee> findByAgeLessThanOrSalaryGreaterThan(Integer age, BigDecimal salary);
|
||||
|
||||
List<Employee> findByNameOrCode(String name, String code);
|
||||
|
||||
List<Employee> findByRoleNot(Employee.Role role);
|
||||
|
||||
List<Employee> findByNameNot(String name);
|
||||
|
||||
// ==================== 7. 排序查询 ====================
|
||||
|
||||
List<Employee> findByActiveTrueOrderByAgeAsc();
|
||||
|
||||
List<Employee> findByActiveTrueOrderByAgeDesc();
|
||||
|
||||
List<Employee> findByActiveTrueOrderBySalaryDesc();
|
||||
|
||||
List<Employee> findByRoleOrderByAgeDescNameAsc(Employee.Role role);
|
||||
|
||||
// ==================== 8. 分页查询 ====================
|
||||
|
||||
Page<Employee> findByActiveTrue(Pageable pageable);
|
||||
|
||||
Page<Employee> findByRole(Employee.Role role, Pageable pageable);
|
||||
|
||||
Page<Employee> findBySalaryGreaterThan(BigDecimal salary, Pageable pageable);
|
||||
|
||||
// ==================== 9. 关联查询 (JOIN) ====================
|
||||
|
||||
List<Employee> findByCompany(Company company);
|
||||
|
||||
List<Employee> findByCompanyName(String companyName);
|
||||
|
||||
List<Employee> findByCompanyNameContaining(String companyName);
|
||||
|
||||
List<Employee> findByCompanyMembersGreaterThan(Integer members);
|
||||
|
||||
List<Employee> findBySkillsContaining(Skill skill);
|
||||
|
||||
List<Employee> findBySkillsName(String skillName);
|
||||
|
||||
List<Employee> findBySkillsNameContaining(String skillName);
|
||||
|
||||
List<Employee> findBySkillsNameIn(List<String> skillNames);
|
||||
|
||||
// ==================== 10. 嵌入式对象查询 ====================
|
||||
|
||||
List<Employee> findByAddressCity(String city);
|
||||
|
||||
List<Employee> findByAddressCityContaining(String city);
|
||||
|
||||
List<Employee> findByAddressState(String state);
|
||||
|
||||
List<Employee> findByAddressCountry(String country);
|
||||
|
||||
List<Employee> findByAddressCityAndAddressState(String city, String state);
|
||||
|
||||
// ==================== 11. 复合复杂查询 ====================
|
||||
|
||||
List<Employee> findByNameAndRoleAndAgeGreaterThan(String name, Employee.Role role, Integer age);
|
||||
|
||||
List<Employee> findByRoleAndActiveTrueAndSalaryGreaterThan(Employee.Role role, BigDecimal salary);
|
||||
|
||||
List<Employee> findByNameContainingIgnoreCaseAndActiveTrueAndAgeBetween(String name, Integer minAge, Integer maxAge);
|
||||
|
||||
List<Employee> findByCompanyNameContainingAndActiveTrue(String companyName);
|
||||
|
||||
List<Employee> findBySkillsNameContainingAndAgeGreaterThan(String skillName, Integer age);
|
||||
|
||||
// ==================== 12. DISTINCT 查询 ====================
|
||||
|
||||
List<Employee> findDistinctByRole(Employee.Role role);
|
||||
|
||||
// ==================== 13. TOP/LIMIT 查询 ====================
|
||||
|
||||
List<Employee> findTop5BySalaryGreaterThan(BigDecimal salary);
|
||||
|
||||
Optional<Employee> findFirstByRoleOrderBySalaryDesc(Employee.Role role);
|
||||
|
||||
// ==================== 14. LIKE 模式查询 ====================
|
||||
|
||||
List<Employee> findByNameLikeIgnoreCase(String pattern);
|
||||
|
||||
List<Employee> findByNameStartingWithAndRole(String prefix, Employee.Role role);
|
||||
|
||||
List<Employee> findByNameEndingWithAndAgeLessThan(String suffix, Integer age);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user