fix(xbatis): 完善测试用例
This commit is contained in:
3
pom.xml
3
pom.xml
@@ -32,6 +32,7 @@
|
|||||||
<mapstruct-plus.version>1.5.0</mapstruct-plus.version>
|
<mapstruct-plus.version>1.5.0</mapstruct-plus.version>
|
||||||
<datasource-decorator.version>2.0.0</datasource-decorator.version>
|
<datasource-decorator.version>2.0.0</datasource-decorator.version>
|
||||||
<easy-query.version>3.1.68</easy-query.version>
|
<easy-query.version>3.1.68</easy-query.version>
|
||||||
|
<xbatis.version>1.9.7-spring-boot4</xbatis.version>
|
||||||
|
|
||||||
<hutool.version>5.8.43</hutool.version>
|
<hutool.version>5.8.43</hutool.version>
|
||||||
</properties>
|
</properties>
|
||||||
@@ -120,7 +121,7 @@
|
|||||||
<dependency>
|
<dependency>
|
||||||
<groupId>cn.xbatis</groupId>
|
<groupId>cn.xbatis</groupId>
|
||||||
<artifactId>xbatis-spring-boot-parent</artifactId>
|
<artifactId>xbatis-spring-boot-parent</artifactId>
|
||||||
<version>1.9.6-spring-boot4</version>
|
<version>${xbatis.version}</version>
|
||||||
<type>pom</type>
|
<type>pom</type>
|
||||||
<scope>import</scope>
|
<scope>import</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|||||||
@@ -26,9 +26,7 @@ public class AbstractTestApplication {
|
|||||||
var cid3 = saveItem("company", randomCompany()).get("data").asLong();
|
var cid3 = saveItem("company", randomCompany()).get("data").asLong();
|
||||||
|
|
||||||
formatLog("List");
|
formatLog("List");
|
||||||
var companies1 = listItems("company");
|
assertListItems(listItems("company"), 3, 3);
|
||||||
Assert.isTrue(companies1.at("/data/items").size() == 3, "数量错误");
|
|
||||||
Assert.isTrue(companies1.at("/data/total").asLong() == 3, "返回数量错误");
|
|
||||||
|
|
||||||
formatLog("Detail");
|
formatLog("Detail");
|
||||||
var company1 = detailItem("company", cid1);
|
var company1 = detailItem("company", cid1);
|
||||||
@@ -51,9 +49,7 @@ public class AbstractTestApplication {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
""";
|
""";
|
||||||
var companies2 = listItems("company", pageRequest);
|
assertListItems(listItems("company", pageRequest), 2, 3);
|
||||||
Assert.isTrue(companies2.at("/data/items").size() == 2, "数量错误");
|
|
||||||
Assert.isTrue(companies2.at("/data/total").asLong() == 3, "返回数量错误");
|
|
||||||
|
|
||||||
formatLog("List Queryable");
|
formatLog("List Queryable");
|
||||||
// language=JSON
|
// language=JSON
|
||||||
@@ -104,18 +100,21 @@ public class AbstractTestApplication {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
""";
|
""";
|
||||||
var companies3 = listItems("company", queryRequest);
|
assertListItems(listItems("company", queryRequest), 1, 1);
|
||||||
Assert.isTrue(companies3.at("/data/items").size() == 1, "数量错误");
|
|
||||||
Assert.isTrue(companies3.at("/data/total").asLong() == 1, "返回数量错误");
|
|
||||||
|
|
||||||
formatLog("Clean");
|
formatLog("Clean");
|
||||||
removeItem("company", cid1);
|
removeItem("company", cid1);
|
||||||
Assert.isTrue(listItems("company").at("/data/items").size() == 2, "数量错误");
|
assertListItems(listItems("company"), 2, 2);
|
||||||
Assert.isTrue(listItems("company").at("/data/total").asLong() == 2, "返回数量错误");
|
|
||||||
removeItem("company", cid2);
|
removeItem("company", cid2);
|
||||||
removeItem("company", cid3);
|
removeItem("company", cid3);
|
||||||
Assert.isTrue(listItems("company").at("/data/items").isEmpty(), "数量错误");
|
assertListItems(listItems("company"), 0, 0);
|
||||||
Assert.isTrue(listItems("company").at("/data/total").asLong() == 0, "返回数量错误");
|
}
|
||||||
|
|
||||||
|
protected void assertListItems(JsonNode node, int itemSizeTarget, int itemTotalTarget) {
|
||||||
|
var itemSize = node.at("/data/items").size();
|
||||||
|
var itemTotal = node.at("/data/total").asLong();
|
||||||
|
Assert.isTrue(itemSize == itemSizeTarget, "数量错误 (%d)".formatted(itemSize));
|
||||||
|
Assert.isTrue(itemTotal == itemTotalTarget, "分页总数错误 (%d)".formatted(itemTotal));
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void formatLog(String text) {
|
protected void formatLog(String text) {
|
||||||
|
|||||||
@@ -29,8 +29,8 @@
|
|||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.h2database</groupId>
|
<groupId>com.lanyuanxiaoyao</groupId>
|
||||||
<artifactId>h2</artifactId>
|
<artifactId>spring-boot-service-template-database-common-test</artifactId>
|
||||||
<scope>test</scope>
|
<scope>test</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
package com.lanyuanxiaoyao.service.template.xbatis.configuration;
|
package com.lanyuanxiaoyao.service.template.database.xbatis.configuration;
|
||||||
|
|
||||||
import cn.xbatis.core.incrementer.GeneratorFactory;
|
import cn.xbatis.core.incrementer.GeneratorFactory;
|
||||||
import cn.xbatis.core.mybatis.mapper.BasicMapper;
|
import cn.xbatis.core.mybatis.mapper.BasicMapper;
|
||||||
import com.lanyuanxiaoyao.service.template.xbatis.entity.SnowflakeIdGenerator;
|
import com.lanyuanxiaoyao.service.template.database.xbatis.entity.SnowflakeIdGenerator;
|
||||||
import com.lanyuanxiaoyao.service.template.xbatis.mapper.MybatisBasicMapper;
|
import com.lanyuanxiaoyao.service.template.database.xbatis.mapper.MybatisBasicMapper;
|
||||||
import org.mybatis.spring.annotation.MapperScan;
|
import org.mybatis.spring.annotation.MapperScan;
|
||||||
import org.springframework.context.annotation.Configuration;
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
|
||||||
@@ -1,11 +1,11 @@
|
|||||||
package com.lanyuanxiaoyao.service.template.xbatis.controller;
|
package com.lanyuanxiaoyao.service.template.database.xbatis.controller;
|
||||||
|
|
||||||
import com.lanyuanxiaoyao.service.template.common.helper.ObjectHelper;
|
import com.lanyuanxiaoyao.service.template.common.helper.ObjectHelper;
|
||||||
import com.lanyuanxiaoyao.service.template.database.common.controller.SimpleController;
|
import com.lanyuanxiaoyao.service.template.database.common.controller.SimpleController;
|
||||||
import com.lanyuanxiaoyao.service.template.database.common.entity.GlobalResponse;
|
import com.lanyuanxiaoyao.service.template.database.common.entity.GlobalResponse;
|
||||||
import com.lanyuanxiaoyao.service.template.database.common.entity.Query;
|
import com.lanyuanxiaoyao.service.template.database.common.entity.Query;
|
||||||
import com.lanyuanxiaoyao.service.template.xbatis.entity.SimpleEntity;
|
import com.lanyuanxiaoyao.service.template.database.xbatis.entity.SimpleEntity;
|
||||||
import com.lanyuanxiaoyao.service.template.xbatis.service.SimpleServiceSupport;
|
import com.lanyuanxiaoyao.service.template.database.xbatis.service.SimpleServiceSupport;
|
||||||
import java.util.function.Function;
|
import java.util.function.Function;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.springframework.transaction.annotation.Transactional;
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
package com.lanyuanxiaoyao.service.template.xbatis.entity;
|
package com.lanyuanxiaoyao.service.template.database.xbatis.entity;
|
||||||
|
|
||||||
import cn.xbatis.db.IdAutoType;
|
import cn.xbatis.db.IdAutoType;
|
||||||
import cn.xbatis.db.annotations.TableId;
|
import cn.xbatis.db.annotations.TableId;
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
package com.lanyuanxiaoyao.service.template.database.xbatis.entity;
|
||||||
|
|
||||||
|
import cn.xbatis.db.annotations.LogicDelete;
|
||||||
|
import cn.xbatis.db.annotations.LogicDeleteTime;
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.Setter;
|
||||||
|
import lombok.ToString;
|
||||||
|
import lombok.experimental.FieldNameConstants;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
@ToString
|
||||||
|
@FieldNameConstants
|
||||||
|
public class LogicDeleteEntity extends IdOnlyEntity {
|
||||||
|
@LogicDelete
|
||||||
|
private Boolean deleted = false;
|
||||||
|
@LogicDeleteTime
|
||||||
|
private LocalDateTime deletedTime;
|
||||||
|
}
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
package com.lanyuanxiaoyao.service.template.xbatis.entity;
|
package com.lanyuanxiaoyao.service.template.database.xbatis.entity;
|
||||||
|
|
||||||
import cn.xbatis.db.annotations.TableField;
|
import cn.xbatis.db.annotations.TableField;
|
||||||
import java.time.LocalDateTime;
|
import java.time.LocalDateTime;
|
||||||
@@ -11,7 +11,7 @@ import lombok.experimental.FieldNameConstants;
|
|||||||
@Setter
|
@Setter
|
||||||
@ToString(callSuper = true)
|
@ToString(callSuper = true)
|
||||||
@FieldNameConstants
|
@FieldNameConstants
|
||||||
public class SimpleEntity extends IdOnlyEntity {
|
public class SimpleEntity extends LogicDeleteEntity {
|
||||||
@TableField(defaultValue = "{NOW}", defaultValueFillAlways = true)
|
@TableField(defaultValue = "{NOW}", defaultValueFillAlways = true)
|
||||||
private LocalDateTime createdTime;
|
private LocalDateTime createdTime;
|
||||||
@TableField(defaultValue = "{NOW}", defaultValueFillAlways = true, updateDefaultValue = "{NOW}", updateDefaultValueFillAlways = true)
|
@TableField(defaultValue = "{NOW}", defaultValueFillAlways = true, updateDefaultValue = "{NOW}", updateDefaultValueFillAlways = true)
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
package com.lanyuanxiaoyao.service.template.xbatis.entity;
|
package com.lanyuanxiaoyao.service.template.database.xbatis.entity;
|
||||||
|
|
||||||
import cn.xbatis.core.incrementer.Generator;
|
import cn.xbatis.core.incrementer.Generator;
|
||||||
import com.lanyuanxiaoyao.service.template.database.common.helper.SnowflakeHelper;
|
import com.lanyuanxiaoyao.service.template.database.common.helper.SnowflakeHelper;
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
package com.lanyuanxiaoyao.service.template.xbatis.mapper;
|
package com.lanyuanxiaoyao.service.template.database.xbatis.mapper;
|
||||||
|
|
||||||
import cn.xbatis.core.mybatis.mapper.BasicMapper;
|
import cn.xbatis.core.mybatis.mapper.BasicMapper;
|
||||||
|
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
package com.lanyuanxiaoyao.service.template.xbatis.service;
|
package com.lanyuanxiaoyao.service.template.database.xbatis.service;
|
||||||
|
|
||||||
import cn.xbatis.core.mybatis.mapper.context.Pager;
|
import cn.xbatis.core.mybatis.mapper.context.Pager;
|
||||||
import cn.xbatis.core.sql.MybatisCmdFactory;
|
import cn.xbatis.core.sql.MybatisCmdFactory;
|
||||||
@@ -9,8 +9,8 @@ import com.lanyuanxiaoyao.service.template.database.common.entity.Query;
|
|||||||
import com.lanyuanxiaoyao.service.template.database.common.exception.IdNotFoundException;
|
import com.lanyuanxiaoyao.service.template.database.common.exception.IdNotFoundException;
|
||||||
import com.lanyuanxiaoyao.service.template.database.common.service.QueryParser;
|
import com.lanyuanxiaoyao.service.template.database.common.service.QueryParser;
|
||||||
import com.lanyuanxiaoyao.service.template.database.common.service.SimpleService;
|
import com.lanyuanxiaoyao.service.template.database.common.service.SimpleService;
|
||||||
import com.lanyuanxiaoyao.service.template.xbatis.entity.SimpleEntity;
|
import com.lanyuanxiaoyao.service.template.database.xbatis.entity.SimpleEntity;
|
||||||
import com.lanyuanxiaoyao.service.template.xbatis.mapper.MybatisBasicMapper;
|
import com.lanyuanxiaoyao.service.template.database.xbatis.mapper.MybatisBasicMapper;
|
||||||
import db.sql.api.cmd.LikeMode;
|
import db.sql.api.cmd.LikeMode;
|
||||||
import db.sql.api.impl.cmd.basic.OrderByDirection;
|
import db.sql.api.impl.cmd.basic.OrderByDirection;
|
||||||
import db.sql.api.impl.cmd.struct.Where;
|
import db.sql.api.impl.cmd.struct.Where;
|
||||||
@@ -37,13 +37,14 @@ public abstract class SimpleServiceSupport<ENTITY extends SimpleEntity> implemen
|
|||||||
@Transactional(rollbackFor = Throwable.class)
|
@Transactional(rollbackFor = Throwable.class)
|
||||||
@Override
|
@Override
|
||||||
public Long save(ENTITY entity) {
|
public Long save(ENTITY entity) {
|
||||||
return (long) mapper.save(entity);
|
mapper.saveOrUpdate(entity);
|
||||||
|
return entity.getId();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Transactional(rollbackFor = Throwable.class)
|
@Transactional(rollbackFor = Throwable.class)
|
||||||
@Override
|
@Override
|
||||||
public void save(Iterable<ENTITY> entities) {
|
public void save(Iterable<ENTITY> entities) {
|
||||||
mapper.save(entities);
|
mapper.saveOrUpdate(entities);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -75,7 +76,6 @@ public abstract class SimpleServiceSupport<ENTITY extends SimpleEntity> implemen
|
|||||||
var size = Math.max(ObjectHelper.defaultIfNull(query.page().size(), DEFAULT_PAGE_SIZE), 1);
|
var size = Math.max(ObjectHelper.defaultIfNull(query.page().size(), DEFAULT_PAGE_SIZE), 1);
|
||||||
paging = Pager.of(index, size);
|
paging = Pager.of(index, size);
|
||||||
}
|
}
|
||||||
chain.paging(paging);
|
|
||||||
|
|
||||||
if (ObjectHelper.isNotEmpty(query.sort())) {
|
if (ObjectHelper.isNotEmpty(query.sort())) {
|
||||||
query.sort().forEach(sort -> chain.orderBy(OrderByDirection.valueOf(sort.direction().name()), sort.column()));
|
query.sort().forEach(sort -> chain.orderBy(OrderByDirection.valueOf(sort.direction().name()), sort.column()));
|
||||||
@@ -85,14 +85,16 @@ public abstract class SimpleServiceSupport<ENTITY extends SimpleEntity> implemen
|
|||||||
commonPredicates(where);
|
commonPredicates(where);
|
||||||
new XBatisQueryParser<>(query.query(), where, target, factory).build();
|
new XBatisQueryParser<>(query.query(), where, target, factory).build();
|
||||||
|
|
||||||
return new Page<>(chain.list(), chain.count());
|
var pager = chain.paging(paging);
|
||||||
|
|
||||||
|
return new Page<>(pager.getResults(), pager.getTotal());
|
||||||
}
|
}
|
||||||
|
|
||||||
private Optional<ENTITY> detailOptional(Long id) {
|
private Optional<ENTITY> detailOptional(Long id) {
|
||||||
if (ObjectHelper.isNull(id)) {
|
if (ObjectHelper.isNull(id)) {
|
||||||
return Optional.empty();
|
return Optional.empty();
|
||||||
}
|
}
|
||||||
return Optional.ofNullable(mapper.getById(target, id));
|
return mapper.getOptionalById(target, id);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Named("detail")
|
@Named("detail")
|
||||||
@@ -181,22 +183,22 @@ public abstract class SimpleServiceSupport<ENTITY extends SimpleEntity> implemen
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void startWith(Query.Queryable queryable, Where where) {
|
protected void startWith(Query.Queryable queryable, Where where) {
|
||||||
queryable.startWith().forEach((column, value) -> where.like(LikeMode.LEFT, factory.field(target, column), value));
|
queryable.startWith().forEach((column, value) -> where.like(LikeMode.RIGHT, factory.field(target, column), value));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void notStartWith(Query.Queryable queryable, Where where) {
|
protected void notStartWith(Query.Queryable queryable, Where where) {
|
||||||
queryable.notStartWith().forEach((column, value) -> where.notLike(LikeMode.LEFT, factory.field(target, column), value));
|
queryable.notStartWith().forEach((column, value) -> where.notLike(LikeMode.RIGHT, factory.field(target, column), value));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void endWith(Query.Queryable queryable, Where where) {
|
protected void endWith(Query.Queryable queryable, Where where) {
|
||||||
queryable.endWith().forEach((column, value) -> where.like(LikeMode.RIGHT, factory.field(target, column), value));
|
queryable.endWith().forEach((column, value) -> where.like(LikeMode.LEFT, factory.field(target, column), value));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void notEndWith(Query.Queryable queryable, Where where) {
|
protected void notEndWith(Query.Queryable queryable, Where where) {
|
||||||
queryable.notEndWith().forEach((column, value) -> where.notLike(LikeMode.RIGHT, factory.field(target, column), value));
|
queryable.notEndWith().forEach((column, value) -> where.notLike(LikeMode.LEFT, factory.field(target, column), value));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -4,7 +4,9 @@ create table if not exists Company
|
|||||||
name varchar(255) not null,
|
name varchar(255) not null,
|
||||||
members int not null,
|
members int not null,
|
||||||
created_time timestamp not null,
|
created_time timestamp not null,
|
||||||
modified_time timestamp not null
|
modified_time timestamp not null,
|
||||||
|
deleted tinyint not null default 0,
|
||||||
|
deleted_time timestamp
|
||||||
);
|
);
|
||||||
|
|
||||||
create table if not exists Employee
|
create table if not exists Employee
|
||||||
@@ -12,6 +14,9 @@ create table if not exists Employee
|
|||||||
id bigint primary key,
|
id bigint primary key,
|
||||||
name varchar(255) not null,
|
name varchar(255) not null,
|
||||||
age int not null,
|
age int not null,
|
||||||
|
company_id bigint not null,
|
||||||
created_time timestamp not null,
|
created_time timestamp not null,
|
||||||
modified_time timestamp not null
|
modified_time timestamp not null,
|
||||||
|
deleted tinyint not null default 0,
|
||||||
|
deleted_time timestamp
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -0,0 +1,82 @@
|
|||||||
|
package com.lanyuanxiaoyao.service.template.database.xbatis;
|
||||||
|
|
||||||
|
import cn.xbatis.core.sql.executor.chain.QueryChain;
|
||||||
|
import com.lanyuanxiaoyao.service.template.database.common.test.AbstractTestApplication;
|
||||||
|
import com.lanyuanxiaoyao.service.template.database.xbatis.entity.Company;
|
||||||
|
import com.lanyuanxiaoyao.service.template.database.xbatis.entity.Employee;
|
||||||
|
import com.lanyuanxiaoyao.service.template.database.xbatis.entity.vo.EmployeeWithCompanyName;
|
||||||
|
import com.lanyuanxiaoyao.service.template.database.xbatis.mapper.MybatisBasicMapper;
|
||||||
|
import db.sql.api.cmd.LikeMode;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.mybatis.spring.annotation.MapperScan;
|
||||||
|
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.util.Assert;
|
||||||
|
|
||||||
|
@Slf4j
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
@MapperScan("com.lanyuanxiaoyao.service.template.database.xbatis.mapper")
|
||||||
|
@SpringBootApplication
|
||||||
|
public class TestApplication extends AbstractTestApplication {
|
||||||
|
private final MybatisBasicMapper mapper;
|
||||||
|
|
||||||
|
public static void main(String[] args) {
|
||||||
|
SpringApplication.run(TestApplication.class, args);
|
||||||
|
}
|
||||||
|
|
||||||
|
@EventListener(ApplicationReadyEvent.class)
|
||||||
|
public void runTests() {
|
||||||
|
testCrud();
|
||||||
|
testDelete();
|
||||||
|
testQuery();
|
||||||
|
|
||||||
|
System.exit(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void testDelete() {
|
||||||
|
formatLog("Delete");
|
||||||
|
saveItem("company", randomCompany());
|
||||||
|
saveItem("company", randomCompany());
|
||||||
|
mapper.deleteAll(Company.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void testQuery() {
|
||||||
|
formatLog("Added");
|
||||||
|
var company1 = Company.builder().name(randomString(5)).members(randomInt(100)).build();
|
||||||
|
mapper.saveOrUpdate(company1);
|
||||||
|
var company2 = Company.builder().name(randomString(5)).members(randomInt(100)).build();
|
||||||
|
mapper.saveOrUpdate(company2);
|
||||||
|
var employee1 = Employee.builder().name("Tom").age(randomInt(100)).companyId(company1.getId()).build();
|
||||||
|
mapper.saveOrUpdate(employee1);
|
||||||
|
var employee2 = Employee.builder().name(randomString(10)).age(randomInt(100)).companyId(company2.getId()).build();
|
||||||
|
mapper.saveOrUpdate(employee2);
|
||||||
|
|
||||||
|
formatLog("Query");
|
||||||
|
var employees1 = QueryChain.of(mapper, Employee.class)
|
||||||
|
.isNotNull(Employee::getName)
|
||||||
|
.eq(Employee::getName, "Tom")
|
||||||
|
.like(Employee::getName, "To")
|
||||||
|
.like(LikeMode.RIGHT, Employee::getName, "To")
|
||||||
|
.like(LikeMode.LEFT, Employee::getName, "om")
|
||||||
|
.lt(Employee::getAge, 200)
|
||||||
|
.gt(Employee::getAge, 0)
|
||||||
|
.in(Employee::getName, "Tom", "Mike")
|
||||||
|
.between(Employee::getAge, 0, 200)
|
||||||
|
.list();
|
||||||
|
Assert.isTrue(employees1.size() == 1, "查询数量错误");
|
||||||
|
|
||||||
|
formatLog("Query Join");
|
||||||
|
var employees2 = QueryChain.of(mapper, Employee.class)
|
||||||
|
.select(Employee::getName, Employee::getAge)
|
||||||
|
.select(Company::getId, c -> c.as(EmployeeWithCompanyName::getCompanyName))
|
||||||
|
.leftJoin(Employee.class, Company.class, on -> on.eq(Employee::getCompanyId, Company::getId).gt(Company::getMembers, 0))
|
||||||
|
.eq(Employee::getName, "Tom")
|
||||||
|
.lt(Company::getMembers, 200)
|
||||||
|
.returnType(EmployeeWithCompanyName.class)
|
||||||
|
.list();
|
||||||
|
Assert.isTrue(employees2.size() == 1, "查询数量错误");
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
package com.lanyuanxiaoyao.service.template.xbatis.controller;
|
package com.lanyuanxiaoyao.service.template.database.xbatis.controller;
|
||||||
|
|
||||||
import com.lanyuanxiaoyao.service.template.xbatis.entity.Company;
|
import com.lanyuanxiaoyao.service.template.database.xbatis.entity.Company;
|
||||||
import com.lanyuanxiaoyao.service.template.xbatis.service.CompanyService;
|
import com.lanyuanxiaoyao.service.template.database.xbatis.service.CompanyService;
|
||||||
import java.time.LocalDateTime;
|
import java.time.LocalDateTime;
|
||||||
import java.util.function.Function;
|
import java.util.function.Function;
|
||||||
import org.springframework.web.bind.annotation.RequestMapping;
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
@@ -1,7 +1,10 @@
|
|||||||
package com.lanyuanxiaoyao.service.template.xbatis.entity;
|
package com.lanyuanxiaoyao.service.template.database.xbatis.entity;
|
||||||
|
|
||||||
import cn.xbatis.db.annotations.Table;
|
import cn.xbatis.db.annotations.Table;
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Builder;
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
import lombok.Setter;
|
import lombok.Setter;
|
||||||
import lombok.ToString;
|
import lombok.ToString;
|
||||||
import lombok.experimental.FieldNameConstants;
|
import lombok.experimental.FieldNameConstants;
|
||||||
@@ -10,6 +13,9 @@ import lombok.experimental.FieldNameConstants;
|
|||||||
@Setter
|
@Setter
|
||||||
@ToString(callSuper = true)
|
@ToString(callSuper = true)
|
||||||
@FieldNameConstants
|
@FieldNameConstants
|
||||||
|
@AllArgsConstructor
|
||||||
|
@NoArgsConstructor
|
||||||
|
@Builder
|
||||||
@Table
|
@Table
|
||||||
public class Company extends SimpleEntity {
|
public class Company extends SimpleEntity {
|
||||||
private String name;
|
private String name;
|
||||||
@@ -0,0 +1,25 @@
|
|||||||
|
package com.lanyuanxiaoyao.service.template.database.xbatis.entity;
|
||||||
|
|
||||||
|
import cn.xbatis.db.annotations.Table;
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Builder;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
import lombok.Setter;
|
||||||
|
import lombok.ToString;
|
||||||
|
import lombok.experimental.FieldNameConstants;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
@ToString(callSuper = true)
|
||||||
|
@FieldNameConstants
|
||||||
|
@AllArgsConstructor
|
||||||
|
@NoArgsConstructor
|
||||||
|
@Builder
|
||||||
|
@Table
|
||||||
|
public class Employee extends SimpleEntity {
|
||||||
|
private String name;
|
||||||
|
private Integer age;
|
||||||
|
|
||||||
|
private Long companyId;
|
||||||
|
}
|
||||||
@@ -1,6 +1,5 @@
|
|||||||
package com.lanyuanxiaoyao.service.template.xbatis.entity;
|
package com.lanyuanxiaoyao.service.template.database.xbatis.entity.vo;
|
||||||
|
|
||||||
import cn.xbatis.db.annotations.Table;
|
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
import lombok.Setter;
|
import lombok.Setter;
|
||||||
import lombok.ToString;
|
import lombok.ToString;
|
||||||
@@ -10,8 +9,8 @@ import lombok.experimental.FieldNameConstants;
|
|||||||
@Setter
|
@Setter
|
||||||
@ToString(callSuper = true)
|
@ToString(callSuper = true)
|
||||||
@FieldNameConstants
|
@FieldNameConstants
|
||||||
@Table
|
public class EmployeeWithCompanyName {
|
||||||
public class Employee extends SimpleEntity {
|
|
||||||
private String name;
|
private String name;
|
||||||
private Integer age;
|
private Integer age;
|
||||||
|
private String companyName;
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
package com.lanyuanxiaoyao.service.template.database.xbatis.service;
|
||||||
|
|
||||||
|
import com.lanyuanxiaoyao.service.template.database.xbatis.entity.Company;
|
||||||
|
import com.lanyuanxiaoyao.service.template.database.xbatis.mapper.MybatisBasicMapper;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
@Service
|
||||||
|
public class CompanyService extends SimpleServiceSupport<Company> {
|
||||||
|
public CompanyService(MybatisBasicMapper mapper) {
|
||||||
|
super(Company.class, mapper);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
package com.lanyuanxiaoyao.service.template.database.xbatis.service;
|
||||||
|
|
||||||
|
import com.lanyuanxiaoyao.service.template.database.xbatis.entity.Employee;
|
||||||
|
import com.lanyuanxiaoyao.service.template.database.xbatis.mapper.MybatisBasicMapper;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
@Service
|
||||||
|
public class EmployeeService extends SimpleServiceSupport<Employee> {
|
||||||
|
public EmployeeService(MybatisBasicMapper mapper) {
|
||||||
|
super(Employee.class, mapper);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,173 +0,0 @@
|
|||||||
package com.lanyuanxiaoyao.service.template.xbatis;
|
|
||||||
|
|
||||||
import lombok.extern.slf4j.Slf4j;
|
|
||||||
import org.mybatis.spring.annotation.MapperScan;
|
|
||||||
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.http.HttpEntity;
|
|
||||||
import org.springframework.http.HttpHeaders;
|
|
||||||
import org.springframework.http.MediaType;
|
|
||||||
import org.springframework.util.Assert;
|
|
||||||
import org.springframework.web.client.RestTemplate;
|
|
||||||
import tools.jackson.databind.JsonNode;
|
|
||||||
import tools.jackson.databind.ObjectMapper;
|
|
||||||
|
|
||||||
@Slf4j
|
|
||||||
@MapperScan("com.lanyuanxiaoyao.service.template.xbatis.mapper")
|
|
||||||
@SpringBootApplication
|
|
||||||
public class TestApplication {
|
|
||||||
private static final String BASE_URL = "http://localhost:2490";
|
|
||||||
private static final RestTemplate REST_CLIENT = new RestTemplate();
|
|
||||||
private static final ObjectMapper MAPPER = new ObjectMapper();
|
|
||||||
|
|
||||||
public static void main(String[] args) {
|
|
||||||
SpringApplication.run(TestApplication.class, args);
|
|
||||||
}
|
|
||||||
|
|
||||||
@EventListener(ApplicationReadyEvent.class)
|
|
||||||
public void runTests() {
|
|
||||||
// 增
|
|
||||||
var cid1 = saveItem("company", "{\"name\": \"Apple\",\"members\": 10}").get("data").asLong();
|
|
||||||
var cid2 = saveItem("company", "{\"name\": \"Banana\",\"members\": 20}").get("data").asLong();
|
|
||||||
var cid3 = saveItem("company", "{\"name\": \"Cheery\",\"members\": 20}").get("data").asLong();
|
|
||||||
|
|
||||||
// 查
|
|
||||||
var companies = listItems("company");
|
|
||||||
Assert.isTrue(companies.at("/data/items").size() == 3, "数量错误");
|
|
||||||
Assert.isTrue(companies.at("/data/total").asLong() == 3, "返回数量错误");
|
|
||||||
|
|
||||||
// language=JSON
|
|
||||||
var companies2 = listItems("company", "{\n" +
|
|
||||||
" \"page\": {\n" +
|
|
||||||
" \"index\": 1,\n" +
|
|
||||||
" \"size\": 2\n" +
|
|
||||||
" }\n" +
|
|
||||||
"}");
|
|
||||||
Assert.isTrue(companies2.at("/data/items").size() == 2, "数量错误");
|
|
||||||
Assert.isTrue(companies2.at("/data/total").asLong() == 3, "返回数量错误");
|
|
||||||
// language=JSON
|
|
||||||
var companies3 = listItems("company", "{\n" +
|
|
||||||
" \"query\": {\n" +
|
|
||||||
" \"notNullEqual\": [\n" +
|
|
||||||
" \"name\"\n" +
|
|
||||||
" ],\n" +
|
|
||||||
" \"equal\": {\n" +
|
|
||||||
" \"name\": \"Apple\"\n" +
|
|
||||||
" },\n" +
|
|
||||||
" \"like\": {\n" +
|
|
||||||
" \"name\": \"Appl%\"\n" +
|
|
||||||
" },\n" +
|
|
||||||
" \"contain\": {\n" +
|
|
||||||
" \"name\": \"ple\"\n" +
|
|
||||||
" },\n" +
|
|
||||||
" \"startWith\": {\n" +
|
|
||||||
" \"name\": \"Appl\"\n" +
|
|
||||||
" },\n" +
|
|
||||||
" \"endWith\": {\n" +
|
|
||||||
" \"name\": \"le\"\n" +
|
|
||||||
" },\n" +
|
|
||||||
" \"less\": {\n" +
|
|
||||||
" \"members\": 50\n" +
|
|
||||||
" },\n" +
|
|
||||||
" \"greatEqual\": {\n" +
|
|
||||||
" \"members\": 0,\n" +
|
|
||||||
" \"createdTime\": \"2025-01-01 00:00:00\"\n" +
|
|
||||||
" },\n" +
|
|
||||||
" \"inside\": {\n" +
|
|
||||||
" \"name\": [\n" +
|
|
||||||
" \"Apple\",\n" +
|
|
||||||
" \"Banana\"\n" +
|
|
||||||
" ]\n" +
|
|
||||||
" },\n" +
|
|
||||||
" \"between\": {\n" +
|
|
||||||
" \"members\": {\n" +
|
|
||||||
" \"start\": 0,\n" +
|
|
||||||
" \"end\": 50\n" +
|
|
||||||
" }\n" +
|
|
||||||
" }\n" +
|
|
||||||
" },\n" +
|
|
||||||
" \"page\": {\n" +
|
|
||||||
" \"index\": 1,\n" +
|
|
||||||
" \"size\": 2\n" +
|
|
||||||
" }\n" +
|
|
||||||
"}");
|
|
||||||
Assert.isTrue(companies3.at("/data/items").size() == 1, "数量错误");
|
|
||||||
Assert.isTrue(companies3.at("/data/total").asLong() == 1, "返回数量错误");
|
|
||||||
|
|
||||||
var company1 = detailItem("company", cid1);
|
|
||||||
Assert.isTrue(cid1 == company1.at("/data/id").asLong(), "id错误");
|
|
||||||
Assert.isTrue("Apple".equals(company1.at("/data/name").asText()), "name错误");
|
|
||||||
|
|
||||||
// 改
|
|
||||||
var cid4 = saveItem("company", "{\"id\": %d, \"name\": \"Dog\"}".formatted(cid2)).get("data").asLong();
|
|
||||||
Assert.isTrue(cid2 == cid4, "id错误");
|
|
||||||
var company2 = detailItem("company", cid2);
|
|
||||||
Assert.isTrue("Dog".equals(company2.at("/data/name").asText()), "name错误");
|
|
||||||
|
|
||||||
// 删
|
|
||||||
removeItem("company", cid3);
|
|
||||||
Assert.isTrue(listItems("company").at("/data/items").size() == 2, "数量错误");
|
|
||||||
Assert.isTrue(listItems("company").at("/data/total").asLong() == 2, "返回数量错误");
|
|
||||||
|
|
||||||
log.info(listItems("company").toPrettyString());
|
|
||||||
System.exit(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
private HttpHeaders headers() {
|
|
||||||
var headers = new HttpHeaders();
|
|
||||||
headers.setContentType(MediaType.APPLICATION_JSON);
|
|
||||||
return headers;
|
|
||||||
}
|
|
||||||
|
|
||||||
private JsonNode saveItem(String path, String body) {
|
|
||||||
var response = REST_CLIENT.postForEntity(
|
|
||||||
"%s/%s/save".formatted(BASE_URL, path),
|
|
||||||
new HttpEntity<>(body, headers()),
|
|
||||||
String.class
|
|
||||||
);
|
|
||||||
Assert.isTrue(response.getStatusCode().is2xxSuccessful(), "请求失败");
|
|
||||||
Assert.notNull(response.getBody(), "请求失败");
|
|
||||||
return MAPPER.readTree(response.getBody());
|
|
||||||
}
|
|
||||||
|
|
||||||
private JsonNode listItems(String path) {
|
|
||||||
var response = REST_CLIENT.getForEntity(
|
|
||||||
"%s/%s/list".formatted(BASE_URL, path),
|
|
||||||
String.class
|
|
||||||
);
|
|
||||||
Assert.isTrue(response.getStatusCode().is2xxSuccessful(), "请求失败");
|
|
||||||
Assert.notNull(response.getBody(), "请求失败");
|
|
||||||
return MAPPER.readTree(response.getBody());
|
|
||||||
}
|
|
||||||
|
|
||||||
private JsonNode listItems(String path, String query) {
|
|
||||||
var response = REST_CLIENT.postForEntity(
|
|
||||||
"%s/%s/list".formatted(BASE_URL, path),
|
|
||||||
new HttpEntity<>(query, headers()),
|
|
||||||
String.class
|
|
||||||
);
|
|
||||||
Assert.isTrue(response.getStatusCode().is2xxSuccessful(), "请求失败");
|
|
||||||
Assert.notNull(response.getBody(), "请求失败");
|
|
||||||
return MAPPER.readTree(response.getBody());
|
|
||||||
}
|
|
||||||
|
|
||||||
private JsonNode detailItem(String path, Long id) {
|
|
||||||
var response = REST_CLIENT.getForEntity(
|
|
||||||
"%s/%s/detail/%d".formatted(BASE_URL, path, id),
|
|
||||||
String.class
|
|
||||||
);
|
|
||||||
Assert.isTrue(response.getStatusCode().is2xxSuccessful(), "请求失败");
|
|
||||||
Assert.notNull(response.getBody(), "请求失败");
|
|
||||||
return MAPPER.readTree(response.getBody());
|
|
||||||
}
|
|
||||||
|
|
||||||
private void removeItem(String path, Long id) {
|
|
||||||
var response = REST_CLIENT.getForEntity(
|
|
||||||
"%s/%s/remove/%d".formatted(BASE_URL, path, id),
|
|
||||||
Void.class
|
|
||||||
);
|
|
||||||
Assert.isTrue(response.getStatusCode().is2xxSuccessful(), "请求失败");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,12 +0,0 @@
|
|||||||
package com.lanyuanxiaoyao.service.template.xbatis.service;
|
|
||||||
|
|
||||||
import com.lanyuanxiaoyao.service.template.xbatis.entity.Company;
|
|
||||||
import com.lanyuanxiaoyao.service.template.xbatis.mapper.MybatisBasicMapper;
|
|
||||||
import org.springframework.stereotype.Service;
|
|
||||||
|
|
||||||
@Service
|
|
||||||
public class CompanyService extends SimpleServiceSupport<Company> {
|
|
||||||
public CompanyService(MybatisBasicMapper mapper) {
|
|
||||||
super(Company.class, mapper);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,12 +0,0 @@
|
|||||||
package com.lanyuanxiaoyao.service.template.xbatis.service;
|
|
||||||
|
|
||||||
import com.lanyuanxiaoyao.service.template.xbatis.entity.Employee;
|
|
||||||
import com.lanyuanxiaoyao.service.template.xbatis.mapper.MybatisBasicMapper;
|
|
||||||
import org.springframework.stereotype.Service;
|
|
||||||
|
|
||||||
@Service
|
|
||||||
public class EmployeeService extends SimpleServiceSupport<Employee> {
|
|
||||||
public EmployeeService(MybatisBasicMapper mapper) {
|
|
||||||
super(Employee.class, mapper);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,8 +1,6 @@
|
|||||||
server:
|
|
||||||
port: 2490
|
|
||||||
spring:
|
spring:
|
||||||
application:
|
profiles:
|
||||||
name: Test
|
include: test
|
||||||
datasource:
|
datasource:
|
||||||
url: "jdbc:h2:mem:testdb;DB_CLOSE_DELAY=-1;MODE=MySQL;DATABASE_TO_LOWER=TRUE;INIT=runscript from '/Users/lanyuanxiaoyao/Project/IdeaProjects/spring-boot-service-template/spring-boot-service-template-database/spring-boot-service-template-database-xbatis/src/test/initial.sql'"
|
url: "jdbc:h2:mem:testdb;DB_CLOSE_DELAY=-1;MODE=MySQL;DATABASE_TO_LOWER=TRUE;INIT=runscript from '/Users/lanyuanxiaoyao/Project/IdeaProjects/spring-boot-service-template/spring-boot-service-template-database/spring-boot-service-template-database-xbatis/src/test/initial.sql'"
|
||||||
username: test
|
username: test
|
||||||
@@ -10,13 +8,4 @@ spring:
|
|||||||
driver-class-name: org.h2.Driver
|
driver-class-name: org.h2.Driver
|
||||||
mybatis:
|
mybatis:
|
||||||
configuration:
|
configuration:
|
||||||
banner: false
|
banner: false
|
||||||
decorator:
|
|
||||||
datasource:
|
|
||||||
p6spy:
|
|
||||||
multiline: false
|
|
||||||
exclude-categories:
|
|
||||||
- commit
|
|
||||||
- result
|
|
||||||
- resultset
|
|
||||||
log-format: "%(category)|%(executionTime)|%(sqlSingleLine)"
|
|
||||||
Reference in New Issue
Block a user