fix(jpa): 完善测试用例
This commit is contained in:
@@ -2,17 +2,16 @@ package com.lanyuanxiaoyao.service.template.database.common.test;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.Random;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.http.HttpEntity;
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.jdbc.core.JdbcTemplate;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.web.client.RestTemplate;
|
||||
import tools.jackson.databind.JsonNode;
|
||||
import tools.jackson.databind.ObjectMapper;
|
||||
|
||||
@RequiredArgsConstructor
|
||||
@Slf4j
|
||||
public class AbstractTestApplication {
|
||||
private static final String BASE_URL = "http://localhost:2490";
|
||||
private static final RestTemplate REST_CLIENT = new RestTemplate();
|
||||
@@ -20,17 +19,18 @@ public class AbstractTestApplication {
|
||||
private static final Random random = new Random();
|
||||
private static final String randomChars = "qwertyuiopasdfghjklzxcvbnmQWERTYUIOPASDFGHJKLZXCVBNM";
|
||||
|
||||
private final JdbcTemplate template;
|
||||
|
||||
protected void testCrud() {
|
||||
formatLog("Save");
|
||||
var cid1 = saveItem("company", randomCompany("Apple")).get("data").asLong();
|
||||
var cid2 = saveItem("company", randomCompany()).get("data").asLong();
|
||||
var cid3 = saveItem("company", randomCompany()).get("data").asLong();
|
||||
|
||||
formatLog("List");
|
||||
var companies1 = listItems("company");
|
||||
Assert.isTrue(companies1.at("/data/items").size() == 3, "数量错误");
|
||||
Assert.isTrue(companies1.at("/data/total").asLong() == 3, "返回数量错误");
|
||||
|
||||
formatLog("Detail");
|
||||
var company1 = detailItem("company", cid1);
|
||||
Assert.isTrue(cid1 == company1.at("/data/id").asLong(), "id错误");
|
||||
Assert.isTrue(company1.at("/data/name").asString("").startsWith("Apple"), "name错误");
|
||||
@@ -41,6 +41,7 @@ public class AbstractTestApplication {
|
||||
var company3 = detailItem("company", cid3);
|
||||
Assert.isTrue(cid3 == company3.at("/data/id").asLong(), "id错误");
|
||||
|
||||
formatLog("List Page");
|
||||
// language=JSON
|
||||
var pageRequest = """
|
||||
{
|
||||
@@ -54,6 +55,7 @@ public class AbstractTestApplication {
|
||||
Assert.isTrue(companies2.at("/data/items").size() == 2, "数量错误");
|
||||
Assert.isTrue(companies2.at("/data/total").asLong() == 3, "返回数量错误");
|
||||
|
||||
formatLog("List Queryable");
|
||||
// language=JSON
|
||||
var queryRequest = """
|
||||
{
|
||||
@@ -106,6 +108,7 @@ public class AbstractTestApplication {
|
||||
Assert.isTrue(companies3.at("/data/items").size() == 1, "数量错误");
|
||||
Assert.isTrue(companies3.at("/data/total").asLong() == 1, "返回数量错误");
|
||||
|
||||
formatLog("Clean");
|
||||
removeItem("company", cid1);
|
||||
Assert.isTrue(listItems("company").at("/data/items").size() == 2, "数量错误");
|
||||
Assert.isTrue(listItems("company").at("/data/total").asLong() == 2, "返回数量错误");
|
||||
@@ -115,6 +118,10 @@ public class AbstractTestApplication {
|
||||
Assert.isTrue(listItems("company").at("/data/total").asLong() == 0, "返回数量错误");
|
||||
}
|
||||
|
||||
protected void formatLog(String text) {
|
||||
log.info("===== {} =====", text);
|
||||
}
|
||||
|
||||
protected Map<String, Object> randomCompany() {
|
||||
return randomCompany(randomString(10));
|
||||
}
|
||||
@@ -146,11 +153,11 @@ public class AbstractTestApplication {
|
||||
);
|
||||
}
|
||||
|
||||
private String randomString(String prefix, int length) {
|
||||
protected String randomString(String prefix, int length) {
|
||||
return prefix + randomString(length);
|
||||
}
|
||||
|
||||
private String randomString(int length) {
|
||||
protected String randomString(int length) {
|
||||
var builder = new StringBuilder();
|
||||
for (int i = 0; i < length; i++) {
|
||||
builder.append(randomChars.charAt(random.nextInt(randomChars.length())));
|
||||
@@ -158,15 +165,15 @@ public class AbstractTestApplication {
|
||||
return builder.toString();
|
||||
}
|
||||
|
||||
private String randomChar(String base) {
|
||||
protected String randomChar(String base) {
|
||||
return base.charAt(randomInt(base.length())) + "";
|
||||
}
|
||||
|
||||
private int randomInt(int bound) {
|
||||
protected int randomInt(int bound) {
|
||||
return random.nextInt(1, bound);
|
||||
}
|
||||
|
||||
private double randomDouble(int bound) {
|
||||
protected double randomDouble(int bound) {
|
||||
return random.nextDouble(1, bound);
|
||||
}
|
||||
|
||||
|
||||
@@ -276,7 +276,7 @@ public abstract class SimpleServiceSupport<ENTITY extends SimpleEntity> implemen
|
||||
@Override
|
||||
public void remove(Long id) {
|
||||
if (ObjectHelper.isNotNull(id)) {
|
||||
repository.deleteById(id);
|
||||
repository.deleteBatchByIds(List.of(id));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -3,24 +3,30 @@ package com.lanyuanxiaoyao.service.template.database.jpa;
|
||||
import com.blinkfox.fenix.EnableFenix;
|
||||
import com.lanyuanxiaoyao.service.template.database.common.test.AbstractTestApplication;
|
||||
import com.lanyuanxiaoyao.service.template.database.common.test.entity.Industry;
|
||||
import com.lanyuanxiaoyao.service.template.database.common.test.entity.Level;
|
||||
import com.lanyuanxiaoyao.service.template.database.jpa.entity.Company;
|
||||
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.Employee_;
|
||||
import com.lanyuanxiaoyao.service.template.database.jpa.entity.QEmployee;
|
||||
import com.lanyuanxiaoyao.service.template.database.jpa.entity.Report;
|
||||
import com.lanyuanxiaoyao.service.template.database.jpa.repository.CompanyRepository;
|
||||
import com.lanyuanxiaoyao.service.template.database.jpa.repository.EmployeeRepository;
|
||||
import com.lanyuanxiaoyao.service.template.database.jpa.repository.ReportRepository;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
import org.springframework.boot.context.event.ApplicationReadyEvent;
|
||||
import org.springframework.context.event.EventListener;
|
||||
import org.springframework.data.jpa.repository.config.EnableJpaAuditing;
|
||||
import org.springframework.jdbc.core.JdbcTemplate;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
@Slf4j
|
||||
@RequiredArgsConstructor
|
||||
@SpringBootApplication
|
||||
@EnableFenix
|
||||
@EnableJpaAuditing
|
||||
@@ -29,13 +35,6 @@ public class TestApplication extends AbstractTestApplication {
|
||||
private final EmployeeRepository employeeRepository;
|
||||
private final ReportRepository reportRepository;
|
||||
|
||||
public TestApplication(JdbcTemplate jdbcTemplate, CompanyRepository companyRepository, EmployeeRepository employeeRepository, ReportRepository reportRepository) {
|
||||
super(jdbcTemplate);
|
||||
this.companyRepository = companyRepository;
|
||||
this.employeeRepository = employeeRepository;
|
||||
this.reportRepository = reportRepository;
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
SpringApplication.run(TestApplication.class, args);
|
||||
}
|
||||
@@ -43,21 +42,72 @@ public class TestApplication extends AbstractTestApplication {
|
||||
@EventListener(ApplicationReadyEvent.class)
|
||||
public void runTests() {
|
||||
testCrud();
|
||||
testDelete();
|
||||
testSpecification();
|
||||
testNative();
|
||||
|
||||
System.exit(0);
|
||||
}
|
||||
|
||||
private void testSpecification() {
|
||||
private void testDelete() {
|
||||
formatLog("Delete JPA");
|
||||
saveItem("company", randomCompany());
|
||||
saveItem("company", randomCompany());
|
||||
companyRepository.deleteAll();
|
||||
|
||||
formatLog("Delete JPA Batch");
|
||||
saveItem("company", randomCompany());
|
||||
saveItem("company", randomCompany());
|
||||
companyRepository.deleteAllInBatch();
|
||||
|
||||
formatLog("Delete JPA by id");
|
||||
var cid1 = saveItem("company", randomCompany()).get("data").asLong();
|
||||
var cid2 = saveItem("company", randomCompany()).get("data").asLong();
|
||||
var cid3 = saveItem("company", randomCompany()).get("data").asLong();
|
||||
var eid1 = saveItem("employee", randomEmployee(cid1, "Tom")).get("data").asLong();
|
||||
var eid2 = saveItem("employee", randomEmployee(cid2)).get("data").asLong();
|
||||
var rid1 = saveItem("report", randomReport(eid1)).get("data").asLong();
|
||||
var rid2 = saveItem("report", randomReport(eid2)).get("data").asLong();
|
||||
companyRepository.deleteAllById(List.of(cid1, cid2));
|
||||
|
||||
formatLog("Delete Fenix by id");
|
||||
cid1 = saveItem("company", randomCompany()).get("data").asLong();
|
||||
cid2 = saveItem("company", randomCompany()).get("data").asLong();
|
||||
companyRepository.deleteByIds(List.of(cid1, cid2));
|
||||
|
||||
formatLog("Delete Fenix Batch by id");
|
||||
cid1 = saveItem("company", randomCompany()).get("data").asLong();
|
||||
cid2 = saveItem("company", randomCompany()).get("data").asLong();
|
||||
companyRepository.deleteBatchByIds(List.of(cid1, cid2));
|
||||
}
|
||||
|
||||
private void testSpecification() {
|
||||
formatLog("Added");
|
||||
var company1 = companyRepository.save(Company.builder().name(randomString(5)).members(randomInt(100)).industries(Set.of(Industry.MEDIA, Industry.SERVICE)).build());
|
||||
var company2 = companyRepository.save(Company.builder().name(randomString(5)).members(randomInt(100)).industries(Set.of(Industry.MEDIA, Industry.SERVICE)).build());
|
||||
var employee1 = employeeRepository.save(
|
||||
Employee.builder()
|
||||
.name("Tom")
|
||||
.age(randomInt(100))
|
||||
.role(Employee.Role.USER)
|
||||
.company(company1)
|
||||
.connections(Map.of(
|
||||
Employee.ConnectionType.ADDRESS, randomString(50),
|
||||
Employee.ConnectionType.EMAIL, randomString(20)
|
||||
))
|
||||
.build()
|
||||
);
|
||||
var employee2 = employeeRepository.save(
|
||||
Employee.builder()
|
||||
.name(randomString(10))
|
||||
.age(randomInt(100))
|
||||
.role(Employee.Role.USER)
|
||||
.company(company2)
|
||||
.connections(Map.of(
|
||||
Employee.ConnectionType.ADDRESS, randomString(50),
|
||||
Employee.ConnectionType.EMAIL, randomString(20)
|
||||
))
|
||||
.build()
|
||||
);
|
||||
var report1 = reportRepository.save(Report.builder().score(randomDouble(50)).level(Level.B).employeeId(employee1.getId()).build());
|
||||
var report2 = reportRepository.save(Report.builder().score(randomDouble(50)).level(Level.E).employeeId(employee2.getId()).build());
|
||||
|
||||
formatLog("Query");
|
||||
var employees1 = employeeRepository.findAll(
|
||||
builder -> builder
|
||||
.andIsNotNull(Employee.Fields.name)
|
||||
@@ -84,7 +134,7 @@ public class TestApplication extends AbstractTestApplication {
|
||||
builder.in(root.get(Employee_.NAME)).value(List.of("Tom", "Mike")),
|
||||
builder.between(root.get(Employee_.age), 0, 200),
|
||||
builder.isNotEmpty(root.get(Employee_.company).get(Company_.employees)),
|
||||
builder.isNotMember(Industry.MEDIA, root.get(Employee_.company).get(Company_.industries))
|
||||
builder.isMember(Industry.MEDIA, root.get(Employee_.company).get(Company_.industries))
|
||||
)
|
||||
);
|
||||
Assert.isTrue(employees2.size() == 1, "查询数量错误");
|
||||
@@ -100,31 +150,36 @@ public class TestApplication extends AbstractTestApplication {
|
||||
.and(QEmployee.employee.name.in("Tom", "Mike"))
|
||||
.and(QEmployee.employee.age.between(0, 200))
|
||||
.and(QEmployee.employee.company().employees.isNotEmpty())
|
||||
.and(QEmployee.employee.company().industries.contains(Industry.MEDIA).not())
|
||||
.and(QEmployee.employee.connections.containsKey(Employee.ConnectionType.EMAIL).not())
|
||||
.and(QEmployee.employee.company().industries.contains(Industry.MEDIA))
|
||||
.and(QEmployee.employee.connections.containsKey(Employee.ConnectionType.EMAIL))
|
||||
);
|
||||
Assert.isTrue(employees3.size() == 1, "查询数量错误");
|
||||
|
||||
companyRepository.deleteAllById(List.of(cid1, cid2, cid3));
|
||||
employeeRepository.deleteAllById(List.of(eid1, eid2));
|
||||
reportRepository.deleteAllById(List.of(rid1, rid2));
|
||||
formatLog("Clean");
|
||||
reportRepository.deleteAllInBatch();
|
||||
employeeRepository.deleteAllInBatch();
|
||||
companyRepository.deleteAllInBatch();
|
||||
}
|
||||
|
||||
private void testNative() {
|
||||
var cid1 = saveItem("company", randomCompany()).get("data").asLong();
|
||||
var cid2 = saveItem("company", randomCompany()).get("data").asLong();
|
||||
var cid3 = saveItem("company", randomCompany()).get("data").asLong();
|
||||
var eid1 = saveItem("employee", randomEmployee(cid1)).get("data").asLong();
|
||||
var eid2 = saveItem("employee", randomEmployee(cid2)).get("data").asLong();
|
||||
var eid3 = saveItem("employee", randomEmployee(cid3)).get("data").asLong();
|
||||
formatLog("Added");
|
||||
var company1 = companyRepository.save(Company.builder().name(randomString(5)).members(randomInt(100)).build());
|
||||
var company2 = companyRepository.save(Company.builder().name(randomString(5)).members(randomInt(100)).build());
|
||||
var company3 = companyRepository.save(Company.builder().name(randomString(5)).members(randomInt(100)).build());
|
||||
var employee1 = employeeRepository.save(Employee.builder().name(randomString(10)).age(randomInt(100)).role(Employee.Role.USER).company(company1).build());
|
||||
var employee2 = employeeRepository.save(Employee.builder().name(randomString(10)).age(randomInt(100)).role(Employee.Role.USER).company(company2).build());
|
||||
var employee3 = employeeRepository.save(Employee.builder().name(randomString(10)).age(randomInt(100)).role(Employee.Role.USER).company(company3).build());
|
||||
|
||||
formatLog("HQL Query");
|
||||
var list = employeeRepository.findAllEmployeeWithCompanyName();
|
||||
Assert.isTrue(list.size() == 3, "数量错误");
|
||||
|
||||
formatLog("SQL Query");
|
||||
var list_native = employeeRepository.findAllEmployeeWithCompanyNameNative();
|
||||
Assert.isTrue(list_native.size() == 3, "数量错误");
|
||||
|
||||
companyRepository.deleteAll();
|
||||
employeeRepository.deleteAll();
|
||||
formatLog("Clean");
|
||||
employeeRepository.deleteAllInBatch();
|
||||
companyRepository.deleteAllInBatch();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,7 +14,10 @@ import jakarta.persistence.OneToMany;
|
||||
import jakarta.persistence.Table;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.Setter;
|
||||
import lombok.ToString;
|
||||
import lombok.experimental.FieldNameConstants;
|
||||
@@ -27,6 +30,9 @@ import org.springframework.data.jpa.domain.support.AuditingEntityListener;
|
||||
@Getter
|
||||
@ToString(callSuper = true)
|
||||
@FieldNameConstants
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
@Builder
|
||||
@Entity
|
||||
@SoftDelete
|
||||
@DynamicUpdate
|
||||
@@ -39,13 +45,13 @@ public class Company extends SimpleEntity {
|
||||
@Column(nullable = false, comment = "成员数")
|
||||
private Integer members;
|
||||
|
||||
@OneToMany(mappedBy = "company")
|
||||
@ToString.Exclude
|
||||
private Set<Employee> employees;
|
||||
|
||||
@ElementCollection
|
||||
@JoinTable(foreignKey = @ForeignKey(ConstraintMode.NO_CONSTRAINT), inverseForeignKey = @ForeignKey(ConstraintMode.NO_CONSTRAINT))
|
||||
@Enumerated(EnumType.STRING)
|
||||
@Column(nullable = false)
|
||||
private Set<Industry> industries = new HashSet<>();
|
||||
|
||||
@OneToMany(mappedBy = "company")
|
||||
@ToString.Exclude
|
||||
private Set<Employee> employees;
|
||||
}
|
||||
|
||||
@@ -15,7 +15,10 @@ import jakarta.persistence.MapKeyEnumerated;
|
||||
import jakarta.persistence.Table;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.Setter;
|
||||
import lombok.ToString;
|
||||
import lombok.experimental.FieldNameConstants;
|
||||
@@ -28,6 +31,9 @@ import org.springframework.data.jpa.domain.support.AuditingEntityListener;
|
||||
@Getter
|
||||
@ToString(callSuper = true)
|
||||
@FieldNameConstants
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
@Builder
|
||||
@Entity
|
||||
@SoftDelete
|
||||
@DynamicUpdate
|
||||
|
||||
@@ -7,7 +7,10 @@ import jakarta.persistence.EntityListeners;
|
||||
import jakarta.persistence.EnumType;
|
||||
import jakarta.persistence.Enumerated;
|
||||
import jakarta.persistence.Table;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.Setter;
|
||||
import lombok.ToString;
|
||||
import lombok.experimental.FieldNameConstants;
|
||||
@@ -20,6 +23,9 @@ import org.springframework.data.jpa.domain.support.AuditingEntityListener;
|
||||
@Getter
|
||||
@ToString(callSuper = true)
|
||||
@FieldNameConstants
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
@Builder
|
||||
@Entity
|
||||
@SoftDelete
|
||||
@DynamicUpdate
|
||||
|
||||
@@ -16,7 +16,7 @@ public interface EmployeeRepository extends SimpleRepository<Employee> {
|
||||
@Override
|
||||
Optional<Employee> findOne(Specification<Employee> specification);
|
||||
|
||||
@Query(value = "select e.name, c.name, e.age, e.role from employee e, company c where e.company_id = c.id", nativeQuery = true)
|
||||
@Query(value = "select e.name, c.name, e.age, e.role from employee e, company c where e.company_id = c.id and c.deleted = false and e.deleted = false", nativeQuery = true)
|
||||
List<EmployeeWithCompanyName> findAllEmployeeWithCompanyNameNative();
|
||||
|
||||
@Query("select new com.lanyuanxiaoyao.service.template.database.jpa.entity.vo.EmployeeWithCompanyName(employee.name, employee.company.name, employee.age, cast(employee.role as string)) from Employee employee")
|
||||
|
||||
Reference in New Issue
Block a user