根本简介
Mybatis-Tiny 是什么?Mybatis-Tiny 是一个基于 Mybatis 框架的一层极简的扩大,它旨在应用 DSL 的形式对单表进行 CRUD 操作,相似于 Mybatis-Plus 框架,但它绝不是反复造轮子!区别于别的相似框架(如 Mybatis-Plus、Fluent-Mybatis 等)的实现形式,它采纳一种逆向曲线救国的实现形式,通过较少的代码,极简的扩大实现了相似于他们大多数的性能,齐全满足日常开发中对单表的各种 CRUD 操作。
我的项目地址:https://github.com/penggle/my…
疾速入门
Talk is cheap,show me the code!
-
插入操作
ProductBaseInfo productBase = ...; List<ProductSaleSpec> productSaleSpecs = ...; productBaseInfoMapper.insert(productBase); // 基于 JDBC-Batch 个性的批量插入操作。productSaleSpecMapper.batchUpdate(productSaleSpecs, productSaleSpec -> productSaleSpecMapper.insert(productSaleSpec)); // 打印日志:- ==> Preparing: INSERT INTO t_product_base_info(product_id, product_name, product_url, product_tags, product_type, audit_status, online_status, shop_id, remark, create_time, update_time) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) - ==> Parameters: null, 24 期免息【当天发】Huawei/ 华为 Mate40 5G 手机官网旗舰店 50pro 直降 mate40e 官网 30 副品 4G 鸿蒙副品 30 全网通(String), https://detail.tmall.com/item.htm?id=633658852628(String), ["手机通信","手机","手机"](String), 1(Integer), 0(Integer), 1(Integer), 111212422(Long), null, 2022-04-27 00:43:42(String), 2022-04-27 00:43:42(String) - <== Updates: 1 - ==> Preparing: INSERT INTO t_product_sale_spec(product_id, spec_no, spec_name, spec_index, remark, create_time, update_time) VALUES (?, ?, ?, ?, ?, ?, ?) - ==> Parameters: 1(Long), 101(String), 4G 全网通(String), 1(Integer), null, 2022-04-27 00:43:42(String), 2022-04-27 00:43:42(String) - ==> Parameters: 1(Long), 102(String), 5G 全网通(String), 2(Integer), null, 2022-04-27 00:43:42(String), 2022-04-27 00:43:42(String) - ==> Parameters: 1(Long), 201(String), 亮彩色(String), 1(Integer), null, 2022-04-27 00:43:42(String), 2022-04-27 00:43:42(String) - ==> Parameters: 1(Long), 202(String), 釉红色(String), 2(Integer), null, 2022-04-27 00:43:42(String), 2022-04-27 00:43:42(String) - ==> Parameters: 1(Long), 203(String), 秘银色(String), 3(Integer), null, 2022-04-27 00:43:42(String), 2022-04-27 00:43:42(String) - ==> Parameters: 1(Long), 204(String), 夏日胡杨(String), 4(Integer), null, 2022-04-27 00:43:42(String), 2022-04-27 00:43:42(String) - ==> Parameters: 1(Long), 205(String), 秋日胡杨(String), 5(Integer), null, 2022-04-27 00:43:42(String), 2022-04-27 00:43:42(String) - ==> Parameters: 1(Long), 301(String), 8+128GB(String), 1(Integer), null, 2022-04-27 00:43:42(String), 2022-04-27 00:43:42(String) - ==> Parameters: 1(Long), 302(String), 8+256GB(String), 2(Integer), null, 2022-04-27 00:43:42(String), 2022-04-27 00:43:42(String)
-
更新操作
// 依据 ID 更新 ProductBaseInfo productBase = ...; Map<String,Object> updateColumns1 = MapLambdaBuilder.of(productBase) // 取 productBase 实例中对应字段的值 .with(ProductBaseInfo::getProductName) .with(ProductBaseInfo::getRemark) // 如果 productBase 实例中对应字段的值为空值 (null| 空串 | 空数组 | 空集合) 则取 default 值 "1" .withDefault(ProductBaseInfo::getProductType, 1) // 疏忽 productBase 实例中对应字段的值,只取 override 值 "0" .withOverride(ProductBaseInfo::getAuditStatus, 0) .withOverride(ProductBaseInfo::getOnlineStatus, 0) .withOverride(ProductBaseInfo::getUpdateTime, DateTimeUtils.formatNow()) .build(); productBaseInfoMapper.updateById(productBase.getProductId(), updateColumns1); // 实现了畛域实体的 identity()办法则 productBase.identity()与 productBase.getProductId()是等效的 //productBaseInfoMapper.updateById(productBase.identity(), updateColumns); // 依据条件更新 Map<String,Object> updateColumns2 = MapLambdaBuilder.<ProductBaseInfo>ofEmpty() .withOverride(ProductBaseInfo::getOnlineStatus, 0) .withOverride(ProductBaseInfo::getUpdateTime, DateTimeUtils.formatNow()) .build(); QueryCriteria<ProductBaseInfo> updateCriteria2 = LambdaQueryCriteria.ofSupplier(ProductBaseInfo::new) .eq(ProductBaseInfo::getProductType, 1) .in(ProductBaseInfo::getAuditStatus, 0, 1) .limit(5); productBaseInfoMapper.updateByCriteria(updateCriteria2, updateColumns2); // 批量更新 List<ProductSaleStock> productSaleStocks = ...; String nowTime = DateTimeUtils.formatNow(); productSaleStockMapper.batchUpdate(productSaleStocks, productSaleStock -> {Map<String,Object> updateColumns = MapLambdaBuilder.of(productSaleStock) .withOverride(ProductSaleStock::getSellPrice, productSaleStock.getSellPrice() - productSaleStock.getSellPrice() % 100) .withOverride(ProductSaleStock::getUpdateTime, nowTime) .build(); //new 一个联结主键实例 ID productSaleStockId = new ID() .addKey(ProductSaleStock::getProductId, productSaleStock.getProductId()) .addKey(ProductSaleStock::getProductId, productSaleStock.getSpecNo()); productSaleStockMapper.updateById(productSaleStockId, updateColumns); // 或者实现了畛域实体的 identity()办法,则能够如下间接调用 //productSaleStockMapper.updateById(productSaleStock.identity(), updateColumns); });
-
查问操作
// 依据 ID 查 ProductBaseInfo productBase1 = productBaseInfoMapper.selectById(1L); ProductBaseInfo productBase2 = productBaseInfoMapper.selectById(10L, new QueryColumns(ProductBaseInfo::getProductId, ProductBaseInfo::getProductName, ProductBaseInfo::getAuditStatus, ProductBaseInfo::getOnlineStatus)); ID id = new ID().addKey(ProductSaleSpec::getProductId, 1L).addKey(ProductSaleSpec::getSpecNo, "101"); ProductSaleSpec productSaleSpec = productSaleSpecMapper.selectById(id); // 依据多个 ID 查问 List<ProductBaseInfo> productBases = productBaseInfoMapper.selectListByIds(Arrays.asList(5L, 6L, 7L, 8L, 9L)); // 依据多个联结主键查问实体对象列表 List<ID> ids = new ArrayList<>(); ids.add(new ID().addKey(ProductSaleSpec::getProductId, 1L).addKey(ProductSaleSpec::getSpecNo, "101")); ids.add(new ID().addKey(ProductSaleSpec::getProductId, 1L).addKey(ProductSaleSpec::getSpecNo, "102")); ids.add(new ID().addKey(ProductSaleSpec::getProductId, 1L).addKey(ProductSaleSpec::getSpecNo, "103")); List<ProductSaleSpec> productSaleSpecs = productSaleSpecMapper.selectListByIds(ids); - ==> Preparing: SELECT product_id AS productId, spec_no AS specNo, spec_name AS specName, spec_index AS specIndex, remark AS remark, DATE_FORMAT(create_time, '%Y-%m-%d %T') AS createTime, DATE_FORMAT(update_time, '%Y-%m-%d %T') AS updateTime FROM t_product_sale_spec WHERE (product_id = ? AND spec_no = ?) OR (product_id = ? AND spec_no = ?) OR (product_id = ? AND spec_no = ?) - ==> Parameters: 1(Long), 101(String), 1(Long), 102(String), 1(Long), 103(String) - <== Total: 2 // 依据条件查问 QueryCriteria<ProductSaleSpec> queryCriteria1 = LambdaQueryCriteria.ofSupplier(ProductSaleSpec::new) .eq(ProductSaleSpec::getProductId, 1L) .eq(ProductSaleSpec::getSpecNo, "101"); ProductSaleSpec productSaleSpec = productSaleSpecMapper.selectByCriteria(queryCriteria1); ProductSaleStock queryRequest1 = ...; QueryCriteria<ProductSaleStock> queryCriteria2 = LambdaQueryCriteria.of(queryRequest1) .eq(ProductSaleStock::getProductId) .likeRight(ProductSaleStock::getSpecNo) .between(ProductSaleStock::getStock, queryRequest1.getMinStock(), queryRequest1.getMaxStock()) .orderBy(OrderBy.desc(ProductSaleStock::getSellPrice)); List<ProductSaleStock> productStocks = productSaleStockMapper.selectListByCriteria(queryCriteria2); QueryCriteria<ProductBaseInfo> queryCriteria3 = LambdaQueryCriteria.of(queryRequest2) .and(nestedCriteria -> nestedCriteria.like(ProductBaseInfo::getProductName, "华为") .or().like(ProductBaseInfo::getProductName, "HUAWEI")) .eq(ProductBaseInfo::getProductType) .eq(ProductBaseInfo::getOnlineStatus) .in(ProductBaseInfo::getAuditStatus, queryRequest.getAuditStatuses().toArray()) .orderBy(OrderBy.desc(ProductBaseInfo::getCreateTime)) .dynamic(true); // 主动过滤掉为空值 (null| 空串 | 空数组 | 空集合) 的查问参数 List<ProductBaseInfo> productBases1 = productBaseInfoMapper.selectListByCriteria(queryCriteria3); // 分页查问 1 Page page = Page.of(1, 10); QueryCriteria<ProductBaseInfo> queryCriteria4 = LambdaQueryCriteria.of(queryRequest) .likeRight(ProductBaseInfo::getProductName) .eq(ProductBaseInfo::getProductType) .eq(ProductBaseInfo::getOnlineStatus) .in(ProductBaseInfo::getAuditStatus, queryRequest.getAuditStatuses().toArray()) .orderBy(page.getOrderBys()) .dynamic(true); // 主动过滤掉为空值 (null| 空串 | 空数组 | 空集合) 的查问参数(条件) List<ProductBaseInfo> productBases2 = productBaseInfoMapper.selectPageListByCriteria(queryCriteria4, new RowBounds(page.offset(), page.limit())); // 设置总记录数 page.setTotalRowCount(productBaseInfoMapper.selectPageCountByCriteria(queryCriteria4)); // 分页查问 2(等效与下面) Page page = Page.of(2, 10); List<ProductBaseInfo> productBases2 = EntityMapperHelper.selectEntityObjectListByPage(productBaseInfoMapper, queryCriteria4, page);
-
删除操作
// 依据 ID 删除 productBaseInfoMapper.deleteById(2L); productExtraInfoMapper.deleteById(2L); // 依据条件删除 QueryCriteria<ProductSaleSpec> queryCriteria1 = LambdaQueryCriteria.ofSupplier(ProductSaleSpec::new) .eq(ProductSaleSpec::getProductId, 2L) .limit(5); productSaleSpecMapper.deleteByCriteria(queryCriteria1);
- 更多示例请见:https://github.com/penggle/my…
个性及限度
-
反对繁多主键或联结主键,繁多主键时主键策略反对:IDENTITY(数据库自增的),SEQUENCE(基于序列的),NONE(无,客户端本人设置主键)
反复造轮子的初衷也是被 Mybatis-Plus 只能应用繁多主键给恶心到了
-
到目前为止,Mybatis-Tiny 没有任何可配置的配置项。Mybatis-Tiny 的数据库方言配置与 Mybatis 自身的方言配置统一,即通过 databaseId 来实现方言。也就是说 Mybatis-Tiny 的方言数据库类型取自 Configuration.databaseId 字段,如果应用程序未设置(通过 DatabaseIdProvider 来设置),则 Mybatis-Tiny 会主动设置。
目前 Mybatis-Tiny 反对支流的数据库:
mysql,mariadb,oracle,db2,sqlserver,postgresql,h2,hsql,sqlite,clickhouse
对于非主流数据库,可参照非主流数据库方言反对
-
Entity 实体类是基于注解的(注解类的设计根本与 JPA 的注解标准统一);实体类必须实现
EntityObject
接口,例如:@Table("t_product_base_info") public class ProductBaseInfo implements EntityObject { /** 商品 ID */ @Id(strategy=GenerationType.IDENTITY) private Long productId; /** 商品名称 */ private String productName; ... /** 审核状态:0- 待审核,1- 审核通过,2- 审核不通过 */ private Integer auditStatus; /** 高低架状态:0- 已下架,1- 已上架 */ private Integer onlineStatus; /** 所属店铺 ID */ //shopId 字段在所有 update 操作时不会被更新(不在 update 列中) @Column(updatable=false) private Long shopId; /** 商品备注 */ private String remark; /** 创立工夫 */ //createTime 字段在所有 update 操作时不会被更新(不在 update 列中) @Column(updatable=false, select="DATE_FORMAT({name},'%Y-%m-%d %T')") private String createTime; /** 最近批改工夫 */ @Column(select="DATE_FORMAT({name},'%Y-%m-%d %T')") private String updateTime; // 以下属于辅助字段 /** productType 的查问后果辅助字段 */ @Transient private String productTypeName; /** auditStatus 的查问后果辅助字段 */ @Transient private String auditStatusName; /** onlineStatus 的查问后果辅助字段 */ @Transient private String onlineStatusName; /** auditStatus 的 IN 查问条件辅助字段 */ @Transient private List<Integer> auditStatuses; //getter/setter... /** * 实现该办法是可选的! * * 返回畛域实体的主键值,当存在联结主键时,在 CRUD 时特地有用 * 联结主键(com.penglecode.codeforce.common.domain.ID) */ @Override public Long identity() {return productId;} /** * 实现该办法是可选的! * * 这个办法在所有 SELECT 操作返回后果集前都会由 Mybatis * 插件 DomainObjectQueryInterceptor 主动执行 * * 通过实现该办法来实现诸如枚举 decode 能力 */ @Override public ProductBaseInfo processOutbound() {Optional.ofNullable(ProductTypeEnum.of(productType)).map(ProductTypeEnum::getTypeName).ifPresent(this::setProductTypeName); Optional.ofNullable(ProductAuditStatusEnum.of(auditStatus)).map(ProductAuditStatusEnum::getStatusName).ifPresent(this::setAuditStatusName); Optional.ofNullable(ProductOnlineStatusEnum.of(onlineStatus)).map(ProductOnlineStatusEnum::getStatusName).ifPresent(this::setOnlineStatusName); return this; } }
-
反对基于 Lambda 的 DSL 形式查问是必须的,例如:
ProductBaseInfo queryRequest = ... QueryCriteria<ProductBaseInfo> queryCriteria = LambdaQueryCriteria.of(queryRequest) .likeRight(ProductBaseInfo::getProductName) .eq(ProductBaseInfo::getProductType) .eq(ProductBaseInfo::getOnlineStatus, 1) // 固定某个查问条件值 .in(ProductBaseInfo::getAuditStatus, queryRequest.getAuditStatuses().toArray()) .orderBy(OrderBy.desc(ProductBaseInfo::getCreateTime)) .limit(5) .dynamic(true); // 主动过滤掉空值 (null| 空串 | 空数组 | 空集合) 查问参数; List<ProductBaseInfo> productBases = productBaseInfoMapper.selectListByCriteria(queryCriteria);
-
反对指定 SELECT 返回列、UPDATE 更新列那都是必须的,例如:
// 更新指定列 ProductBaseInfo updateRequest = ... Map<String,Object> updateColumns = MapLambdaBuilder.of(updateRequest) .with(ProductBaseInfo::getProductName) .with(ProductBaseInfo::getRemark) .withDefault(ProductBaseInfo::getProductType, 1) .withOverride(ProductBaseInfo::getAuditStatus, 0) .withOverride(ProductBaseInfo::getOnlineStatus, 0) .withOverride(ProductBaseInfo::getUpdateTime, DateTimeUtils.formatNow()) .build(); productBaseInfoMapper.updateById(updateRequest.identity(), updateColumns); // 查问返回指定列 ProductBaseInfo productBase = productBaseInfoMapper.selectById(1L, new QueryColumns(ProductBaseInfo::getProductId, ProductBaseInfo::getProductName, ProductBaseInfo::getAuditStatus, ProductBaseInfo::getOnlineStatus));
-
自带基于 RowBounds 的分页性能,不论是调用
BaseEntityMapper#selectPageListByCriteria(QueryCriteria<T>, RowBounds)
还是调用自定义的分页查询方法XxxMapper#selectXxxListByPage(Xxx condition, RowBounds)
都将会被主动分页,例如:public List<ProductBaseInfo> queryProductListByPage(ProductBaseInfo queryRequest, Page page) {QueryCriteria<ProductBaseInfo>> queryCriteria = LambdaQueryCriteria.of(queryRequest) .like(ProductBaseInfo::getProductName) .eq(ProductBaseInfo::getProductType) .eq(ProductBaseInfo::getOnlineStatus) .in(ProductBaseInfo::getAuditStatus, queryRequest.getAuditStatuses().toArray()) .orderBy(page.getOrderBys()) .dynamic(true); // 主动过滤掉为空值 (null| 空串 | 空数组 | 空集合) 的查问参数 List<ProductBaseInfo> productBases = productBaseInfoMapper.selectPageListByCriteria(queryCriteria, new RowBounds(page.offset(), page.limit())); page.setTotalRowCount(productBaseInfoMapper.selectPageCountByCriteria(queryCriteria)); // 设置总记录数 return productBases; }
-
在 Xxx 实体对象的 XxxMapper 中自定义办法必定是能够的:
见 ProductBaseInfoMapper.xml
-
WHERE 条件逻辑嵌套查问仅反对嵌套一层(在单表操作中仅反对一层嵌套曾经能满足绝大多数要求了),例如:
QueryCriteria<ProductBaseInfo> queryCriteria = LambdaQueryCriteria.of(queryRequest) // 仅反对一层嵌套 .and(nestedCriteria -> nestedCriteria.like(ProductBaseInfo::getProductName, "华为") .or().like(ProductBaseInfo::getProductName, "HUAWEI")) .eq(ProductBaseInfo::getProductType) .eq(ProductBaseInfo::getOnlineStatus) .in(ProductBaseInfo::getAuditStatus, queryRequest.getAuditStatuses().toArray()) .orderBy(page.getOrderBys()) .dynamic(true); // 主动过滤掉为空值 (null| 空串 | 空数组 | 空集合) 的查问参数
下面 DSL 语句的理论输入 SQL 如下:
- ==> Preparing: SELECT t.product_id productId, t.product_name productName, t.product_type productType, t.audit_status auditStatus, t.online_status onlineStatus FROM t_product_base_info t WHERE (t.product_name like ? OR t.product_name like ?) AND t.product_type = ? AND t.audit_status in (? , ? , ?) ORDER BY t.create_time DESC LIMIT 0, 10 - ==> Parameters: % 华为 %(String), %HUAWEI%(String), 1(Integer), 0(Integer), 1(Integer), 2(Integer) - <== Total: 10
- 扩大了 Mybatis 的
org.apache.ibatis.executor.Executor
,叫DynamicExecutor
,用于解决在应用 mybatis-spring 框架时在同一个事务中不能切换 ExecutorType 的蛋疼问题(如果你硬要这么做,你将会失去一个异样:’Cannot change the ExecutorType when there is an existing transaction’),这个 Mybatis 自身设计导致(SqlSession 中固化了 ExecutorType),派生出DynamicExecutor
就是来解决这个问题的。 -
仅反对单表 CRUD 操作,不反对多表 JOIN,不反对聚合查问(聚合函数 +GROUP BY)
写这个框架的当初初衷仅仅是为了可能省去编写千篇一律的单表 CRUD(XxxMapper.xml),如果做多表 JOIN 及聚合查问的话,则就失去了应用 Mybatis 的意义了,还不如间接应用 JPA。试想你把一个简单查问通过 DSL 的形式写在 JAVA 代码中,这跟十多年前在 JAVA 或者 JSP 代码中写 SQL 一样,感觉很恶心。
-
仅提供了通用的 BaseEntityMapper,没有提供 BaseService 之类的,BaseEntityMapper 的办法如下:
-
反对对 BaseEntityMapper 的扩大,扩大根底 Mapper 办法是基于约定的,例如存在这样的扩大:
package com.penglecode.codeforce.mybatistiny.examples.extensions; import com.penglecode.codeforce.common.domain.EntityObject; import com.penglecode.codeforce.mybatistiny.dsl.QueryColumns; import com.penglecode.codeforce.mybatistiny.mapper.BaseEntityMapper; import org.apache.ibatis.annotations.Param; /** * 加强性能的 BaseEntityMapper 扩大 * * @author pengpeng * @version 1.0 */ public interface EnhancedBaseMapper<T extends EntityObject> extends BaseEntityMapper<T> { /** * 通过规范 MERGE INTO 语句来进行合并存储 * * @param mergeEntity - 被更新的实体对象 * @param updateColumns - 如果是 update 操作,此参数可指定被更新的列 * @return */ int merge(@Param("mergeEntity") T mergeEntity, @Param("updateColumns") QueryColumns... updateColumns); }
基于约定的,你必须在同样 package 下存在EnhancedBaseMapper.ftl
Freemarker 模板中的预置参数集见 EntityMapperTemplateParameter
OK,这就扩大好了,就是这么简略!
应用形式
Mybatis-Tiny 是一层很薄的货色,没有任何个性化的自定义配置,其仅依赖 Mybatis 自身(不依赖于 Spring 或 SpringBoot)
其 Maven 依赖:
<dependency>
<groupId>io.github.penggle</groupId>
<artifactId>mybatis-tiny-core</artifactId>
<!-- 版本阐明:3.5 指的是基于 Mybatis 3.5.x 版本的意思 -->
<version>3.5</version>
</dependency>
上面列举三种应用场景。
-
只应用 Mybatis(无 Spring、SpringBoot 等大型框架的反对)
// 我不论你其余配置是啥,只有 sqlSessionFactory 实例是通过 DecoratedSqlSessionFactoryBuilder 弄出来的就行了!!!SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new DecoratedSqlSessionFactoryBuilder(); SqlSessionFactory sqlSessionFactory = sqlSessionFactoryBuilder.build(Resources.getResourceAsStream("mybatis-config.xml"));
-
仅与 Spring 框架(精确地说是 mybatis-spring)集成应用
引入相干 Maven 依赖后在配置类上应用注解
@EnableMybatisTiny
即可,例如:import com.penglecode.codeforce.mybatistiny.EnableMybatisTiny; import com.penglecode.codeforce.mybatistiny.core.DecoratedSqlSessionFactoryBuilder; import com.penglecode.codeforce.mybatistiny.examples.BasePackage; import com.zaxxer.hikari.HikariConfig; import com.zaxxer.hikari.HikariDataSource; import org.apache.commons.lang3.ArrayUtils; import org.apache.ibatis.annotations.Mapper; import org.mybatis.spring.SqlSessionFactoryBean; import org.mybatis.spring.annotation.MapperScan; import org.springframework.context.EnvironmentAware; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.PropertySource; import org.springframework.jdbc.datasource.DataSourceTransactionManager; import org.springframework.transaction.annotation.EnableTransactionManagement; @Configuration @EnableMybatisTiny @EnableTransactionManagement(proxyTargetClass=true) @MapperScan(basePackageClasses=BasePackage.class, annotationClass=Mapper.class) @ComponentScan(basePackageClasses=BasePackage.class) @PropertySource(value="classpath:application.yml", factory=YamlPropertySourceFactory.class) public class MybatisConfiguration { @Bean public DataSource dataSource() { Properties properties = ... return new HikariDataSource(new HikariConfig(properties)); } @Bean public SqlSessionFactoryBean sqlSessionFactory(DataSource dataSource) {SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean(); sqlSessionFactoryBean.setDataSource(dataSource); // 这里用不必 Mybatis-Tiny 提供的 DecoratedSqlSessionFactoryBuilder 是可选的 // 如果不必,在 Spring 环境下 Mybatis-Tiny 框架是有应答的补救措施的 //sqlSessionFactoryBean.setSqlSessionFactoryBuilder(new DecoratedSqlSessionFactoryBuilder()); sqlSessionFactoryBean.setConfigLocation(getConfigLocation()); sqlSessionFactoryBean.setTypeAliasesPackage(getTypeAliasesPackage()); sqlSessionFactoryBean.setTypeAliasesSuperType(getTypeAliasesSuperType()); sqlSessionFactoryBean.setMapperLocations(getMapperLocations()); return sqlSessionFactoryBean; } @Bean public DataSourceTransactionManager transactionManager(DataSource dataSource) {return new DataSourceTransactionManager(dataSource); } ... }
-
仅与 SpringBoot 框架(精确地说是 mybatis-spring-boot-starter)集成应用
引入相干 Maven 依赖后在 SpringBoot 启动类上应用注解
@EnableMybatisTiny
即可,例如:import com.penglecode.codeforce.mybatistiny.EnableMybatisTiny; import com.penglecode.codeforce.mybatistiny.examples.BasePackage; import org.springframework.boot.autoconfigure.SpringBootApplication; @EnableMybatisTiny @SpringBootApplication(scanBasePackageClasses=BasePackage.class) public class MybatisTinyExampleApplication {public static void main(String[] args) {SpringApplication.run(MybatisTinyExampleApplication.class, args); } }
mybatis-spring-boot-starter
及DataSource
的配置依旧就好了,application.yml
例如:#SpringBoot 利用的名称 spring: application: name: mybatis-tiny-examples-springboot #Hikari 连接池配置 datasource: hikari: #连接池名字 pool-name: defaultHikariCP #最小闲暇连贯数量 minimum-idle: 5 #闲暇连贯存活最大工夫,默认 600000(10 分钟) idle-timeout: 180000 #连接池最大连接数,默认是 10 maximum-pool-size: 10 #池中连贯的默认主动提交行为,默认值 true auto-commit: true #池中连贯的最长生命周期,0 示意有限生命周期,默认 1800000(30 分钟) max-lifetime: 1800000 #期待来自池的连贯的最大毫秒数,默认 30000(30 秒) connection-timeout: 30000 #连贯测试语句 connection-test-query: SELECT 1 username: root password: 123456 url: jdbc:mysql://127.0.0.1:3306/examples?useUnicode=true&characterEncoding=utf-8&allowMultiQueries=true&serverTimezone=GMT%2B8&useSSL=false&rewriteBatchedStatements=true&useCursorFetch=true #Mybatis-SpringBoot 配置 mybatis: config-location: classpath:config/mybatis/mybatis-config.xml mapper-locations: classpath*:com/penglecode/codeforce/mybatistiny/examples/**/*Mapper.xml type-aliases-package: com.penglecode.codeforce.mybatistiny.examples type-aliases-super-type: com.penglecode.codeforce.common.domain.DomainObject
-
其余框架集成 Mybatis-Tiny
我不论你其余框架具体是啥,只有 sqlSessionFactory 实例是通过 DecoratedSqlSessionFactoryBuilder 弄出来的就行了!!!!