Note: if you want to use this repository,please keep the version above
1.1.0.RELEASE
.
project-version | reactor-bom | r2dbc-bom | spring-boot |
---|---|---|---|
1.1.x |
>= 2020.0.17 |
Arabba-SRxxx |
2.6.x |
1.2.x |
>= 2020.0.21 |
Borca-SR1 |
>=2.7.0 && <=2.7.x |
The
[Borca-SR1,~)
is based onr2dbc-spi
[0.9.1.RELEASE] Sincer2dbc-spi
is changed in1.0.0.RELEASE
,Borca-SR1
's future versions need to be re-adapted.
This project has met the general business usage scenarios, including:
- 1 . Parameter parsing and mapping
- 2 . One-to-many associative relationships for result mapping
- 3 . Result mapping for one-to-one relationships
- 4 . Returning a generated key
- 5 . generated key by nested query (
@SelectKey
/<selectKey>
) - 6 . Manual transaction operation
- 7 . Adaptation of parameter binding placeholders for different r2dbc drivers
- 8 . SpringBoot transaction Integration
- 9 . Supported drivers:
- mysql
- h2
- mssql
- postgresql
- oracle
- This project is aimed to adapt mybatis to reactive project (aka WebFlux/Reactor3)
mybatis-r2dbc
module is inspired by linux-china/mybatis-r2dbc and based onmybatis3
's original source codemybatis-generator
module is used to adaptmybatis-dynamic-sql
to reactive project- Support SpringBoot AutoConfiguration,
@R2dbcMapperScan
/@R2dbcMapperScans
for scan@Mapper
, Spring XML bean config . - Support Spring's Transaction.
- Unsupported mybatis3 feature:
- ❌ 1 . mybatis-plugin
- ❌ 2 . multi resultSet and
resultOrdered = true
in mapper.XML - ❌ 3 . nested query with multi SQL
⚠️ 4 . blocking java type (aka: InputStream .eg)
⚠️ Mapper Method's return type only supportFlux<T>
/Mono<T>
/Mono<Void>
/Flux<Void>
, and not supportvoid
- Using Reactor's Context and dynamic proxy to implement Transaction
- More detail, please see source code and test suits, tests use MySQL database with
test-prepare.sql
schema setup - It has been piloted in a small scale within my company, and any bugs found will be updated at any time
-
⚠️ When usinguseGeneratedKeys="true"
ininsert
label of mapper-xml, thekeyColumns="xxxx"
must be set- 1 . The
JDBC driver
'sConnection
only provides a method defined asPreparedStatement prepareStatement(String sql, int autoGeneratedKeys) throws SQLException;
, the second parameter of this method indicates whether auto returns generatedKeys - 2 . The
R2DBC driver
'sStatement
does not provide any method to return generatedKeys automatically, the Statement only provides a method defined asStatement returnGeneratedValues(String... columns)
to return generatedKeys,the columns is not nullable , so the key column name must be specific. - Reference:
- 1 . The
-
⚠️ r2dbc-mysql
driver- when calling
Row#<T> T get(int index, Class<T> type)
,with jdbcType isBIGINT
and javaType isLong.class
- the driver will occur an exception, because the driver is deeply bound to
BitInteger.class
,and can't cast toLong.class
- MySQL-JDBC driver and
r2dbc-mariadb
driver don't have this issue - possible link r2dbc-mysql/issues/177
- This might be fixed in the next release of the driver
- when calling
-
⚠️ resultOrdered
inselect
label of mapper-xml- Since r2dbc only return single
Result
(ResultSet
in JDBC) , so I change theresultOrdered
process for hold result data for nested result mapping in order to reduce the cache generated when nested-result-map processing as much as possible - When using
resultOrdered="true"
inselect
label of mapper-xml, theDefaultReactiveResultHandler
only hold the related result data for nested result mapping. - When using
resultOrdered="false"
inselect
label of mapper-xml (by default), theDefaultReactiveResultHandler
hold all related result data for nested result mapping.
- Since r2dbc only return single
- dependency
<dependencies>
<dependency>
<groupId>pro.chenggang</groupId>
<artifactId>mybatis-r2dbc</artifactId>
<version>${latest.version}</version>
</dependency>
<dependency>
<groupId>pro.chenggang</groupId>
<artifactId>mybatis-r2dbc-generator</artifactId>
<version>${latest.version}</version>
</dependency>
<dependency>
<groupId>pro.chenggang</groupId>
<artifactId>mybatis-r2dbc-spring</artifactId>
<version>${latest.version}</version>
</dependency>
</dependencies>
- The example distinguish different databases by
reactive-mybatis-support-examples
's branch- mysql
- h2
- mssql
- postgresql
- oracle
- Generate
mybatis-dynamic-sql
Note: the generator is based on
mybatis-generator-core
,therefor the generator is rely onjdbc-driver
- import dependency
<dependencies>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-pool2</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mybatis.dynamic-sql</groupId>
<artifactId>mybatis-dynamic-sql</artifactId>
</dependency>
<dependency>
<groupId>pro.chenggang</groupId>
<artifactId>mybatis-r2dbc-generator</artifactId>
<version>${latest.version}</version>
<scope>test</scope>
</dependency>
</dependencies>
- copy
mybatis-generator.yml
formsource-code/mybatis-reactive-generator/resources/META-INF/mybatis-generator.yml
- modify source database settings in
mybatis-generator.yml
- add a test case or a main method
public class MyBatisGeneratorAction {
/**
* generate through main method
*
* @param args args
*/
public static void main(String[] args) {
String codeAbsoluteLocation = new File("").getAbsolutePath() + "/mybatis-r2dbc-generator";
MybatisDynamicCodeGenerator.withYamlConfiguration()
.customConfigure()
.configureGenerateBasePackage(codeAbsoluteLocation, "pro.chenggang.project.reactive.mybatis.support.generator")
.toGenerator()
.generate();
}
/**
* generate through junit test method
*/
@Test
public void generateWithYamlWithJunitTestMethod() {
MybatisDynamicCodeGenerator.withYamlConfiguration()
.customConfigure()
.applyGenerateBasePackageFromClass(MyBatisGeneratorAction.class)
.toGenerator()
.generate();
}
}
- run the test ,then it will generate the dynamic code ,mapper interface ,mapper xml
- also see
mybatis-reactive-generator
's test cases
- import dependency
<dependencies>
<dependency>
<groupId>org.mariadb</groupId>
<artifactId>r2dbc-mariadb</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-r2dbc</artifactId>
</dependency>
<dependency>
<groupId>org.mybatis.dynamic-sql</groupId>
<artifactId>mybatis-dynamic-sql</artifactId>
<version>${latest.version}</version>
</dependency>
<dependency>
<groupId>pro.chenggang</groupId>
<artifactId>mybatis-r2dbc-spring</artifactId>
<version>${latest.version}</version>
</dependency>
</dependencies>
-
then use in project as usual ,also support
@Transaction
andTransactionalOperator
. -
other details sees the
mybatis-r2dbc-spring
's test cases,the test case include mapper tests and service tests. -
before run the
mybatis-r2dbc-spring
's test cases ,you should executetest_prepare.sql
in the test resources. -
spring-boot-test is not support
@Transaction
in tests ,link Spring Issue -
customize
ConnectionFactoryOptions
@Bean public ConnectionFactoryOptionsCustomizer connectionFactoryOptionsCustomizer() { return connectionFactoryOptionsBuilder -> connectionFactoryOptionsBuilder .option(Option.valueOf("name"), "value"); }
-
customize
R2dbcMybatisConfiguration
@Bean public R2dbcMybatisConfigurationCustomizer r2dbcMybatisConfigurationCustomizer() { return r2dbcMybatisConfiguration -> r2dbcMybatisConfiguration.setLogPrefix("mybatis-log"); }
-
custom mapper scan
- Original
@MapperScan
is replaced with@R2dbcMapperScan
- Original
@MapperScans
is replaced with@R2dbcMapperScans
- Original
-
import dependency
<dependencies> <dependency> <groupId>org.mariadb</groupId> <artifactId>r2dbc-mariadb</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-r2dbc</artifactId> </dependency> <dependency> <groupId>pro.chenggang</groupId> <artifactId>mybatis-r2dbc-spring</artifactId> <version>${latest.version}</version> </dependency> </dependencies>
- then use in project as usual ,also support
@Transaction
andTransactionalOperator
.
- then use in project as usual ,also support