Merge pull request #227 from mofan212/unit-test

test: remove System.out.println(), use assert
This commit is contained in:
Michael Yang 2023-12-06 10:39:04 +08:00 committed by GitHub
commit 1902324018
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
32 changed files with 1529 additions and 366 deletions

View File

@ -24,7 +24,7 @@ import com.mybatisflex.core.mask.Masks;
import java.io.Serializable;
@Table(value = "tb_account", dataSource = "ds2", onSet = AccountOnSetListener.class)
@Table(value = "tb_account6", dataSource = "ds2", onSet = AccountOnSetListener.class)
public class Account6 extends BaseEntity implements Serializable, AgeAware {
private static final long serialVersionUID = 1L;

View File

@ -24,7 +24,7 @@ import com.mybatisflex.core.mask.Masks;
import java.io.Serializable;
@Table(value = "tb_account")
@Table(value = "tb_account7")
public class Account7 extends BaseEntity implements Serializable, AgeAware {
private static final long serialVersionUID = 1L;

View File

@ -22,7 +22,6 @@ public class AccountOnSetListener implements SetListener {
@Override
public Object onSet(Object entity, String property, Object value) {
// System.out.println(">>>>>>> property: " + property +" value:" + value);
return value;
}

View File

@ -17,7 +17,6 @@
package com.mybatisflex.test.relation.onetoone;
import com.mybatisflex.annotation.Id;
import com.mybatisflex.annotation.KeyType;
import com.mybatisflex.annotation.RelationManyToMany;
import com.mybatisflex.annotation.Table;
@ -28,7 +27,7 @@ import java.util.Map;
@Table(value = "tb_account")
public class Account implements Serializable {
@Id(keyType = KeyType.Auto)
@Id
private Long id;
private String userName;

View File

@ -45,7 +45,8 @@ public class AccountDTO implements Serializable {
@RelationManyToMany(
joinTable = "tb_role_mapping",
joinSelfColumn = "account_id",
joinTargetColumn = "role_id"
joinTargetColumn = "role_id",
selfField = "id"
)
private List<Role> roles;

View File

@ -1,129 +0,0 @@
/*
* Copyright (c) 2022-2023, Mybatis-Flex (fuhai999@gmail.com).
* <p>
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* <p>
* http://www.apache.org/licenses/LICENSE-2.0
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.mybatisflex.test.relation.onetoone;
import com.alibaba.fastjson.JSON;
import com.mybatisflex.core.MybatisFlexBootstrap;
import com.mybatisflex.core.audit.AuditManager;
import com.mybatisflex.core.audit.ConsoleMessageCollector;
import com.mybatisflex.core.audit.MessageCollector;
import com.mybatisflex.core.paginate.Page;
import com.mybatisflex.core.query.QueryWrapper;
import com.mybatisflex.core.relation.RelationManager;
import com.mybatisflex.test.relation.mapper.AccountMapper;
import com.mybatisflex.test.relation.mapper.BookMapper;
import com.mybatisflex.test.relation.mapper.MenuMapper;
import org.junit.BeforeClass;
import org.junit.Test;
import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseBuilder;
import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseType;
import javax.sql.DataSource;
import java.util.List;
import static com.mybatisflex.test.relation.onetoone.table.MenuTableDef.MENU;
public class RelationsTester {
static AccountMapper accountMapper;
static BookMapper bookMapper;
static MenuMapper menuMapper;
@BeforeClass
public static void init() {
DataSource dataSource = new EmbeddedDatabaseBuilder()
.setType(EmbeddedDatabaseType.H2)
.addScript("relation/onetoone/schema.sql")
.addScript("relation/onetoone/data.sql")
.build();
MybatisFlexBootstrap bootstrap = MybatisFlexBootstrap.getInstance()
.setDataSource(dataSource)
.addMapper(AccountMapper.class)
.addMapper(BookMapper.class)
.addMapper(MenuMapper.class)
.start();
//开启审计功能
AuditManager.setAuditEnable(true);
//设置 SQL 审计收集器
MessageCollector collector = new ConsoleMessageCollector();
AuditManager.setMessageCollector(collector);
accountMapper = bootstrap.getMapper(AccountMapper.class);
bookMapper = bootstrap.getMapper(BookMapper.class);
menuMapper = bootstrap.getMapper(MenuMapper.class);
}
@Test
public void testOneToOne() {
List<Account> accounts = accountMapper.selectAllWithRelations();
System.out.println(JSON.toJSONString(accounts));
}
@Test
public void testManyToOne() {
List<Book> books = bookMapper.selectAll();
System.out.println(">>>>>>1: " + books);
RelationManager.queryRelations(bookMapper, books);
System.out.println(">>>>>>2: " + books);
}
@Test
public void testManyToMany1() {
List<Account> accounts = accountMapper.selectAll();
System.out.println(">>>>>>1: " + accounts);
RelationManager.queryRelations(accountMapper, accounts);
System.out.println(">>>>>>2: " + accounts);
}
@Test
public void testAsDto() {
List<AccountDTO> accounts = accountMapper.selectListWithRelationsByQueryAs(QueryWrapper.create(), AccountDTO.class);
System.out.println(">>>>>>1: " + accounts);
}
@Test
public void testMenu() {
QueryWrapper qw = QueryWrapper.create();
qw.where(MENU.PARENT_ID.eq(0));
List<Menu> menus = menuMapper.selectListWithRelationsByQuery(qw);
System.out.println(JSON.toJSONString(menus));
}
@Test
public void testMenuIgnoreParent() {
QueryWrapper qw = QueryWrapper.create();
qw.where(MENU.PARENT_ID.eq(0));
RelationManager.addIgnoreRelations("parent");
List<Menu> menus = menuMapper.selectListWithRelationsByQuery(qw);
System.out.println(JSON.toJSONString(menus));
}
@Test
public void testPaginate() {
Page<Account> accountPage = accountMapper.paginateWithRelations(1, 2, QueryWrapper.create());
System.out.println(accountPage);
}
}

View File

@ -16,6 +16,7 @@
package com.mybatisflex.test.relation.onetoone;
import com.mybatisflex.annotation.Id;
import com.mybatisflex.annotation.RelationManyToMany;
import com.mybatisflex.annotation.Table;
@ -25,6 +26,7 @@ import java.util.List;
@Table(value = "tb_role")
public class Role implements Serializable {
@Id
private Long id;
private String name;

View File

@ -0,0 +1,95 @@
package com.mybatisflex.test;
import com.mybatisflex.core.MybatisFlexBootstrap;
import com.mybatisflex.core.audit.AuditManager;
import com.mybatisflex.core.audit.ConsoleMessageCollector;
import com.mybatisflex.core.datasource.DataSourceKey;
import com.mybatisflex.mapper.Account6Mapper;
import org.apache.ibatis.logging.stdout.StdOutImpl;
import org.assertj.core.api.InstanceOfAssertFactories;
import org.assertj.core.api.WithAssertions;
import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import org.springframework.jdbc.datasource.embedded.EmbeddedDatabase;
import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseBuilder;
import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseType;
import java.lang.reflect.InvocationTargetException;
import java.util.List;
/**
* @author mofan
* @date 2023/12/4 22:44
*/
public class Account6Test implements WithAssertions {
private EmbeddedDatabase dataSource;
private Account6Mapper mapper;
private static final String DATA_SOURCE_KEY = "none_key";
@BeforeClass
public static void enableAudit() {
AuditManager.setAuditEnable(true);
AuditManager.setMessageCollector(new ConsoleMessageCollector());
}
@Before
public void init() {
this.dataSource = new EmbeddedDatabaseBuilder()
.setType(EmbeddedDatabaseType.H2)
.addScript("none_key_schema.sql")
.addScript("none_key_data.sql")
.build();
MybatisFlexBootstrap bootstrap = new MybatisFlexBootstrap()
.setDataSource(DATA_SOURCE_KEY, this.dataSource)
.setLogImpl(StdOutImpl.class)
.addMapper(Account6Mapper.class)
.start();
DataSourceKey.use(DATA_SOURCE_KEY);
mapper = bootstrap.getMapper(Account6Mapper.class);
}
@After
public void destroy() {
this.dataSource.shutdown();
DataSourceKey.clear();
}
/**
* issues https://gitee.com/mybatis-flex/mybatis-flex/issues/I873OZ
*/
@Test
public void testGiteeIssue_I873OZ() {
Account6 account1 = new Account6();
account1.setId(3L);
account1.setUserName("michael");
account1.setAge(5);
assertThat(this.mapper.insertSelective(account1)).isEqualTo(1);
Account6 account2 = new Account6();
account2.setUserName("michael");
account2.setAge(5);
try {
mapper.insertSelective(account2);
// 没有 ID插入失败
Assert.fail();
} catch (Exception e) {
assertThat(e.getCause()).isInstanceOf(InvocationTargetException.class)
.asInstanceOf(InstanceOfAssertFactories.type(InvocationTargetException.class))
.extracting(i -> i.getTargetException().getMessage())
.asString()
.contains("NULL not allowed for column \"ID\"");
}
List<Account6> list = mapper.selectAll();
assertThat(list).hasSize(3);
}
}

View File

@ -0,0 +1,99 @@
package com.mybatisflex.test;
import com.mybatisflex.core.MybatisFlexBootstrap;
import com.mybatisflex.core.audit.AuditManager;
import com.mybatisflex.core.audit.ConsoleMessageCollector;
import com.mybatisflex.core.datasource.DataSourceKey;
import com.mybatisflex.core.keygen.KeyGeneratorFactory;
import org.apache.ibatis.logging.stdout.StdOutImpl;
import org.assertj.core.api.WithAssertions;
import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import com.mybatisflex.mapper.Account7Mapper;
import org.springframework.jdbc.datasource.embedded.EmbeddedDatabase;
import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseBuilder;
import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseType;
import java.util.List;
import java.util.OptionalLong;
/**
* @author mofan
* @date 2023/12/4 23:06
*/
public class Account7Test implements WithAssertions {
private EmbeddedDatabase dataSource;
private Account7Mapper mapper;
private static final String DATA_SOURCE_KEY = "generate_key";
@BeforeClass
public static void enableAudit() {
AuditManager.setAuditEnable(true);
AuditManager.setMessageCollector(new ConsoleMessageCollector());
// 设置主键生成策略
KeyGeneratorFactory.register("test", new TestKeyGenerator());
}
@Before
public void init() {
this.dataSource = new EmbeddedDatabaseBuilder()
.setType(EmbeddedDatabaseType.H2)
.addScript("generate_key_schema.sql")
.addScript("generate_key_data.sql")
.build();
MybatisFlexBootstrap bootstrap = new MybatisFlexBootstrap()
.setDataSource(DATA_SOURCE_KEY, this.dataSource)
.setLogImpl(StdOutImpl.class)
.addMapper(Account7Mapper.class)
.start();
DataSourceKey.use(DATA_SOURCE_KEY);
mapper = bootstrap.getMapper(Account7Mapper.class);
}
@After
public void destroy() {
this.dataSource.shutdown();
DataSourceKey.clear();
}
/**
* issues https://gitee.com/mybatis-flex/mybatis-flex/issues/I88TX1
*/
@Test
public void testGiteeIssue_I88TX1() {
List<Account7> list = this.mapper.selectAll();
OptionalLong maxIdOpt = list.stream().mapToLong(Account7::getId).max();
if (!maxIdOpt.isPresent()) {
Assert.fail();
}
Account7 account1 = new Account7();
account1.setId(maxIdOpt.getAsLong() + 1);
account1.setUserName("michael");
account1.setAge(5);
int result1 = this.mapper.insert(account1);
assertThat(result1).isEqualTo(1);
assertThat(account1).extracting(Account7::getId).isEqualTo(3L);
Account7 account2 = new Account7();
account2.setUserName("michael");
account2.setAge(5);
int result2 = this.mapper.insert(account2);
assertThat(result2).isEqualTo(1);
assertThat(account2).extracting(Account7::getId)
.asInstanceOf(LONG)
// 组件通过时间戳 / 1000 获取
.isGreaterThanOrEqualTo(10000L);
}
}

View File

@ -18,47 +18,69 @@ package com.mybatisflex.test;
import com.mybatisflex.core.MybatisFlexBootstrap;
import com.mybatisflex.core.audit.AuditManager;
import com.mybatisflex.core.audit.ConsoleMessageCollector;
import com.mybatisflex.core.audit.MessageCollector;
import com.mybatisflex.core.datasource.DataSourceKey;
import com.mybatisflex.mapper.Account5Mapper;
import org.assertj.core.api.WithAssertions;
import org.junit.After;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Ignore;
import org.junit.Test;
import org.springframework.jdbc.datasource.embedded.EmbeddedDatabase;
import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseBuilder;
import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseType;
import javax.sql.DataSource;
public class AccountInsertWithArrayAttrTest implements WithAssertions {
public class AccountInsertWithArrayAttrTestStarter {
private Account5Mapper accountMapper;
private EmbeddedDatabase dataSource;
public static void main(String[] args) {
DataSource dataSource = new EmbeddedDatabaseBuilder()
private static final String DATA_SOURCE_KEY = "data05";
@BeforeClass
public static void enableAudit() {
AuditManager.setAuditEnable(true);
AuditManager.setMessageCollector(new ConsoleMessageCollector());
}
@Before
public void init() {
this.dataSource = new EmbeddedDatabaseBuilder()
.setType(EmbeddedDatabaseType.H2)
.addScript("schema05.sql")
.addScript("data05.sql")
.build();
MybatisFlexBootstrap bootstrap = MybatisFlexBootstrap.getInstance()
.setDataSource(dataSource)
MybatisFlexBootstrap bootstrap = new MybatisFlexBootstrap()
.setDataSource(DATA_SOURCE_KEY, dataSource)
.addMapper(Account5Mapper.class)
.start();
//开启审计功能
AuditManager.setAuditEnable(true);
DataSourceKey.use(DATA_SOURCE_KEY);
//设置 SQL 审计收集器
MessageCollector collector = new ConsoleMessageCollector();
AuditManager.setMessageCollector(collector);
//
// String insertSql = "INSERT INTO `tb_account`(`id`,`user_name`, `age`, `birthday`, `options`, `is_delete`, `data_scope`) VALUES (?, ?, ?, ?, ?, ?, ?)";
// Db.insertBySql(insertSql,null,"lisi",null,null,null,null,null);
accountMapper = bootstrap.getMapper(Account5Mapper.class);
}
@After
public void destroy() {
this.dataSource.shutdown();
DataSourceKey.clear();
}
Account5Mapper accountMapper = bootstrap.getMapper(Account5Mapper.class);
@Test
@Ignore
public void testInsertWithPk() {
Account5 account = new Account5();
account.setId(3L);
account.setUserName("lisi");
account.setDataScope(new Long[]{1L, 2L});
accountMapper.insertWithPk(account, false);
// todo argument type mismatch
Account5 result = accountMapper.selectOneById(3L);
assertThat(result).isNotNull()
.extracting(Account5::getUserName, Account5::getDataScope)
.containsExactly("lisi", new Long[]{1L, 2L});
}
}

View File

@ -19,8 +19,7 @@ import com.mybatisflex.core.FlexGlobalConfig;
import com.mybatisflex.core.MybatisFlexBootstrap;
import com.mybatisflex.core.audit.AuditManager;
import com.mybatisflex.core.audit.ConsoleMessageCollector;
import com.mybatisflex.core.audit.MessageCollector;
import com.mybatisflex.core.keygen.KeyGeneratorFactory;
import com.mybatisflex.core.datasource.DataSourceKey;
import com.mybatisflex.core.mybatis.Mappers;
import com.mybatisflex.core.query.If;
import com.mybatisflex.core.query.QueryWrapper;
@ -28,83 +27,96 @@ import com.mybatisflex.core.row.DbChain;
import com.mybatisflex.core.update.UpdateChain;
import com.mybatisflex.core.update.UpdateWrapper;
import com.mybatisflex.core.util.UpdateEntity;
import com.mybatisflex.mapper.Account6Mapper;
import com.mybatisflex.mapper.Account7Mapper;
import com.mybatisflex.mapper.ArticleMapper;
import org.apache.ibatis.logging.stdout.StdOutImpl;
import org.junit.Assert;
import org.assertj.core.api.WithAssertions;
import org.assertj.core.data.Index;
import org.junit.After;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Ignore;
import org.junit.Test;
import org.springframework.jdbc.datasource.embedded.EmbeddedDatabase;
import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseBuilder;
import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseType;
import javax.sql.DataSource;
import java.util.List;
import java.util.Objects;
import static com.mybatisflex.test.table.AccountTableDef.ACCOUNT;
import static com.mybatisflex.test.table.ArticleTableDef.ARTICLE;
public class AccountTester {
public class AccountNativeTest implements WithAssertions {
static AccountMapper accountMapper;
static ArticleMapper articleMapper;
private EmbeddedDatabase dataSource;
private AccountMapper accountMapper;
private ArticleMapper articleMapper;
private static final String DATA_SOURCE_KEY = "auto_increment";
@BeforeClass
public static void init() {
DataSource dataSource = new EmbeddedDatabaseBuilder()
public static void enableAudit() {
AuditManager.setAuditEnable(true);
AuditManager.setMessageCollector(new ConsoleMessageCollector());
FlexGlobalConfig.getDefaultConfig().setLogicDeleteColumn("is_delete");
}
@Before
public void init() {
this.dataSource = new EmbeddedDatabaseBuilder()
.setType(EmbeddedDatabaseType.H2)
.addScript("schema.sql")
.addScript("data.sql")
.addScript("auto_increment_key_schema.sql")
.addScript("auto_increment_key_data.sql")
.build();
FlexGlobalConfig.getDefaultConfig()
.setLogicDeleteColumn("is_delete");
KeyGeneratorFactory.register("test", new TestKeyGenerator());
MybatisFlexBootstrap bootstrap = MybatisFlexBootstrap.getInstance()
.setDataSource(dataSource)
MybatisFlexBootstrap bootstrap = new MybatisFlexBootstrap()
.setDataSource(DATA_SOURCE_KEY, this.dataSource)
.setLogImpl(StdOutImpl.class)
.addMapper(AccountMapper.class)
.addMapper(Account6Mapper.class)
.addMapper(Account7Mapper.class)
.addMapper(ArticleMapper.class)
.start();
//开启审计功能
AuditManager.setAuditEnable(true);
//设置 SQL 审计收集器
MessageCollector collector = new ConsoleMessageCollector();
AuditManager.setMessageCollector(collector);
DataSourceKey.use(DATA_SOURCE_KEY);
accountMapper = bootstrap.getMapper(AccountMapper.class);
articleMapper = bootstrap.getMapper(ArticleMapper.class);
}
@After
public void destroy() {
this.dataSource.shutdown();
DataSourceKey.clear();
}
@Test
public void testLogicDelete() {
accountMapper.selectAll().forEach(System.out::println);
List<Account> accounts = accountMapper.selectAll();
assertThat(accounts).hasSize(2)
.extracting(Account::getId, Account::getUserName)
.containsExactly(tuple(1L, "张*"), tuple(2L, "王麻**叔"));
}
@Test
public void testExecutor() {
DbChain.table("tb_account")
List<Account> accountList = DbChain.table("tb_account")
.select(ACCOUNT.ALL_COLUMNS)
.from(ACCOUNT)
.where(ACCOUNT.ID.ge(1))
.listAs(Account.class)
.forEach(System.out::println);
.listAs(Account.class);
assertThat(accountList).hasSize(2)
.extracting(Account::getId, Account::getUserName)
.containsExactly(tuple(1L, "张*"), tuple(2L, "王麻**叔"));
AccountMapper accountBaseMapper = (AccountMapper) Mappers.ofEntityClass(Account.class);
AccountMapper accountMapper = Mappers.ofMapperClass(AccountMapper.class);
System.out.println(">>>>> : " + (accountBaseMapper == accountMapper));
assertThat(accountBaseMapper).isSameAs(accountMapper);
Account account = accountBaseMapper.selectOneById(1);
System.out.println(">>>> account: " + account);
assertThat(account).isNotNull()
.extracting(Account::getId, Account::getUserName)
.containsExactly(1L, "张*");
}
@Test
@ -113,15 +125,19 @@ public class AccountTester {
queryWrapper.where(Account::getId).ge(100)
.and(Account::getUserName).like("michael")
.or(Account::getUserName).like(null, If::notNull);
System.out.println(queryWrapper.toSQL());
String expectSql = "SELECT * FROM WHERE `id` >= 100 AND `user_name` LIKE '%michael%'";
assertThat(queryWrapper.toSQL()).isEqualTo(expectSql);
}
@Test
public void testTenant() {
QueryWrapper queryWrapper = QueryWrapper.create();
// id >= 1
queryWrapper.where(Account::getId).ge(1);
List<Account> accounts = accountMapper.selectListByQuery(queryWrapper);
System.out.println(accounts);
assertThat(accounts).hasSize(2)
.extracting(Account::getId, Account::getUserName)
.containsExactly(tuple(1L, "张*"), tuple(2L, "王麻**叔"));
}
@Test
@ -130,38 +146,56 @@ public class AccountTester {
queryWrapper.from(ARTICLE)
.leftJoin(ACCOUNT).on(ARTICLE.ACCOUNT_ID.eq(ACCOUNT.ID))
.where(ARTICLE.ID.ge(1));
String expectSql = "SELECT * FROM `tb_article` " +
"LEFT JOIN `tb_account` ON `tb_article`.`account_id` = `tb_account`.`id` " +
"WHERE `tb_article`.`id` >= 1";
assertThat(queryWrapper.toSQL()).isEqualTo(expectSql);
List<Article> accounts = articleMapper.selectListByQuery(queryWrapper);
System.out.println(accounts);
assertThat(accounts).hasSize(3)
.extracting(Article::getId, Article::getAccountId, Article::getTitle)
.containsExactly(tuple(1L, 1L, "标题1"), tuple(2L, 2L, "标题2"), tuple(3L, 1L, "标题3"));
}
/**
* issues https://gitee.com/mybatis-flex/mybatis-flex/issues/I7QD29
*/
@Test
public void testLeftJoinSelfForLogicDelete() {
public void testGiteeIssue_I7QD29() {
QueryWrapper queryWrapper = QueryWrapper.create();
queryWrapper.from(ACCOUNT)
.leftJoin(ACCOUNT).as("a1").on(ACCOUNT.ID.eq(ARTICLE.ACCOUNT_ID))
.leftJoin(ACCOUNT).as("a2").on(ACCOUNT.ID.eq(ARTICLE.ACCOUNT_ID))
.leftJoin(ARTICLE).as("a1").on(ACCOUNT.ID.eq(ARTICLE.ACCOUNT_ID))
.leftJoin(ARTICLE).as("a2").on(ACCOUNT.ID.eq(ARTICLE.ACCOUNT_ID))
.where(ACCOUNT.ID.ge(1));
List<Article> accounts = articleMapper.selectListByQuery(queryWrapper);
System.out.println(accounts);
String expectSql = "SELECT * FROM `tb_account` " +
"LEFT JOIN `tb_article` AS `a1` ON `tb_account`.`id` = `a1`.`account_id` AND `a1`.`is_delete` = 0 " +
"LEFT JOIN `tb_article` AS `a2` ON `tb_account`.`id` = `a1`.`account_id` AND `a2`.`is_delete` = 0 " +
"WHERE `tb_account`.`id` >= 1";
assertThat(queryWrapper.toSQL()).isEqualTo(expectSql);
assertThat(accounts).hasSize(9);
}
/**
* issues https://gitee.com/mybatis-flex/mybatis-flex/issues/I7VAG8
*/
@Test
public void testLeftJoinSelectWithIgnoreColumn() {
public void testGiteeIssue_I7VAG8() {
QueryWrapper queryWrapper = QueryWrapper.create();
queryWrapper
.select(ACCOUNT.ID, ACCOUNT.AGE, ARTICLE.TITLE)
.from(ACCOUNT)
.leftJoin(ARTICLE).on(ACCOUNT.ID.eq(ARTICLE.ACCOUNT_ID))
.where(ACCOUNT.ID.ge(1));
String expectSql = "SELECT `tb_account`.`id` AS `account_id`, `tb_account`.`age` AS `my_age`, `tb_article`.`title` " +
"FROM `tb_account` " +
"LEFT JOIN `tb_article` " +
"ON `tb_account`.`id` = `tb_article`.`account_id` " +
"WHERE `tb_account`.`id` >= 1";
assertThat(queryWrapper.toSQL()).isEqualTo(expectSql);
List<Account> accounts = accountMapper.selectListByQuery(queryWrapper);
System.out.println(accounts);
assertThat(accounts).hasSize(2)
.extracting(Account::getId, Account::getAge, Account::getTitle)
.containsExactly(tuple(1L, 18, "标题1"), tuple(2L, 19, "标题2"));
}
@ -169,15 +203,17 @@ public class AccountTester {
* issues https://gitee.com/mybatis-flex/mybatis-flex/issues/I7RE0J
*/
@Test
public void testUpdateByUpdateWrapper() {
@Ignore
public void testGiteeIssue_I7RE0J() {
Account account = new Account();
account.setId(1L);
account = UpdateWrapper.of(account)
.set(Account::getId, 1)
.set(Account::getAge, 20)
//设置 Ignore 字段会被自动忽略
// 设置 Ignore 字段会被自动忽略
.setRaw(Account::getTitle, "xxxx")
.toEntity();
// todo title not found
accountMapper.update(account);
}
@ -185,19 +221,27 @@ public class AccountTester {
@Test
public void testSelectAsToDTO() {
QueryWrapper queryWrapper = QueryWrapper.create();
// queryWrapper.select(ACCOUNT.ALL_COLUMNS,ARTICLE.TITLE.as(AccountDTO::getPermissions))
queryWrapper.select(ACCOUNT.ALL_COLUMNS, ACCOUNT.USER_NAME.as(AccountDTO::getTestOtherField))
// queryWrapper.select(ACCOUNT.ALL_COLUMNS)
.from(ACCOUNT).leftJoin(ARTICLE).on(ACCOUNT.ID.eq(ARTICLE.ACCOUNT_ID));
.from(ACCOUNT)
.leftJoin(ARTICLE).on(ACCOUNT.ID.eq(ARTICLE.ACCOUNT_ID));
String expectSql = "SELECT `tb_account`.*, `tb_account`.`user_name` AS `test_other_field` " +
"FROM `tb_account` " +
"LEFT JOIN `tb_article` " +
"ON `tb_account`.`id` = `tb_article`.`account_id`";
assertThat(queryWrapper.toSQL()).isEqualTo(expectSql);
List<AccountDTO> accountDTOS = accountMapper.selectListByQueryAs(queryWrapper, AccountDTO.class);
System.out.println(accountDTOS);
assertThat(accountDTOS).hasSize(2)
.extracting(AccountDTO::getId, AccountDTO::getUserName)
.containsExactly(tuple(1L, "张*"), tuple(2L, "王麻**叔"));
}
@Test
public void testUpdate1() {
List<Account> accounts = accountMapper.selectAll();
System.out.println(accounts);
assertThat(accounts).hasSize(2)
.extracting(Account::getId, Account::getAge)
.containsExactly(tuple(1L, 18), tuple(2L, 19));
Account account = UpdateEntity.of(Account.class, 1);
@ -209,46 +253,54 @@ public class AccountTester {
accounts = accountMapper.selectAll();
System.out.println(accounts);
assertThat(accounts).hasSize(2)
.filteredOn(i -> Objects.equals(1L, i.getId()))
.extracting(Account::getUserName, Account::getAge)
.containsExactly(tuple("**si", 19));
}
@Test
public void testUpdate2() {
List<Account> accounts = accountMapper.selectAll();
System.out.println(accounts);
assertThat(accounts).hasSize(2)
.filteredOn(i -> Objects.equals(1L, i.getId()))
.extracting(Account::getUserName)
.containsExactly("张*");
UpdateChain.of(Account.class)
.set(Account::getUserName, "zhangsan123")
// .leftJoin(ARTICLE).on(ARTICLE.ACCOUNT_ID.eq(ACCOUNT.ID))
.where(Account::getId).eq(1)
// .and(ARTICLE.ID.ge(0))
.limit(1)
.remove();
accounts = accountMapper.selectAll();
System.out.println(accounts);
assertThat(accounts).hasSize(1)
.singleElement()
.extracting(Account::getId, Account::getUserName)
.containsExactly(2L, "王麻**叔");
}
/**
* https://gitee.com/mybatis-flex/mybatis-flex/issues/I7L6DF
*/
@Test
public void testInsertSelectiveWithPk() {
public void testGiteeIssue_I7L6DF() {
List<Account> accounts = accountMapper.selectAll();
System.out.println(accounts);
assertThat(accounts).hasSize(2);
Account account = new Account();
account.setId(4L);
account.setUserName("test04");
int rows = accountMapper.insertSelectiveWithPk(account);
System.out.println(rows);
assertThat(rows).isEqualTo(1);
accounts = accountMapper.selectAll();
System.out.println(accounts);
assertThat(accounts).hasSize(3)
.filteredOn(i -> Objects.equals(4L, i.getId()))
.extracting(Account::getUserName)
.containsExactly("te***4");
}
@ -258,65 +310,14 @@ public class AccountTester {
account.setUserName("michael");
Account newAccount = UpdateWrapper.of(account)
// .setRaw("birthday", "now()")
// .setRaw(ACCOUNT.BIRTHDAY, "now()")
.setRaw(Account::getBirthday, "now()")
.toEntity();
accountMapper.insert(newAccount);
Account result = accountMapper.selectOneByEntityId(newAccount);
assertThat(result).isNotNull()
.extracting(Account::getId, Account::getUserName, Account::getBirthday)
.contains(3L, Index.atIndex(0))
.contains("mi****l", Index.atIndex(1))
.allMatch(Objects::nonNull);
}
/**
* issues https://gitee.com/mybatis-flex/mybatis-flex/issues/I873OZ
*/
@Test
public void testInsertSelective01() {
Account6Mapper mapper = MybatisFlexBootstrap.getInstance()
.getMapper(Account6Mapper.class);
Account6 account1 = new Account6();
account1.setId(1L);
account1.setUserName("michael");
account1.setAge(5);
Assert.assertEquals(mapper.insertSelective(account1), 1);
Account6 account2 = new Account6();
// account2.setId(1L); 不设置主键
account2.setUserName("michael");
account2.setAge(5);
Assert.assertEquals(mapper.insertSelective(account2), 1);
}
/**
* issues https://gitee.com/mybatis-flex/mybatis-flex/issues/I88TX1
*/
@Test
public void testInsertWithEntityId() {
Account7Mapper mapper = MybatisFlexBootstrap.getInstance()
.getMapper(Account7Mapper.class);
Account7 account1 = new Account7();
account1.setId(1L);
account1.setUserName("michael");
account1.setAge(5);
int result1 = mapper.insert(account1);
Assert.assertEquals(result1, 1);
Account7 account2 = new Account7();
// account2.setId(1L); 不设置主键自动生成主键
account2.setUserName("michael");
account2.setAge(5);
int result2 = mapper.insert(account2);
Assert.assertEquals(result2, 1);
}
}

View File

@ -16,19 +16,23 @@
package com.mybatisflex.test;
import com.mybatisflex.core.MybatisFlexBootstrap;
import com.mybatisflex.core.audit.AuditManager;
import com.mybatisflex.core.audit.ConsoleMessageCollector;
import com.mybatisflex.core.row.DbChain;
import com.mybatisflex.core.row.Row;
import com.mybatisflex.core.row.RowKey;
import com.mybatisflex.core.row.RowUtil;
import lombok.SneakyThrows;
import org.assertj.core.api.WithAssertions;
import org.junit.After;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import org.springframework.jdbc.datasource.embedded.EmbeddedDatabase;
import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseBuilder;
import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseType;
import javax.sql.DataSource;
import java.sql.Timestamp;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
@ -36,73 +40,102 @@ import java.util.List;
* @author 王帅
* @since 2023-07-23
*/
public class DbChainTest {
public class DbChainTest implements WithAssertions {
private static final String[] PROPERTIES = new String[]{"ID", "USER_NAME", "AGE", "BIRTHDAY"};
private static final SimpleDateFormat DATE_FORMAT = new SimpleDateFormat("yyyy-MM-dd");
private static final String ENVIRONMENT_ID = "db_chain";
private EmbeddedDatabase database;
@BeforeClass
public static void init() {
DataSource dataSource = new EmbeddedDatabaseBuilder()
.setType(EmbeddedDatabaseType.H2)
.addScript("schema.sql")
.addScript("data.sql")
.build();
MybatisFlexBootstrap.getInstance()
.setDataSource(dataSource)
.start();
public static void enableAudit() {
AuditManager.setAuditEnable(true);
AuditManager.setMessageCollector(new ConsoleMessageCollector());
}
@Before
public void init() {
this.database = new EmbeddedDatabaseBuilder()
.setType(EmbeddedDatabaseType.H2)
.addScript("auto_increment_key_schema.sql")
.addScript("auto_increment_key_data.sql")
.build();
// Environment environment = new Environment(ENVIRONMENT_ID, new JdbcTransactionFactory(), this.database);
// FlexConfiguration configuration = new FlexConfiguration(environment);
// configuration.addMapper(RowMapper.class);
// FlexGlobalConfig flexGlobalConfig = new FlexGlobalConfig();
// flexGlobalConfig.setConfiguration(configuration);
// flexGlobalConfig.setSqlSessionFactory(new DefaultSqlSessionFactory(configuration));
// FlexGlobalConfig.setConfig(environment.getId(), flexGlobalConfig, false);
}
@After
public void destroy() {
// 用一个销毁一个保证每个测试方法的都是一个新的
this.database.shutdown();
}
@Test
public void testSave() {
Date birthday = new Date();
boolean saved = DbChain.table("tb_account")
.setId(RowKey.AUTO)
.set("user_name", "王帅")
.set("age", 18)
.set("birthday", new Date())
.set("birthday", birthday)
.save();
assertThat(saved).isTrue();
Row row = DbChain.table("tb_account")
.where("user_name = ?", "王帅")
.one();
System.out.println(row);
assertThat(row).extracting(PROPERTIES)
.containsExactly(3, "王帅", 18, new Timestamp(birthday.getTime()));
}
@Test
@SneakyThrows
public void testUpdate() {
boolean updated = DbChain.table("tb_account")
.setId(RowKey.AUTO, 1)
.set("age", 1000)
.updateById();
assertThat(updated).isTrue();
Row row = DbChain.table("tb_account")
.where("id = ?", 1)
.one();
System.out.println(row);
Date date = DATE_FORMAT.parse("2020-01-11");
assertThat(row).extracting(PROPERTIES)
.containsExactly(1, "张三", 1000, new Timestamp(date.getTime()));
}
@Test
@SneakyThrows
public void testRemove() {
DbChain.table("tb_account")
.where("id = ?", 1)
.remove();
long count = DbChain.table("tb_account").count();
assertThat(count).isEqualTo(1L);
List<Row> tb_account = DbChain.table("tb_account").list();
RowUtil.printPretty(tb_account);
System.out.println(">>>>>>testRemove count: " + count);
assertThat(tb_account).hasSize(1)
.extracting(PROPERTIES)
.containsExactly(tuple(2, "王麻子叔叔", 19, new Timestamp(DATE_FORMAT.parse("2021-03-21").getTime())));
}
@Test
public void testList() {
DbChain.table("tb_account")
.list()
.forEach(System.out::println);
List<Row> list = DbChain.table("tb_account").list();
assertThat(list).hasSize(2)
.extracting("ID", "USER_NAME")
.containsExactly(tuple(1, "张三"), tuple(2, "王麻子叔叔"));
}
}

View File

@ -18,12 +18,16 @@ package com.mybatisflex.test;
import com.mybatisflex.core.FlexGlobalConfig;
import com.mybatisflex.core.MybatisFlexBootstrap;
import com.mybatisflex.core.datasource.DataSourceKey;
import org.apache.ibatis.logging.stdout.StdOutImpl;
import org.assertj.core.api.WithAssertions;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.springframework.jdbc.datasource.embedded.EmbeddedDatabase;
import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseBuilder;
import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseType;
import javax.sql.DataSource;
import java.util.Date;
/**
@ -34,33 +38,51 @@ import java.util.Date;
*/
public class ListenerTest implements WithAssertions {
// 注册父类接口监听器
// @Test
public void onInsertInterface() throws Exception {
DataSource dataSource = new EmbeddedDatabaseBuilder()
private static final String DATA_SOURCE_KEY = "listener";
private AccountMapper accountMapper;
private EmbeddedDatabase dataSource;
@Before
public void init() {
dataSource = new EmbeddedDatabaseBuilder()
.setType(EmbeddedDatabaseType.H2)
.addScript("schema.sql")
.addScript("auto_increment_key_schema.sql")
.build();
// 注册全局监听器
FlexGlobalConfig defaultConfig = FlexGlobalConfig.getDefaultConfig();
// age < 0将其设置为 0
defaultConfig.registerInsertListener(new AgeHandleListener(), AgeAware.class);
MybatisFlexBootstrap bootstrap = MybatisFlexBootstrap.getInstance()
MybatisFlexBootstrap bootstrap = new MybatisFlexBootstrap()
.setLogImpl(StdOutImpl.class)
.setDataSource(dataSource)
.setDataSource(DATA_SOURCE_KEY, dataSource)
.addMapper(AccountMapper.class)
.start();
AccountMapper accountMapper = bootstrap.getMapper(AccountMapper.class);
DataSourceKey.use(DATA_SOURCE_KEY);
accountMapper = bootstrap.getMapper(AccountMapper.class);
}
@After
public void destroy() {
this.dataSource.shutdown();
DataSourceKey.clear();
}
@Test
public void onInsertInterface() {
Account account = new Account();
account.setAge(-2);
account.setUserName("on insert");
account.setBirthday(new Date());
Date birthday = new Date();
account.setBirthday(birthday);
accountMapper.insert(account);
Account one = accountMapper.selectOneById(account.getId());
System.out.println(one);
// assertThat(one.getAge()).isEqualTo(1);
assertThat(one).isNotNull()
.extracting(Account::getId, Account::getUserName, Account::getAge, Account::getBirthday)
.containsExactly(1L, "on******t", 0, birthday);
}
}

View File

@ -0,0 +1,173 @@
/*
* Copyright (c) 2022-2023, Mybatis-Flex (fuhai999@gmail.com).
* <p>
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* <p>
* http://www.apache.org/licenses/LICENSE-2.0
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.mybatisflex.test;
import com.fasterxml.jackson.databind.json.JsonMapper;
import com.mybatisflex.core.MybatisFlexBootstrap;
import com.mybatisflex.core.audit.AuditManager;
import com.mybatisflex.core.audit.ConsoleMessageCollector;
import com.mybatisflex.core.datasource.DataSourceKey;
import com.mybatisflex.core.paginate.Page;
import com.mybatisflex.core.query.QueryWrapper;
import com.mybatisflex.core.relation.RelationManager;
import com.mybatisflex.test.relation.mapper.AccountMapper;
import com.mybatisflex.test.relation.mapper.BookMapper;
import com.mybatisflex.test.relation.mapper.MenuMapper;
import com.mybatisflex.test.relation.onetoone.Account;
import com.mybatisflex.test.relation.onetoone.AccountDTO;
import com.mybatisflex.test.relation.onetoone.Book;
import com.mybatisflex.test.relation.onetoone.Menu;
import lombok.SneakyThrows;
import net.javacrumbs.jsonunit.assertj.JsonAssertions;
import org.apache.commons.io.FileUtils;
import org.assertj.core.api.WithAssertions;
import org.junit.After;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import org.springframework.core.io.ClassPathResource;
import org.springframework.jdbc.datasource.embedded.EmbeddedDatabase;
import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseBuilder;
import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseType;
import java.nio.charset.StandardCharsets;
import java.util.List;
import static com.mybatisflex.test.relation.onetoone.table.MenuTableDef.MENU;
public class RelationsTest implements WithAssertions {
private AccountMapper accountMapper;
private BookMapper bookMapper;
private MenuMapper menuMapper;
private EmbeddedDatabase dataSource;
private static final String DATA_SOURCE_KEY = "relation-onetoone";
private static final JsonMapper JSON_MAPPER = JsonMapper.builder().build();
@BeforeClass
public static void enableAudit() {
AuditManager.setAuditEnable(true);
AuditManager.setMessageCollector(new ConsoleMessageCollector());
}
@Before
public void init() {
dataSource = new EmbeddedDatabaseBuilder()
.setType(EmbeddedDatabaseType.H2)
.addScript("relation/onetoone/schema.sql")
.addScript("relation/onetoone/data.sql")
.build();
MybatisFlexBootstrap bootstrap = MybatisFlexBootstrap.getInstance()
.setDataSource(DATA_SOURCE_KEY, dataSource)
.addMapper(AccountMapper.class)
.addMapper(BookMapper.class)
.addMapper(MenuMapper.class)
.start();
DataSourceKey.use(DATA_SOURCE_KEY);
accountMapper = bootstrap.getMapper(AccountMapper.class);
bookMapper = bootstrap.getMapper(BookMapper.class);
menuMapper = bootstrap.getMapper(MenuMapper.class);
}
@After
public void destroy() {
this.dataSource.shutdown();
DataSourceKey.clear();
}
@Test
@SneakyThrows
public void testOneToOne() {
List<com.mybatisflex.test.relation.onetoone.Account> accounts = accountMapper.selectAllWithRelations();
assertThat(accounts).hasSize(5);
assertRelationResult(accounts, "relation/result/account-relation-result.json");
}
@Test
public void testManyToOne() {
List<Book> books = bookMapper.selectAll();
assertThat(books).hasSize(6)
.extracting(Book::getId)
.containsExactly(1L, 2L, 3L, 4L, 5L, 6L);
RelationManager.queryRelations(bookMapper, books);
assertRelationResult(books, "relation/result/book-relation-result.json");
}
@Test
public void testManyToMany1() {
List<com.mybatisflex.test.relation.onetoone.Account> accounts = accountMapper.selectAll();
assertThat(accounts).hasSize(5)
.extracting(Account::getId)
.containsExactly(1L, 2L, 3L, 4L, 5L);
RelationManager.queryRelations(accountMapper, accounts);
assertRelationResult(accounts, "relation/result/account-relation-result.json");
}
@Test
public void testAsDto() {
List<com.mybatisflex.test.relation.onetoone.AccountDTO> accounts = accountMapper.selectListWithRelationsByQueryAs(QueryWrapper.create(), AccountDTO.class);
assertRelationResult(accounts, "relation/result/accountDto-relation-result.json");
}
@Test
public void testMenu() {
QueryWrapper qw = QueryWrapper.create();
qw.where(MENU.PARENT_ID.eq(0));
List<Menu> menus = menuMapper.selectListWithRelationsByQuery(qw);
assertRelationResult(menus, "relation/result/menu-relation-result.json");
}
@Test
public void testMenuIgnoreParent() {
QueryWrapper qw = QueryWrapper.create();
qw.where(MENU.PARENT_ID.eq(0));
RelationManager.addIgnoreRelations("parent");
List<Menu> menus = menuMapper.selectListWithRelationsByQuery(qw);
assertRelationResult(menus, "relation/result/menu-relation-ignore-parent-result.json");
}
@Test
public void testPaginate() {
Page<Account> accountPage = accountMapper.paginateWithRelations(1, 2, QueryWrapper.create());
assertRelationResult(accountPage.getRecords(), "relation/result/account-page-relation-result.json");
}
private void assertRelationResult(Object object, String classPath) {
String resultJson = writeObject2String(object);
String expectJson = getFileAsString(classPath);
JsonAssertions.assertThatJson(resultJson).isEqualTo(expectJson);
}
@SneakyThrows
private String writeObject2String(Object object) {
return JSON_MAPPER.writeValueAsString(object);
}
@SneakyThrows
private String getFileAsString(String classPath) {
ClassPathResource resource = new ClassPathResource(classPath);
return FileUtils.readFileToString(resource.getFile(), StandardCharsets.UTF_8);
}
}

View File

@ -19,76 +19,104 @@ import com.mybatisflex.annotation.KeyType;
import com.mybatisflex.core.MybatisFlexBootstrap;
import com.mybatisflex.core.audit.AuditManager;
import com.mybatisflex.core.audit.ConsoleMessageCollector;
import com.mybatisflex.core.datasource.DataSourceKey;
import com.mybatisflex.core.keygen.KeyGenerators;
import com.mybatisflex.core.query.QueryWrapper;
import com.mybatisflex.core.row.Db;
import com.mybatisflex.core.row.Row;
import com.mybatisflex.core.row.RowKey;
import com.mybatisflex.core.row.RowUtil;
import org.apache.ibatis.logging.stdout.StdOutImpl;
import org.assertj.core.api.WithAssertions;
import org.junit.After;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import org.springframework.jdbc.datasource.embedded.EmbeddedDatabase;
import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseBuilder;
import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseType;
import javax.sql.DataSource;
import java.util.List;
import static com.mybatisflex.test.relation.onetoone.table.AccountTableDef.ACCOUNT;
public class RowTestStarter {
public class RowTest implements WithAssertions {
private static final String DATA_SOURCE_KEY = "row";
private EmbeddedDatabase dataSource;
@BeforeClass
public static void init() {
DataSource dataSource = new EmbeddedDatabaseBuilder()
public static void enableAudit() {
AuditManager.setAuditEnable(true);
AuditManager.setMessageCollector(new ConsoleMessageCollector());
}
@Before
public void init() {
dataSource = new EmbeddedDatabaseBuilder()
.setType(EmbeddedDatabaseType.H2)
.addScript("schema_row.sql")
.addScript("data_row.sql")
.build();
MybatisFlexBootstrap.getInstance()
.setDataSource(dataSource)
new MybatisFlexBootstrap().setDataSource(DATA_SOURCE_KEY, dataSource)
.setLogImpl(StdOutImpl.class)
.start();
AuditManager.setAuditEnable(true);
AuditManager.setMessageCollector(new ConsoleMessageCollector());
DataSourceKey.use(DATA_SOURCE_KEY);
}
@After
public void destroy() {
this.dataSource.shutdown();
DataSourceKey.clear();
}
@Test
public void testSetRaw(){
public void testSetRaw() {
Row row = new Row();
row.set("user_name","michael");
row.setRaw("birthday","now()");
row.set("user_name", "michael");
row.setRaw("birthday", "now()");
Db.insert("tb_account",row);
Db.insert("tb_account", row);
List<Row> rowList = Db.selectAll("tb_account");
RowUtil.printPretty(rowList);
assertThat(rowList).hasSize(3)
.extracting("USER_NAME")
.containsOnly("张三", "王麻子叔叔", "michael");
// 插入的数据没有 id
assertThat(row).doesNotContainKey("id");
}
@Test
public void testCustomRowKey(){
public void testCustomRowKey() {
RowKey rowKey = RowKey.of("id", KeyType.Generator, KeyGenerators.flexId);
Row row = Row.ofKey(rowKey);
row.set("user_name","michael");
row.setRaw("birthday","now()");
row.set("user_name", "michael");
row.setRaw("birthday", "now()");
Db.insert("tb_account",row);
Db.insert("tb_account", row);
List<Row> rowList = Db.selectAll("tb_account");
RowUtil.printPretty(rowList);
assertThat(rowList).hasSize(3)
.extracting("USER_NAME")
.containsOnly("张三", "王麻子叔叔", "michael");
// 指定了主键生成策略 ID
assertThat(row).containsKey("id")
.extracting("id")
.isInstanceOf(Long.class);
}
//https://gitee.com/mybatis-flex/mybatis-flex/issues/I7W7HQ
// https://gitee.com/mybatis-flex/mybatis-flex/issues/I7W7HQ
@Test
public void testRow01(){
public void testGiteeIssue_I7W7HQ() {
QueryWrapper qw = QueryWrapper.create().select("id, MAX(`tb_account`.`age`)")
.groupBy("id")
.from(ACCOUNT);
List<Row> rowList = Db.selectListByQuery(qw);
RowUtil.printPretty(rowList);
assertThat(rowList).hasSize(2)
.extracting("MAX(TB_ACCOUNT.AGE)")
.containsOnly(18, 19);
}
}

View File

@ -19,50 +19,66 @@ package com.mybatisflex.test;
import com.mybatisflex.core.MybatisFlexBootstrap;
import com.mybatisflex.core.audit.AuditManager;
import com.mybatisflex.core.audit.ConsoleMessageCollector;
import com.mybatisflex.core.audit.MessageCollector;
import com.mybatisflex.core.datasource.DataSourceKey;
import com.mybatisflex.core.query.QueryChain;
import com.mybatisflex.core.update.UpdateChain;
import lombok.SneakyThrows;
import org.apache.ibatis.logging.stdout.StdOutImpl;
import org.assertj.core.api.WithAssertions;
import org.junit.After;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import org.springframework.jdbc.datasource.embedded.EmbeddedDatabase;
import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseBuilder;
import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseType;
import javax.sql.DataSource;
import java.text.SimpleDateFormat;
import java.util.Collections;
import java.util.List;
import static com.mybatisflex.test.table.AccountTableDef.ACCOUNT;
import static com.mybatisflex.test.table.ArticleTableDef.ARTICLE;
public class UpdateChainTest {
public class UpdateChainTest implements WithAssertions {
static AccountMapper accountMapper;
private AccountMapper accountMapper;
private EmbeddedDatabase dataSource;
private static final String DATA_SOURCE_KEY = "ds2";
@BeforeClass
public static void init() {
DataSource dataSource = new EmbeddedDatabaseBuilder()
public static void enableAudit() {
AuditManager.setAuditEnable(true);
AuditManager.setMessageCollector(new ConsoleMessageCollector());
}
@Before
public void init() {
this.dataSource = new EmbeddedDatabaseBuilder()
.setType(EmbeddedDatabaseType.H2)
.addScript("schema.sql")
.addScript("data.sql")
.build();
MybatisFlexBootstrap bootstrap = MybatisFlexBootstrap.getInstance()
.setDataSource(dataSource)
MybatisFlexBootstrap bootstrap = new MybatisFlexBootstrap()
.setDataSource(DATA_SOURCE_KEY, this.dataSource)
.setLogImpl(StdOutImpl.class)
.addMapper(AccountMapper.class)
.start();
//开启审计功能
AuditManager.setAuditEnable(true);
//设置 SQL 审计收集器
MessageCollector collector = new ConsoleMessageCollector();
AuditManager.setMessageCollector(collector);
DataSourceKey.use(DATA_SOURCE_KEY);
accountMapper = bootstrap.getMapper(AccountMapper.class);
}
@After
public void destroy() {
this.dataSource.shutdown();
DataSourceKey.clear();
}
@Test
@SneakyThrows
public void testUpdateChain() {
UpdateChain.of(Account.class)
.set(Account::getUserName, "张三")
@ -71,7 +87,19 @@ public class UpdateChainTest {
.update();
Account account = accountMapper.selectOneById(1);
System.out.println(account);
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
String toParse = "2020-01-11";
assertThat(account).isNotNull()
.extracting(
Account::getUserName, Account::getAge,
Account::getSex, Account::getBirthday,
Account::getOptions, Account::getDelete,
Account::getArticles, Account::getTitle)
.containsExactly(
"张*", 19,
SexEnum.TYPE1, format.parse(toParse),
Collections.singletonMap("key", "value1"), false,
Collections.emptyList(), null);
}
@Test
@ -82,9 +110,10 @@ public class UpdateChainTest {
.and(Account::getAge).eq(18)
.update();
QueryChain.of(accountMapper)
.list()
.forEach(System.out::println);
List<Account> list = QueryChain.of(accountMapper).list();
assertThat(list).hasSize(2)
.extracting(Account::getId, Account::getUserName, Account::getAge)
.containsExactly(tuple(1L, "张*", 18), tuple(2L, "王麻**叔", 19));
}
@Test
@ -96,7 +125,11 @@ public class UpdateChainTest {
.where(ACCOUNT.ID.eq(4))
.toSQL();
System.out.println(sql);
String expectSQL = "UPDATE `tb_account` " +
"LEFT JOIN `tb_article` AS `ar` ON `tb_account`.`id` = `ar`.`account_id` " +
"SET `age` = 18 , `accountId` = 4 WHERE `id` = 4";
assertThat(sql).isEqualTo(expectSQL);
}
}

View File

@ -0,0 +1,11 @@
-- 设置主键自增时,初始化数据不显式设置 ID
INSERT INTO tb_account(`user_name`, `age`, `sex`, `birthday`, `options`, `is_delete`)
VALUES ('张三', 18, 0,'2020-01-11', '{"key":"value1"}',0),
('王麻子叔叔', 19, 1, '2021-03-21', '{"key":"value2"}',0);
INSERT INTO tb_article(`account_id`, `title`, `content`, `is_delete`)
VALUES (1, '标题1', '内容1',0),
(2, '标题2', '内容2',0),
(1, '标题3', '内容3',0);

View File

@ -0,0 +1,22 @@
CREATE TABLE IF NOT EXISTS `tb_account`
(
`id` INTEGER AUTO_INCREMENT,
`user_name` VARCHAR(100),
`age` Integer,
`sex` Integer,
`birthday` DATETIME,
`options` VARCHAR(1024),
`is_delete` Integer,
PRIMARY KEY(id)
);
CREATE TABLE IF NOT EXISTS `tb_article`
(
`id` INTEGER AUTO_INCREMENT,
`account_id` Integer,
`title` VARCHAR(100),
`content` text,
`is_delete` Integer,
PRIMARY KEY(id)
);

View File

@ -0,0 +1,5 @@
-- 使用主键生成器生成主键,初始化数据时仍然手动设置 ID
INSERT INTO tb_account7(`id`, `user_name`, `age`)
VALUES (1, '张三', 18),
(2, '王麻子叔叔', 19);

View File

@ -0,0 +1,7 @@
CREATE TABLE IF NOT EXISTS `tb_account7`
(
`id` INTEGER,
`user_name` VARCHAR(100),
`age` Integer,
PRIMARY KEY(id)
);

View File

@ -0,0 +1,5 @@
-- 没有主键生成策略,手动插入 ID
INSERT INTO tb_account6(`id`, `user_name`, `age`)
VALUES (1, '张三', 18),
(2, '王麻子叔叔', 19);

View File

@ -0,0 +1,7 @@
CREATE TABLE IF NOT EXISTS `tb_account6`
(
`id` INTEGER,
`user_name` VARCHAR(100),
`age` Integer,
PRIMARY KEY(id)
);

View File

@ -1,11 +1,11 @@
CREATE TABLE IF NOT EXISTS `tb_account`
(
`id` INTEGER auto_increment,
`id` INTEGER,
`user_name` VARCHAR(100),
`age` Integer
`age` Integer,
PRIMARY KEY(id)
);
CREATE TABLE IF NOT EXISTS `tb_idcard`
(
`account_id` Integer,
@ -13,39 +13,38 @@ CREATE TABLE IF NOT EXISTS `tb_idcard`
`content` text
);
CREATE TABLE IF NOT EXISTS `tb_idcard_mapping`
(
`account_id` Integer,
`idcard_id` Integer
);
CREATE TABLE IF NOT EXISTS `tb_book`
(
`id` INTEGER auto_increment,
`id` INTEGER,
`account_id` Integer,
`title` VARCHAR(100),
`content` text
`content` text,
PRIMARY KEY(id)
);
CREATE TABLE IF NOT EXISTS `tb_role`
(
`id` INTEGER auto_increment,
`name` VARCHAR(100)
`id` INTEGER,
`name` VARCHAR(100),
PRIMARY KEY(id)
);
CREATE TABLE IF NOT EXISTS `tb_role_mapping`
(
`account_id` INTEGER ,
`account_id` INTEGER ,
`role_id` INTEGER
);
CREATE TABLE IF NOT EXISTS `tb_menu`
(
`id` INTEGER auto_increment,
`parent_id` INTEGER,
`name` VARCHAR(100)
`id` INTEGER,
`parent_id` INTEGER,
`name` VARCHAR(100),
PRIMARY KEY(id)
);

View File

@ -0,0 +1,85 @@
[
{
"id": 1,
"userName": "孙悟空",
"age": 18,
"idCard": null,
"books": [],
"roles": [],
"rolesMap": {
"3": {
"id": 3,
"name": "角色3",
"accounts": [
{
"id": 1,
"userName": "孙悟空",
"age": 18,
"idCard": null,
"books": [],
"roles": [],
"rolesMap": null
},
{
"id": 2,
"userName": "猪八戒",
"age": 19,
"idCard": null,
"books": [],
"roles": [],
"rolesMap": null
}
]
}
}
},
{
"id": 2,
"userName": "猪八戒",
"age": 19,
"idCard": null,
"books": [],
"roles": [],
"rolesMap": {
"2": {
"id": 2,
"name": "角色2",
"accounts": [
{
"id": 2,
"userName": "猪八戒",
"age": 19,
"idCard": null,
"books": [],
"roles": [],
"rolesMap": null
}
]
},
"3": {
"id": 3,
"name": "角色3",
"accounts": [
{
"id": 1,
"userName": "孙悟空",
"age": 18,
"idCard": null,
"books": [],
"roles": [],
"rolesMap": null
},
{
"id": 2,
"userName": "猪八戒",
"age": 19,
"idCard": null,
"books": [],
"roles": [],
"rolesMap": null
}
]
}
}
}
]

View File

@ -0,0 +1,112 @@
[
{
"id": 1,
"userName": "孙悟空",
"age": 18,
"idCard": null,
"books": [],
"roles": [],
"rolesMap": {
"3": {
"id": 3,
"name": "角色3",
"accounts": [
{
"id": 1,
"userName": "孙悟空",
"age": 18,
"idCard": null,
"books": [],
"roles": [],
"rolesMap": null
},
{
"id": 2,
"userName": "猪八戒",
"age": 19,
"idCard": null,
"books": [],
"roles": [],
"rolesMap": null
}
]
}
}
},
{
"id": 2,
"userName": "猪八戒",
"age": 19,
"idCard": null,
"books": [],
"roles": [],
"rolesMap": {
"2": {
"id": 2,
"name": "角色2",
"accounts": [
{
"id": 2,
"userName": "猪八戒",
"age": 19,
"idCard": null,
"books": [],
"roles": [],
"rolesMap": null
}
]
},
"3": {
"id": 3,
"name": "角色3",
"accounts": [
{
"id": 1,
"userName": "孙悟空",
"age": 18,
"idCard": null,
"books": [],
"roles": [],
"rolesMap": null
},
{
"id": 2,
"userName": "猪八戒",
"age": 19,
"idCard": null,
"books": [],
"roles": [],
"rolesMap": null
}
]
}
}
},
{
"id": 3,
"userName": "沙和尚",
"age": 19,
"idCard": null,
"books": [],
"roles": [],
"rolesMap": null
},
{
"id": 4,
"userName": "六耳猕猴",
"age": 19,
"idCard": null,
"books": [],
"roles": [],
"rolesMap": null
},
{
"id": 5,
"userName": "王麻子叔叔",
"age": 19,
"idCard": null,
"books": [],
"roles": [],
"rolesMap": null
}
]

View File

@ -0,0 +1,155 @@
[
{
"id": 1,
"userName": "孙悟空",
"age": 18,
"idCard": null,
"books": [],
"roles": [
{
"id": 1,
"name": "角色1",
"accounts": [
{
"id": 1,
"userName": "孙悟空",
"age": 18,
"idCard": null,
"books": [],
"roles": [],
"rolesMap": null
},
{
"id": 2,
"userName": "猪八戒",
"age": 19,
"idCard": null,
"books": [],
"roles": [],
"rolesMap": null
}
]
},
{
"id": 3,
"name": "角色3",
"accounts": [
{
"id": 1,
"userName": "孙悟空",
"age": 18,
"idCard": null,
"books": [],
"roles": [],
"rolesMap": null
},
{
"id": 2,
"userName": "猪八戒",
"age": 19,
"idCard": null,
"books": [],
"roles": [],
"rolesMap": null
}
]
}
]
},
{
"id": 2,
"userName": "猪八戒",
"age": 19,
"idCard": null,
"books": [],
"roles": [
{
"id": 1,
"name": "角色1",
"accounts": [
{
"id": 1,
"userName": "孙悟空",
"age": 18,
"idCard": null,
"books": [],
"roles": [],
"rolesMap": null
},
{
"id": 2,
"userName": "猪八戒",
"age": 19,
"idCard": null,
"books": [],
"roles": [],
"rolesMap": null
}
]
},
{
"id": 2,
"name": "角色2",
"accounts": [
{
"id": 2,
"userName": "猪八戒",
"age": 19,
"idCard": null,
"books": [],
"roles": [],
"rolesMap": null
}
]
},
{
"id": 3,
"name": "角色3",
"accounts": [
{
"id": 1,
"userName": "孙悟空",
"age": 18,
"idCard": null,
"books": [],
"roles": [],
"rolesMap": null
},
{
"id": 2,
"userName": "猪八戒",
"age": 19,
"idCard": null,
"books": [],
"roles": [],
"rolesMap": null
}
]
}
]
},
{
"id": 3,
"userName": "沙和尚",
"age": 19,
"idCard": null,
"books": [],
"roles": null
},
{
"id": 4,
"userName": "六耳猕猴",
"age": 19,
"idCard": null,
"books": [],
"roles": null
},
{
"id": 5,
"userName": "王麻子叔叔",
"age": 19,
"idCard": null,
"books": [],
"roles": null
}
]

View File

@ -0,0 +1,138 @@
[
{
"id": 1,
"accountId": 1,
"title": "图书1",
"content": "内容1",
"account": {
"id": 1,
"userName": "孙悟空",
"age": 18,
"idCard": null,
"books": [],
"roles": [],
"rolesMap": {
"3": {
"id": 3,
"name": "角色3",
"accounts": []
}
}
}
},
{
"id": 2,
"accountId": 2,
"title": "图书2",
"content": "内容2",
"account": {
"id": 2,
"userName": "猪八戒",
"age": 19,
"idCard": null,
"books": [],
"roles": [],
"rolesMap": {
"2": {
"id": 2,
"name": "角色2",
"accounts": []
},
"3": {
"id": 3,
"name": "角色3",
"accounts": []
}
}
}
},
{
"id": 3,
"accountId": 1,
"title": "图书3",
"content": "内容2",
"account": {
"id": 1,
"userName": "孙悟空",
"age": 18,
"idCard": null,
"books": [],
"roles": [],
"rolesMap": {
"3": {
"id": 3,
"name": "角色3",
"accounts": []
}
}
}
},
{
"id": 4,
"accountId": 1,
"title": "图书4",
"content": "内容2",
"account": {
"id": 1,
"userName": "孙悟空",
"age": 18,
"idCard": null,
"books": [],
"roles": [],
"rolesMap": {
"3": {
"id": 3,
"name": "角色3",
"accounts": []
}
}
}
},
{
"id": 5,
"accountId": 1,
"title": "图书5",
"content": "内容2",
"account": {
"id": 1,
"userName": "孙悟空",
"age": 18,
"idCard": null,
"books": [],
"roles": [],
"rolesMap": {
"3": {
"id": 3,
"name": "角色3",
"accounts": []
}
}
}
},
{
"id": 6,
"accountId": 2,
"title": "图书6",
"content": "内容2",
"account": {
"id": 2,
"userName": "猪八戒",
"age": 19,
"idCard": null,
"books": [],
"roles": [],
"rolesMap": {
"2": {
"id": 2,
"name": "角色2",
"accounts": []
},
"3": {
"id": 3,
"name": "角色3",
"accounts": []
}
}
}
}
]

View File

@ -0,0 +1,90 @@
[
{
"id": 1,
"parentId": 0,
"name": "顶级菜单1",
"parent": null,
"children": [
{
"id": 4,
"parentId": 1,
"name": "子菜单4",
"parent": null,
"children": [
{
"id": 9,
"parentId": 4,
"name": "子菜单9",
"parent": null,
"children": null
},
{
"id": 10,
"parentId": 4,
"name": "子菜单10",
"parent": null,
"children": null
}
]
},
{
"id": 5,
"parentId": 1,
"name": "子菜单5",
"parent": null,
"children": [
{
"id": 11,
"parentId": 5,
"name": "子菜单11",
"parent": null,
"children": null
},
{
"id": 12,
"parentId": 5,
"name": "子菜单12",
"parent": null,
"children": null
}
]
}
]
},
{
"id": 2,
"parentId": 0,
"name": "顶级菜单2",
"parent": null,
"children": []
},
{
"id": 3,
"parentId": 0,
"name": "顶级菜单3",
"parent": null,
"children": [
{
"id": 6,
"parentId": 3,
"name": "子菜单6",
"parent": null,
"children": []
},
{
"id": 7,
"parentId": 3,
"name": "子菜单7",
"parent": null,
"children": []
},
{
"id": 8,
"parentId": 3,
"name": "子菜单8",
"parent": null,
"children": []
}
]
}
]

View File

@ -0,0 +1,120 @@
[
{
"id": 1,
"parentId": 0,
"name": "顶级菜单1",
"parent": null,
"children": [
{
"id": 4,
"parentId": 1,
"name": "子菜单4",
"parent": {
"id": 1,
"parentId": 0,
"name": "顶级菜单1",
"parent": null,
"children": null
},
"children": [
{
"id": 9,
"parentId": 4,
"name": "子菜单9",
"parent": null,
"children": null
},
{
"id": 10,
"parentId": 4,
"name": "子菜单10",
"parent": null,
"children": null
}
]
},
{
"id": 5,
"parentId": 1,
"name": "子菜单5",
"parent": {
"id": 1,
"parentId": 0,
"name": "顶级菜单1",
"parent": null,
"children": null
},
"children": [
{
"id": 11,
"parentId": 5,
"name": "子菜单11",
"parent": null,
"children": null
},
{
"id": 12,
"parentId": 5,
"name": "子菜单12",
"parent": null,
"children": null
}
]
}
]
},
{
"id": 2,
"parentId": 0,
"name": "顶级菜单2",
"parent": null,
"children": []
},
{
"id": 3,
"parentId": 0,
"name": "顶级菜单3",
"parent": null,
"children": [
{
"id": 6,
"parentId": 3,
"name": "子菜单6",
"parent": {
"id": 3,
"parentId": 0,
"name": "顶级菜单3",
"parent": null,
"children": null
},
"children": []
},
{
"id": 7,
"parentId": 3,
"name": "子菜单7",
"parent": {
"id": 3,
"parentId": 0,
"name": "顶级菜单3",
"parent": null,
"children": null
},
"children": []
},
{
"id": 8,
"parentId": 3,
"name": "子菜单8",
"parent": {
"id": 3,
"parentId": 0,
"name": "顶级菜单3",
"parent": null,
"children": null
},
"children": []
}
]
}
]

View File

@ -24,8 +24,32 @@
<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
<commons-io.version>2.15.1</commons-io.version>
<org.projectlombok.version>1.18.30</org.projectlombok.version>
<!-- 高版本基于 JDK17勿动 -->
<json-unit-assertj.version>2.38.0</json-unit-assertj.version>
</properties>
<dependencies>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>${commons-io.version}</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>${org.projectlombok.version}</version>
</dependency>
<dependency>
<groupId>net.javacrumbs.json-unit</groupId>
<artifactId>json-unit-assertj</artifactId>
<version>${json-unit-assertj.version}</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
@ -36,6 +60,11 @@
<source>1.8</source>
<target>1.8</target>
<annotationProcessorPaths>
<path>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>${org.projectlombok.version}</version>
</path>
<path>
<groupId>com.mybatis-flex</groupId>
<artifactId>mybatis-flex-processor</artifactId>